summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPatrick Griffis <pgriffis@igalia.com>2020-08-28 17:25:14 -0500
committerPatrick Griffis <pgriffis@igalia.com>2020-09-19 15:41:25 -0700
commit4217855114d1357eb16c5cf663b2fa09a6e6bd3c (patch)
tree8a745435b39475d061a1474c374b4c2409a25d85
parentc8a211c04ee8f6c87a797f0f756360916e737325 (diff)
downloadlibsoup-4217855114d1357eb16c5cf663b2fa09a6e6bd3c.tar.gz
Remove XMLRPC support
This feature does not appear to be used by any maintained project and in general XMLRPC usage on the internet has gone down. Removing it just reduces complexity and maintainance burden.
-rw-r--r--.gitlab-ci/Dockerfile2
-rw-r--r--docs/reference/client-howto.xml3
-rw-r--r--docs/reference/libsoup-2.4-docs.sgml1
-rw-r--r--docs/reference/libsoup-2.4-sections.txt28
-rw-r--r--docs/reference/meson.build1
-rw-r--r--libsoup/Soup-2.4.metadata5
-rw-r--r--libsoup/include/soup-installed.h1
-rw-r--r--libsoup/meson.build4
-rw-r--r--libsoup/soup.h1
-rw-r--r--libsoup/xmlrpc/soup-xmlrpc.c1478
-rw-r--r--libsoup/xmlrpc/soup-xmlrpc.h95
-rw-r--r--meson.build23
-rw-r--r--tests/httpd.conf.in3
-rw-r--r--tests/meson.build27
-rw-r--r--tests/php.ini.in1
-rw-r--r--tests/xmlrpc-server-test.c381
-rw-r--r--tests/xmlrpc-server.php99
-rw-r--r--tests/xmlrpc-test.c742
18 files changed, 2 insertions, 2893 deletions
diff --git a/.gitlab-ci/Dockerfile b/.gitlab-ci/Dockerfile
index 465fad1d..da3f716c 100644
--- a/.gitlab-ci/Dockerfile
+++ b/.gitlab-ci/Dockerfile
@@ -12,8 +12,6 @@ RUN dnf update -y \
make \
meson \
mod_ssl \
- php \
- php-xmlrpc \
redhat-rpm-config \
samba-winbind-clients \
which \
diff --git a/docs/reference/client-howto.xml b/docs/reference/client-howto.xml
index 1cc190a6..f9e0327c 100644
--- a/docs/reference/client-howto.xml
+++ b/docs/reference/client-howto.xml
@@ -259,8 +259,7 @@ request headers and body of the message:
(Although this is a bad example, because
<application>libsoup</application> actually has convenience methods
for dealing with <link linkend="libsoup-2.4-HTML-Form-Support">HTML
-forms</link>, as well as <link
-linkend="libsoup-2.4-XMLRPC-Support">XML-RPC</link>.)
+forms</link>.)
</para>
<para>
diff --git a/docs/reference/libsoup-2.4-docs.sgml b/docs/reference/libsoup-2.4-docs.sgml
index 36215abe..07da9241 100644
--- a/docs/reference/libsoup-2.4-docs.sgml
+++ b/docs/reference/libsoup-2.4-docs.sgml
@@ -63,7 +63,6 @@
<chapter>
<title>Web Services APIs</title>
<xi:include href="xml/soup-form.xml"/>
- <xi:include href="xml/soup-xmlrpc.xml"/>
<xi:include href="xml/soup-websocket.xml"/>
</chapter>
diff --git a/docs/reference/libsoup-2.4-sections.txt b/docs/reference/libsoup-2.4-sections.txt
index 7760c86b..9c8043a8 100644
--- a/docs/reference/libsoup-2.4-sections.txt
+++ b/docs/reference/libsoup-2.4-sections.txt
@@ -672,34 +672,6 @@ soup_form_request_new_from_multipart
</SECTION>
<SECTION>
-<FILE>soup-xmlrpc</FILE>
-<TITLE>XMLRPC Support</TITLE>
-<SUBSECTION>
-SOUP_XMLRPC_ERROR
-SoupXMLRPCError
-SOUP_XMLRPC_FAULT
-SoupXMLRPCFault
-<SUBSECTION>
-soup_xmlrpc_build_request
-soup_xmlrpc_message_new
-soup_xmlrpc_parse_response
-soup_xmlrpc_variant_new_datetime
-soup_xmlrpc_variant_get_datetime
-<SUBSECTION>
-SoupXMLRPCParams
-soup_xmlrpc_params_free
-soup_xmlrpc_params_parse
-soup_xmlrpc_parse_request
-soup_xmlrpc_build_response
-soup_xmlrpc_build_fault
-soup_xmlrpc_message_set_response
-soup_xmlrpc_message_set_fault
-<SUBSECTION Private>
-soup_xmlrpc_error_quark
-soup_xmlrpc_fault_quark
-</SECTION>
-
-<SECTION>
<FILE>soup-logger</FILE>
<TITLE>SoupLogger</TITLE>
SoupLogger
diff --git a/docs/reference/meson.build b/docs/reference/meson.build
index 724a8d92..eb6ae393 100644
--- a/docs/reference/meson.build
+++ b/docs/reference/meson.build
@@ -40,7 +40,6 @@ ignore_headers = [
'soup-socket-private.h',
'soup-value-utils.h',
'soup-websocket-extension-manager-private.h',
- 'soup-xmlrpc-old.h'
]
mkdb_args = [
diff --git a/libsoup/Soup-2.4.metadata b/libsoup/Soup-2.4.metadata
index c1d3d273..3fd48166 100644
--- a/libsoup/Soup-2.4.metadata
+++ b/libsoup/Soup-2.4.metadata
@@ -5,9 +5,6 @@ AuthDomain
form_* parent="Soup.Form" name="form_(.+)"
form_encode_datalist.form_data_set type_arguments="string"
form_request_new_from_datalist.form_data_set type_arguments="string"
-xmlrpc_* parent="Soup.XMLRPC" name="xmlrpc_(.+)"
-XMLRPCFault errordomain parent="Soup.XMLRPC" name="Fault"
-XMLRPCError parent="Soup.XMLRPC" name="Error"
HTTPVersion.http_* name="http_(.+)"
// Report upstream
@@ -36,7 +33,6 @@ Session*.new_with_options skip=false
URI
.set_query_from_fields skip=false
// uri_host_*.* type="Soup.URI"
-xmlrpc_* skip=false
// Not enough GIR information
Buffer.data type="uint8[]" array_length_field="length"
@@ -44,7 +40,6 @@ MessageBody.data type="uint8[]" array_length_field="length"
Date
.new_from_time_t.when type="time_t"
.to_time_t type="time_t"
-xmlrpc_build_fault printf_format
// Simplify memory management
Buffer
diff --git a/libsoup/include/soup-installed.h b/libsoup/include/soup-installed.h
index cf08bbd2..c1e45b01 100644
--- a/libsoup/include/soup-installed.h
+++ b/libsoup/include/soup-installed.h
@@ -55,7 +55,6 @@ extern "C" {
#include <libsoup/soup-websocket-extension.h>
#include <libsoup/soup-websocket-extension-deflate.h>
#include <libsoup/soup-websocket-extension-manager.h>
-#include <libsoup/soup-xmlrpc.h>
#undef __SOUP_H_INSIDE__
diff --git a/libsoup/meson.build b/libsoup/meson.build
index 2515ba35..8c991547 100644
--- a/libsoup/meson.build
+++ b/libsoup/meson.build
@@ -46,8 +46,6 @@ soup_sources = [
'websocket/soup-websocket-extension-deflate.c',
'websocket/soup-websocket-extension-manager.c',
- 'xmlrpc/soup-xmlrpc.c',
-
'soup-body-input-stream.c',
'soup-body-output-stream.c',
'soup-client-input-stream.c',
@@ -123,8 +121,6 @@ soup_introspection_headers = [
'websocket/soup-websocket-extension-deflate.h',
'websocket/soup-websocket-extension-manager.h',
- 'xmlrpc/soup-xmlrpc.h',
-
'soup-date.h',
'soup-form.h',
'soup-headers.h',
diff --git a/libsoup/soup.h b/libsoup/soup.h
index 254ce582..f0511b93 100644
--- a/libsoup/soup.h
+++ b/libsoup/soup.h
@@ -57,7 +57,6 @@ extern "C" {
#include "websocket/soup-websocket-extension.h"
#include "websocket/soup-websocket-extension-deflate.h"
#include "websocket/soup-websocket-extension-manager.h"
-#include "xmlrpc/soup-xmlrpc.h"
#undef __SOUP_H_INSIDE__
diff --git a/libsoup/xmlrpc/soup-xmlrpc.c b/libsoup/xmlrpc/soup-xmlrpc.c
deleted file mode 100644
index 42dcda9c..00000000
--- a/libsoup/xmlrpc/soup-xmlrpc.c
+++ /dev/null
@@ -1,1478 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * soup-xmlrpc.c: XML-RPC parser/generator
- *
- * Copyright 2007 Red Hat, Inc.
- * Copyright 2007 OpenedHand Ltd.
- * Copyright 2015 Collabora ltd.
- *
- * Author:
- * Eduardo Lima Mitev <elima@igalia.com>
- * Xavier Claessens <xavier.claessens@collabora.com>
- */
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-
-#include <string.h>
-#include <errno.h>
-#include <libxml/tree.h>
-#include "soup-xmlrpc.h"
-#include "soup.h"
-
-static gboolean insert_value (xmlNode *parent, GVariant *value, GError **error);
-
-static gboolean
-insert_array (xmlNode *parent, GVariant *value, GError **error)
-{
- xmlNode *node;
- GVariantIter iter;
- GVariant *child;
-
- node = xmlNewChild (parent, NULL,
- (const xmlChar *)"array", NULL);
- node = xmlNewChild (node, NULL,
- (const xmlChar *)"data", NULL);
-
- g_variant_iter_init (&iter, value);
- while ((child = g_variant_iter_next_value (&iter))) {
- if (!insert_value (node, child, error)) {
- g_variant_unref (child);
- return FALSE;
- }
- g_variant_unref (child);
- }
-
- return TRUE;
-}
-
-static gboolean
-insert_struct_member (xmlNode *parent, GVariant *value, GError **error)
-{
- xmlNode *member;
- GVariant *mname;
- GVariant *mvalue;
- gboolean ret = FALSE;
-
- mname = g_variant_get_child_value (value, 0);
- mvalue = g_variant_get_child_value (value, 1);
-
- if (g_variant_classify (mname) != G_VARIANT_CLASS_STRING) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "Only string keys are supported in dictionaries, got %s",
- g_variant_get_type_string (mname));
- goto fail;
- }
-
- member = xmlNewChild (parent, NULL,
- (const xmlChar *)"member", NULL);
-
- xmlNewTextChild (member, NULL,
- (const xmlChar *)"name",
- (const xmlChar *)g_variant_get_string (mname, NULL));
-
- ret = insert_value (member, mvalue, error);
-
-fail:
- g_variant_unref (mname);
- g_variant_unref (mvalue);
-
- return ret;
-}
-
-static gboolean
-insert_struct (xmlNode *parent, GVariant *value, GError **error)
-{
- xmlNode *struct_node;
- GVariantIter iter;
- GVariant *child;
-
- struct_node = xmlNewChild (parent, NULL,
- (const xmlChar *)"struct", NULL);
-
- g_variant_iter_init (&iter, value);
- while ((child = g_variant_iter_next_value (&iter))) {
- if (!insert_struct_member (struct_node, child, error)) {
- g_variant_unref (child);
- return FALSE;
- }
- g_variant_unref (child);
- }
-
- return TRUE;
-}
-
-static gboolean
-insert_value (xmlNode *parent, GVariant *value, GError **error)
-{
- xmlNode *xvalue;
- const char *type_str = NULL;
- char buf[128];
-
- xvalue = xmlNewChild (parent, NULL, (const xmlChar *)"value", NULL);
-
- switch (g_variant_classify (value)) {
- case G_VARIANT_CLASS_BOOLEAN:
- g_snprintf (buf, sizeof (buf), "%d", g_variant_get_boolean (value));
- type_str = "boolean";
- break;
- case G_VARIANT_CLASS_BYTE:
- g_snprintf (buf, sizeof (buf), "%u", g_variant_get_byte (value));
- type_str = "int";
- break;
- case G_VARIANT_CLASS_INT16:
- g_snprintf (buf, sizeof (buf), "%d", g_variant_get_int16 (value));
- type_str = "int";
- break;
- case G_VARIANT_CLASS_UINT16:
- g_snprintf (buf, sizeof (buf), "%u", g_variant_get_uint16 (value));
- type_str = "int";
- break;
- case G_VARIANT_CLASS_INT32:
- g_snprintf (buf, sizeof (buf), "%d", g_variant_get_int32 (value));
- type_str = "int";
- break;
- case G_VARIANT_CLASS_UINT32:
- g_snprintf (buf, sizeof (buf), "%u", g_variant_get_uint32 (value));
- type_str = "i8";
- break;
- case G_VARIANT_CLASS_INT64:
- g_snprintf (buf, sizeof (buf), "%"G_GINT64_FORMAT, g_variant_get_int64 (value));
- type_str = "i8";
- break;
- case G_VARIANT_CLASS_DOUBLE:
- g_ascii_dtostr (buf, sizeof (buf), g_variant_get_double (value));
- type_str = "double";
- break;
- case G_VARIANT_CLASS_STRING:
- xmlNewTextChild (xvalue, NULL,
- (const xmlChar *)"string",
- (const xmlChar *)g_variant_get_string (value, NULL));
- break;
- case G_VARIANT_CLASS_VARIANT: {
- GVariant *child;
-
- xmlUnlinkNode (xvalue);
- xmlFreeNode (xvalue);
-
- child = g_variant_get_variant (value);
- if (!insert_value (parent, child, error)) {
- g_variant_unref (child);
- return FALSE;
- }
- g_variant_unref (child);
- break;
- }
- case G_VARIANT_CLASS_ARRAY: {
- if (g_variant_is_of_type (value, G_VARIANT_TYPE_BYTESTRING)) {
- char *encoded;
-
- encoded = g_base64_encode (g_variant_get_data (value),
- g_variant_get_size (value));
- xmlNewChild (xvalue, NULL,
- (const xmlChar *)"base64",
- (const xmlChar *)encoded);
- g_free (encoded);
- } else if (g_variant_is_of_type (value, G_VARIANT_TYPE_DICTIONARY)) {
- if (!insert_struct (xvalue, value, error))
- return FALSE;
- } else {
- if (!insert_array (xvalue, value, error))
- return FALSE;
- }
-
- break;
- }
- case G_VARIANT_CLASS_TUPLE: {
- /* Special case for custom types */
- if (g_variant_is_of_type (value, G_VARIANT_TYPE ("(oss)"))) {
- const char *path;
- const char *type;
- const char *v;
-
- g_variant_get (value, "(&o&s&s)", &path, &type, &v);
- if (g_str_equal (path, "/org/gnome/libsoup/ExtensionType")) {
- xmlNewTextChild (xvalue, NULL,
- (const xmlChar *)type,
- (const xmlChar *)v);
- break;
- }
- }
-
- if (!insert_array (xvalue, value, error))
- return FALSE;
- break;
- }
- case G_VARIANT_CLASS_DICT_ENTRY: {
- xmlNode *node;
-
- node = xmlNewChild (xvalue, NULL,
- (const xmlChar *)"struct", NULL);
- if (!insert_struct_member (node, value, error))
- return FALSE;
- break;
- }
- case G_VARIANT_CLASS_HANDLE:
- case G_VARIANT_CLASS_MAYBE:
- case G_VARIANT_CLASS_UINT64:
- case G_VARIANT_CLASS_OBJECT_PATH:
- case G_VARIANT_CLASS_SIGNATURE:
- default:
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "Unsupported type: %s", g_variant_get_type_string (value));
- goto fail;
- }
-
- if (type_str != NULL) {
- xmlNewTextChild (xvalue, NULL,
- (const xmlChar *)type_str,
- (const xmlChar *)buf);
- }
-
- return TRUE;
-
-fail:
- return FALSE;
-}
-
-/**
- * soup_xmlrpc_build_request:
- * @method_name: the name of the XML-RPC method
- * @params: a #GVariant tuple
- * @error: a #GError, or %NULL
- *
- * This creates an XML-RPC methodCall and returns it as a string.
- * This is the low-level method that soup_xmlrpc_message_new() is
- * built on.
- *
- * @params is a #GVariant tuple representing the method parameters.
- *
- * Serialization details:
- * - "a{s*}" and "{s*}" are serialized as &lt;struct&gt;
- * - "ay" is serialized as &lt;base64&gt;
- * - Other arrays and tuples are serialized as &lt;array&gt;
- * - booleans are serialized as &lt;boolean&gt;
- * - byte, int16, uint16 and int32 are serialized as &lt;int&gt;
- * - uint32 and int64 are serialized as the nonstandard &lt;i8&gt; type
- * - doubles are serialized as &lt;double&gt;
- * - Strings are serialized as &lt;string&gt;
- * - Variants (i.e. "v" type) are unwrapped and their child is serialized.
- * - #GVariants created by soup_xmlrpc_variant_new_datetime() are serialized as
- * &lt;dateTime.iso8601&gt;
- * - Other types are not supported and will return %NULL and set @error.
- * This notably includes: object-paths, signatures, uint64, handles, maybes
- * and dictionaries with non-string keys.
- *
- * If @params is floating, it is consumed.
- *
- * Return value: the text of the methodCall, or %NULL on error.
- * Since: 2.52
- **/
-char *
-soup_xmlrpc_build_request (const char *method_name,
- GVariant *params,
- GError **error)
-{
- xmlDoc *doc;
- xmlNode *node, *param;
- xmlChar *xmlbody;
- GVariantIter iter;
- GVariant *child;
- int len;
- char *body = NULL;
-
- g_return_val_if_fail (g_variant_is_of_type (params, G_VARIANT_TYPE_TUPLE), NULL);
-
- g_variant_ref_sink (params);
-
- doc = xmlNewDoc ((const xmlChar *)"1.0");
- doc->standalone = FALSE;
- doc->encoding = xmlCharStrdup ("UTF-8");
-
- node = xmlNewDocNode (doc, NULL, (const xmlChar *)"methodCall", NULL);
- xmlDocSetRootElement (doc, node);
- xmlNewChild (node, NULL, (const xmlChar *)"methodName",
- (const xmlChar *)method_name);
-
- node = xmlNewChild (node, NULL, (const xmlChar *)"params", NULL);
- g_variant_iter_init (&iter, params);
- while ((child = g_variant_iter_next_value (&iter))) {
- param = xmlNewChild (node, NULL,
- (const xmlChar *)"param", NULL);
- if (!insert_value (param, child, error)) {
- xmlFreeDoc (doc);
- g_variant_unref (child);
- g_variant_unref (params);
- return NULL;
- }
- g_variant_unref (child);
- }
-
- xmlDocDumpMemory (doc, &xmlbody, &len);
- body = g_strndup ((char *)xmlbody, len);
- xmlFree (xmlbody);
-
- xmlFreeDoc (doc);
- g_variant_unref (params);
-
- return body;
-}
-
-/**
- * soup_xmlrpc_message_new:
- * @uri: URI of the XML-RPC service
- * @method_name: the name of the XML-RPC method to invoke at @uri
- * @params: a #GVariant tuple
- * @error: a #GError, or %NULL
- *
- * Creates an XML-RPC methodCall and returns a #SoupMessage, ready
- * to send, for that method call.
- *
- * See soup_xmlrpc_build_request() for serialization details.
- *
- * If @params is floating, it is consumed.
- *
- * Returns: (transfer full): a #SoupMessage encoding the
- * indicated XML-RPC request, or %NULL on error.
- *
- * Since: 2.52
- **/
-SoupMessage *
-soup_xmlrpc_message_new (const char *uri,
- const char *method_name,
- GVariant *params,
- GError **error)
-{
- SoupMessage *msg;
- char *body;
-
- body = soup_xmlrpc_build_request (method_name, params, error);
- if (!body)
- return NULL;
-
- msg = soup_message_new ("POST", uri);
- soup_message_set_request (msg, "text/xml", SOUP_MEMORY_TAKE,
- body, strlen (body));
- return msg;
-}
-
-/**
- * soup_xmlrpc_build_response:
- * @value: the return value
- * @error: a #GError, or %NULL
- *
- * This creates a (successful) XML-RPC methodResponse and returns it
- * as a string. To create a fault response, use soup_xmlrpc_build_fault(). This
- * is the low-level method that soup_xmlrpc_message_set_response() is built on.
- *
- * See soup_xmlrpc_build_request() for serialization details, but note
- * that since a method can only have a single return value, @value
- * should not be a tuple here (unless the return value is an array).
- *
- * If @value is floating, it is consumed.
- *
- * Returns: the text of the methodResponse, or %NULL on error.
- *
- * Since: 2.52
- **/
-char *
-soup_xmlrpc_build_response (GVariant *value, GError **error)
-{
- xmlDoc *doc;
- xmlNode *node;
- xmlChar *xmlbody;
- char *body;
- int len;
-
- g_variant_ref_sink (value);
-
- doc = xmlNewDoc ((const xmlChar *)"1.0");
- doc->standalone = FALSE;
- doc->encoding = xmlCharStrdup ("UTF-8");
-
- node = xmlNewDocNode (doc, NULL,
- (const xmlChar *)"methodResponse", NULL);
- xmlDocSetRootElement (doc, node);
-
- node = xmlNewChild (node, NULL, (const xmlChar *)"params", NULL);
- node = xmlNewChild (node, NULL, (const xmlChar *)"param", NULL);
- if (!insert_value (node, value, error)) {
- xmlFreeDoc (doc);
- g_variant_unref (value);
- return NULL;
- }
-
- xmlDocDumpMemory (doc, &xmlbody, &len);
- body = g_strndup ((char *)xmlbody, len);
- xmlFree (xmlbody);
-
- xmlFreeDoc (doc);
- g_variant_unref (value);
-
- return body;
-}
-
-char *
-soup_xmlrpc_build_faultv (int fault_code,
- const char *fault_format,
- va_list args) G_GNUC_PRINTF (2, 0);
-
-char *
-soup_xmlrpc_build_faultv (int fault_code, const char *fault_format, va_list args)
-{
- xmlDoc *doc;
- xmlNode *node, *member;
- GVariant *value;
- xmlChar *xmlbody;
- char *fault_string, *body;
- int len;
-
- fault_string = g_strdup_vprintf (fault_format, args);
-
- doc = xmlNewDoc ((const xmlChar *)"1.0");
- doc->standalone = FALSE;
- doc->encoding = xmlCharStrdup ("UTF-8");
-
- node = xmlNewDocNode (doc, NULL,
- (const xmlChar *)"methodResponse", NULL);
- xmlDocSetRootElement (doc, node);
- node = xmlNewChild (node, NULL, (const xmlChar *)"fault", NULL);
- node = xmlNewChild (node, NULL, (const xmlChar *)"value", NULL);
- node = xmlNewChild (node, NULL, (const xmlChar *)"struct", NULL);
-
- member = xmlNewChild (node, NULL, (const xmlChar *)"member", NULL);
- xmlNewChild (member, NULL,
- (const xmlChar *)"name", (const xmlChar *)"faultCode");
- value = g_variant_new_int32 (fault_code);
- insert_value (member, value, NULL);
- g_variant_unref (value);
-
- member = xmlNewChild (node, NULL, (const xmlChar *)"member", NULL);
- xmlNewChild (member, NULL,
- (const xmlChar *)"name", (const xmlChar *)"faultString");
- value = g_variant_new_take_string (fault_string);
- insert_value (member, value, NULL);
- g_variant_unref (value);
-
- xmlDocDumpMemory (doc, &xmlbody, &len);
- body = g_strndup ((char *)xmlbody, len);
- xmlFree (xmlbody);
- xmlFreeDoc (doc);
-
- return body;
-}
-
-/**
- * soup_xmlrpc_build_fault:
- * @fault_code: the fault code
- * @fault_format: a printf()-style format string
- * @...: the parameters to @fault_format
- *
- * This creates an XML-RPC fault response and returns it as a string.
- * (To create a successful response, use
- * soup_xmlrpc_build_method_response().)
- *
- * Return value: the text of the fault
- **/
-char *
-soup_xmlrpc_build_fault (int fault_code, const char *fault_format, ...)
-{
- va_list args;
- char *body;
-
- va_start (args, fault_format);
- body = soup_xmlrpc_build_faultv (fault_code, fault_format, args);
- va_end (args);
- return body;
-}
-
-/**
- * soup_xmlrpc_message_set_fault:
- * @msg: an XML-RPC request
- * @fault_code: the fault code
- * @fault_format: a printf()-style format string
- * @...: the parameters to @fault_format
- *
- * Sets the status code and response body of @msg to indicate an
- * unsuccessful XML-RPC call, with the error described by @fault_code
- * and @fault_format.
- *
- * Since: 2.52
- **/
-void
-soup_xmlrpc_message_set_fault (SoupMessage *msg, int fault_code,
- const char *fault_format, ...)
-{
- va_list args;
- char *body;
-
- va_start (args, fault_format);
- body = soup_xmlrpc_build_faultv (fault_code, fault_format, args);
- va_end (args);
-
- soup_message_set_status (msg, SOUP_STATUS_OK);
- soup_message_set_response (msg, "text/xml", SOUP_MEMORY_TAKE,
- body, strlen (body));
-}
-
-/**
- * soup_xmlrpc_message_set_response:
- * @msg: an XML-RPC request
- * @value: a #GVariant
- * @error: a #GError, or %NULL
- *
- * Sets the status code and response body of @msg to indicate a
- * successful XML-RPC call, with a return value given by @value. To set a
- * fault response, use soup_xmlrpc_message_set_fault().
- *
- * See soup_xmlrpc_build_request() for serialization details.
- *
- * If @value is floating, it is consumed.
- *
- * Returns: %TRUE on success, %FALSE otherwise.
- *
- * Since: 2.52
- **/
-gboolean
-soup_xmlrpc_message_set_response (SoupMessage *msg, GVariant *value, GError **error)
-{
- char *body;
-
- body = soup_xmlrpc_build_response (value, error);
- if (!body)
- return FALSE;
-
- soup_message_set_status (msg, SOUP_STATUS_OK);
- soup_message_set_response (msg, "text/xml", SOUP_MEMORY_TAKE,
- body, strlen (body));
- return TRUE;
-}
-
-static GVariant *parse_value (xmlNode *node, const char **signature, GError **error);
-
-static xmlNode *
-find_real_node (xmlNode *node)
-{
- while (node && (node->type == XML_COMMENT_NODE ||
- xmlIsBlankNode (node)))
- node = node->next;
- return node;
-}
-
-static char *
-signature_get_next_complete_type (const char **signature)
-{
- GVariantClass class;
- const char *initial_signature;
- char *result;
-
- /* here it is assumed that 'signature' is a valid type string */
-
- initial_signature = *signature;
- class = (*signature)[0];
-
- if (class == G_VARIANT_CLASS_TUPLE || class == G_VARIANT_CLASS_DICT_ENTRY) {
- char stack[256] = {0};
- guint stack_len = 0;
-
- do {
- if ((*signature)[0] == G_VARIANT_CLASS_TUPLE) {
- stack[stack_len] = ')';
- stack_len++;
- }
- else if ( (*signature)[0] == G_VARIANT_CLASS_DICT_ENTRY) {
- stack[stack_len] = '}';
- stack_len++;
- }
-
- (*signature)++;
-
- if ( (*signature)[0] == stack[stack_len - 1])
- stack_len--;
- } while (stack_len > 0);
-
- (*signature)++;
- } else if (class == G_VARIANT_CLASS_ARRAY || class == G_VARIANT_CLASS_MAYBE) {
- char *tmp_sig;
-
- (*signature)++;
- tmp_sig = signature_get_next_complete_type (signature);
- g_free (tmp_sig);
- } else {
- (*signature)++;
- }
-
- result = g_strndup (initial_signature, (*signature) - initial_signature);
-
- return result;
-}
-
-static GVariant *
-parse_array (xmlNode *node, const char **signature, GError **error)
-{
- GVariant *variant = NULL;
- char *child_signature = NULL;
- char *array_signature = NULL;
- const char *tmp_signature;
- gboolean is_tuple = FALSE;
- xmlNode *member;
- GVariantBuilder builder;
- gboolean is_params = FALSE;
-
- if (signature && *signature[0] == G_VARIANT_CLASS_VARIANT)
- signature = NULL;
-
- if (g_str_equal (node->name, "array")) {
- node = find_real_node (node->children);
- if (!g_str_equal (node->name, "data")) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "<data> expected but got '%s'", node->name);
- goto fail;
- }
- } else if (g_str_equal (node->name, "params")) {
- is_params = TRUE;
- } else {
- g_assert_not_reached ();
- }
-
- if (signature != NULL) {
- if ((*signature)[0] == G_VARIANT_CLASS_TUPLE) {
- tmp_signature = *signature;
- array_signature = signature_get_next_complete_type (&tmp_signature);
- is_tuple = TRUE;
- }
- (*signature)++;
- child_signature = signature_get_next_complete_type (signature);
- } else {
- child_signature = g_strdup ("v");
- }
-
- if (!array_signature)
- array_signature = g_strdup_printf ("a%s", child_signature);
- g_variant_builder_init (&builder, G_VARIANT_TYPE (array_signature));
-
- for (member = find_real_node (node->children);
- member;
- member = find_real_node (member->next)) {
- GVariant *child;
- xmlNode *xval = member;
-
- if (is_params) {
- if (!g_str_equal (member->name, "param")) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "<param> expected but got '%s'", member->name);
- goto fail;
- }
- xval = find_real_node (member->children);
- }
-
- if (strcmp ((const char *)xval->name, "value") != 0) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "<value> expected but got '%s'", xval->name);
- goto fail;
- }
-
- if (is_tuple && child_signature[0] == ')') {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "Too many values for tuple");
- goto fail;
- }
-
- tmp_signature = child_signature;
- child = parse_value (xval, &tmp_signature, error);
- if (child == NULL)
- goto fail;
-
- if (is_tuple) {
- g_free (child_signature),
- child_signature = signature_get_next_complete_type (signature);
- }
-
- g_variant_builder_add_value (&builder, child);
- }
-
- if (is_tuple && child_signature[0] != ')') {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "Too few values for tuple");
- goto fail;
- }
-
- variant = g_variant_builder_end (&builder);
-
-fail:
- g_variant_builder_clear (&builder);
- g_free (child_signature);
- g_free (array_signature);
-
- /* compensate the (*signature)++ call at the end of 'recurse()' */
- if (signature)
- (*signature)--;
-
- return variant;
-}
-
-static void
-parse_dict_entry_signature (const char **signature,
- char **entry_signature,
- char **key_signature,
- char **value_signature)
-{
- const char *tmp_sig;
-
- if (signature)
- *entry_signature = signature_get_next_complete_type (signature);
- else
- *entry_signature = g_strdup ("{sv}");
-
- tmp_sig = (*entry_signature) + 1;
- *key_signature = signature_get_next_complete_type (&tmp_sig);
- *value_signature = signature_get_next_complete_type (&tmp_sig);
-}
-
-static GVariant *
-parse_dictionary (xmlNode *node, const char **signature, GError **error)
-{
- GVariant *variant = NULL;
- char *dict_signature;
- char *entry_signature;
- char *key_signature;
- char *value_signature;
- GVariantBuilder builder;
- xmlNode *member;
-
- if (signature && *signature[0] == G_VARIANT_CLASS_VARIANT)
- signature = NULL;
-
- if (signature)
- (*signature)++;
-
- parse_dict_entry_signature (signature,
- &entry_signature,
- &key_signature,
- &value_signature);
-
- dict_signature = g_strdup_printf ("a%s", entry_signature);
- g_variant_builder_init (&builder, G_VARIANT_TYPE (dict_signature));
-
- if (!g_str_equal (key_signature, "s")) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "Dictionary key must be string but got '%s'", key_signature);
- goto fail;
- }
-
- for (member = find_real_node (node->children);
- member;
- member = find_real_node (member->next)) {
- xmlNode *child, *mname, *mxval;
- const char *tmp_signature;
- GVariant *value;
- xmlChar *content;
-
- if (strcmp ((const char *)member->name, "member") != 0) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "<member> expected but got '%s'", member->name);
- goto fail;
- }
-
- mname = mxval = NULL;
-
- for (child = find_real_node (member->children);
- child;
- child = find_real_node (child->next)) {
- if (!strcmp ((const char *)child->name, "name"))
- mname = child;
- else if (!strcmp ((const char *)child->name, "value"))
- mxval = child;
- else {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "<name> or <value> expected but got '%s'", child->name);
- goto fail;
- }
- }
-
- if (!mname || !mxval) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "Missing name or value in <member>");
- goto fail;
- }
-
- tmp_signature = value_signature;
- value = parse_value (mxval, &tmp_signature, error);
- if (!value)
- goto fail;
-
- content = xmlNodeGetContent (mname);
- g_variant_builder_open (&builder, G_VARIANT_TYPE (entry_signature));
- g_variant_builder_add (&builder, "s", content);
- g_variant_builder_add_value (&builder, value);
- g_variant_builder_close (&builder);
- xmlFree (content);
- }
-
- variant = g_variant_builder_end (&builder);
-
-fail:
- g_variant_builder_clear (&builder);
- g_free (value_signature);
- g_free (key_signature);
- g_free (entry_signature);
- g_free (dict_signature);
-
- /* compensate the (*signature)++ call at the end of 'recurse()' */
- if (signature != NULL)
- (*signature)--;
-
- return variant;
-}
-
-static GVariant *
-parse_number (xmlNode *typenode, GVariantClass class, GError **error)
-{
- xmlChar *content;
- const char *str;
- char *endptr;
- gint64 num = 0;
- guint64 unum = 0;
- GVariant *variant = NULL;
-
- content = xmlNodeGetContent (typenode);
- str = (const char *) content;
-
- errno = 0;
-
- if (class == G_VARIANT_CLASS_UINT64)
- unum = g_ascii_strtoull (str, &endptr, 10);
- else
- num = g_ascii_strtoll (str, &endptr, 10);
-
- if (errno || endptr == str) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "Couldn't parse number '%s'", str);
- goto fail;
- }
-
-#define RANGE(v, min, max) \
-G_STMT_START{ \
- if (v < min || v > max) { \
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS, \
- "Number out of range '%s'", str); \
- goto fail; \
- } \
-} G_STMT_END
-
- switch (class) {
- case G_VARIANT_CLASS_BOOLEAN:
- RANGE (num, 0, 1);
- variant = g_variant_new_boolean (num);
- break;
- case G_VARIANT_CLASS_BYTE:
- RANGE (num, 0, G_MAXUINT8);
- variant = g_variant_new_byte (num);
- break;
- case G_VARIANT_CLASS_INT16:
- RANGE (num, G_MININT16, G_MAXINT16);
- variant = g_variant_new_int16 (num);
- break;
- case G_VARIANT_CLASS_UINT16:
- RANGE (num, 0, G_MAXUINT16);
- variant = g_variant_new_uint16 (num);
- break;
- case G_VARIANT_CLASS_INT32:
- RANGE (num, G_MININT32, G_MAXINT32);
- variant = g_variant_new_int32 (num);
- break;
- case G_VARIANT_CLASS_UINT32:
- RANGE (num, 0, G_MAXUINT32);
- variant = g_variant_new_uint32 (num);
- break;
- case G_VARIANT_CLASS_INT64:
- RANGE (num, G_MININT64, G_MAXINT64);
- variant = g_variant_new_int64 (num);
- break;
- case G_VARIANT_CLASS_UINT64:
- RANGE (unum, 0, G_MAXUINT64);
- variant = g_variant_new_uint64 (unum);
- break;
- default:
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "<%s> node does not match signature",
- (const char *)typenode->name);
- goto fail;
- }
-
-fail:
- xmlFree (content);
-
- return variant;
-}
-
-static GVariant *
-parse_double (xmlNode *typenode, GError **error)
-{
- GVariant *variant = NULL;
- xmlChar *content;
- const char *str;
- char *endptr;
- gdouble d;
-
- content = xmlNodeGetContent (typenode);
- str = (const char *) content;
-
- errno = 0;
- d = g_ascii_strtod (str, &endptr);
- if (errno || endptr == str) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "Couldn't parse double '%s'", str);
- goto fail;
- }
-
- variant = g_variant_new_double (d);
-
-fail:
- xmlFree (content);
-
- return variant;
-}
-
-static GVariant *
-parse_base64 (xmlNode *typenode, GError **error)
-{
- GVariant *variant;
- xmlChar *content;
- guchar *decoded;
- gsize len;
-
- content = xmlNodeGetContent (typenode);
- decoded = g_base64_decode ((char *)content, &len);
- variant = g_variant_new_from_data (G_VARIANT_TYPE ("ay"),
- decoded, len,
- TRUE,
- g_free, decoded);
- xmlFree (content);
-
- return variant;
-}
-
-static GVariant *
-soup_xmlrpc_variant_new_custom (const char *type, const char *v)
-{
- return g_variant_new ("(oss)", "/org/gnome/libsoup/ExtensionType",
- type, v);
-}
-
-static GVariant *
-parse_value (xmlNode *node, const char **signature, GError **error)
-{
- xmlNode *typenode;
- const char *typename;
- xmlChar *content = NULL;
- GVariant *variant = NULL;
- GVariantClass class = G_VARIANT_CLASS_VARIANT;
-
- if (signature)
- class = *signature[0];
-
- if (g_str_equal ((const char *)node->name, "value")) {
- typenode = find_real_node (node->children);
- if (!typenode) {
- /* If no typenode, assume value's content is string */
- typename = "string";
- typenode = node;
- } else {
- typename = (const char *)typenode->name;
- }
- } else if (g_str_equal ((const char *)node->name, "params")) {
- typenode = node;
- typename = "params";
- } else {
- g_assert_not_reached ();
- }
-
- if (g_str_equal (typename, "boolean")) {
- if (class != G_VARIANT_CLASS_VARIANT && class != G_VARIANT_CLASS_BOOLEAN) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "<boolean> node does not match signature");
- goto fail;
- }
- variant = parse_number (typenode, G_VARIANT_CLASS_BOOLEAN, error);
- } else if (g_str_equal (typename, "int") || g_str_equal (typename, "i4")) {
- if (class == G_VARIANT_CLASS_VARIANT)
- variant = parse_number (typenode, G_VARIANT_CLASS_INT32, error);
- else
- variant = parse_number (typenode, class, error);
- } else if (g_str_equal (typename, "i8")) {
- if (class == G_VARIANT_CLASS_VARIANT)
- variant = parse_number (typenode, G_VARIANT_CLASS_INT64, error);
- else
- variant = parse_number (typenode, class, error);
- } else if (g_str_equal (typename, "double")) {
- if (class != G_VARIANT_CLASS_VARIANT && class != G_VARIANT_CLASS_DOUBLE) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "<double> node does not match signature");
- goto fail;
- }
- variant = parse_double (typenode, error);
- } else if (g_str_equal (typename, "string")) {
- if (class != G_VARIANT_CLASS_VARIANT && class != G_VARIANT_CLASS_STRING) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "<string> node does not match signature");
- goto fail;
- }
- content = xmlNodeGetContent (typenode);
- variant = g_variant_new_string ((const char *)content);
- } else if (g_str_equal (typename, "base64")) {
- if (class != G_VARIANT_CLASS_VARIANT) {
- if (!g_str_has_prefix (*signature, "ay")) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "<base64> node does not match signature");
- goto fail;
- }
- (*signature)++;
- }
- variant = parse_base64 (typenode, error);
- } else if (g_str_equal (typename, "struct")) {
- if (class != G_VARIANT_CLASS_VARIANT &&
- !g_str_has_prefix (*signature, "a{")) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "<struct> node does not match signature");
- goto fail;
- }
- variant = parse_dictionary (typenode, signature, error);
- } else if (g_str_equal (typename, "array") || g_str_equal (typename, "params")) {
- if (class != G_VARIANT_CLASS_VARIANT &&
- class != G_VARIANT_CLASS_ARRAY &&
- class != G_VARIANT_CLASS_TUPLE) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "<%s> node does not match signature", typename);
- goto fail;
- }
- variant = parse_array (typenode, signature, error);
- } else if (g_str_equal (typename, "dateTime.iso8601")) {
- if (class != G_VARIANT_CLASS_VARIANT) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "<dateTime.iso8601> node does not match signature");
- goto fail;
- }
-
- content = xmlNodeGetContent (typenode);
- variant = soup_xmlrpc_variant_new_custom ("dateTime.iso8601",
- (const char *)content);
- } else {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "Unknown node name %s", typename);
- goto fail;
- }
-
- if (variant && signature) {
- if (class == G_VARIANT_CLASS_VARIANT)
- variant = g_variant_new_variant (variant);
- (*signature)++;
- }
-
-fail:
- if (content)
- xmlFree (content);
-
- return variant;
-}
-
-/**
- * SoupXMLRPCParams:
- *
- * Opaque structure containing XML-RPC methodCall parameter values.
- * Can be parsed using soup_xmlrpc_params_parse() and freed with
- * soup_xmlrpc_params_free().
- *
- * Since: 2.52
- */
-struct _SoupXMLRPCParams
-{
- xmlNode *node;
-};
-
-/**
- * soup_xmlrpc_params_free:
- * @self: a SoupXMLRPCParams
- *
- * Free a #SoupXMLRPCParams returned by soup_xmlrpc_parse_request().
- *
- * Since: 2.52
- */
-void
-soup_xmlrpc_params_free (SoupXMLRPCParams *self)
-{
- g_return_if_fail (self != NULL);
-
- if (self->node)
- xmlFreeDoc (self->node->doc);
- g_slice_free (SoupXMLRPCParams, self);
-}
-
-static SoupXMLRPCParams *
-soup_xmlrpc_params_new (xmlNode *node)
-{
- SoupXMLRPCParams *self;
-
- self = g_slice_new (SoupXMLRPCParams);
- self->node = node;
-
- return self;
-}
-
-/**
- * soup_xmlrpc_params_parse:
- * @self: A #SoupXMLRPCParams
- * @signature: (allow-none): A valid #GVariant type string, or %NULL
- * @error: a #GError, or %NULL
- *
- * Parse method parameters returned by soup_xmlrpc_parse_request().
- *
- * Deserialization details:
- * - If @signature is provided, &lt;int&gt; and &lt;i4&gt; can be deserialized
- * to byte, int16, uint16, int32, uint32, int64 or uint64. Otherwise
- * it will be deserialized to int32. If the value is out of range
- * for the target type it will return an error.
- * - &lt;struct&gt; will be deserialized to "a{sv}". @signature could define
- * another value type (e.g. "a{ss}").
- * - &lt;array&gt; will be deserialized to "av". @signature could define
- * another element type (e.g. "as") or could be a tuple (e.g. "(ss)").
- * - &lt;base64&gt; will be deserialized to "ay".
- * - &lt;string&gt; will be deserialized to "s".
- * - &lt;dateTime.iso8601&gt; will be deserialized to an unspecified variant
- * type. If @signature is provided it must have the generic "v" type, which
- * means there is no guarantee that it's actually a datetime that has been
- * received. soup_xmlrpc_variant_get_datetime() must be used to parse and
- * type check this special variant.
- * - @signature must not have maybes, otherwise an error is returned.
- * - Dictionaries must have string keys, otherwise an error is returned.
- *
- * Returns: (transfer full): a new (non-floating) #GVariant, or %NULL
- *
- * Since: 2.52
- */
-GVariant *
-soup_xmlrpc_params_parse (SoupXMLRPCParams *self,
- const char *signature,
- GError **error)
-{
- GVariant *value = NULL;
-
- g_return_val_if_fail (self, NULL);
- g_return_val_if_fail (!signature || g_variant_type_string_is_valid (signature), NULL);
-
- if (!self->node) {
- if (!signature || g_variant_type_equal (G_VARIANT_TYPE (signature), G_VARIANT_TYPE ("av")))
- value = g_variant_new_array (G_VARIANT_TYPE_VARIANT, NULL, 0);
- else if (g_variant_type_equal (G_VARIANT_TYPE (signature), G_VARIANT_TYPE_UNIT))
- value = g_variant_new_tuple (NULL, 0);
- else {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "Invalid signature '%s', was expecting '()'", signature);
- goto fail;
- }
- } else {
- value = parse_value (self->node, signature ? &signature : NULL, error);
- }
-
-fail:
- return value ? g_variant_ref_sink (value) : NULL;
-}
-
-/**
- * soup_xmlrpc_parse_request:
- * @method_call: the XML-RPC methodCall string
- * @length: the length of @method_call, or -1 if it is NUL-terminated
- * @params: (out): on success, a new #SoupXMLRPCParams
- * @error: a #GError, or %NULL
- *
- * Parses @method_call and return the method name. Method parameters can be
- * parsed later using soup_xmlrpc_params_parse().
- *
- * Returns: (transfer full): method's name, or %NULL on error.
- * Since: 2.52
- **/
-char *
-soup_xmlrpc_parse_request (const char *method_call,
- int length,
- SoupXMLRPCParams **params,
- GError **error)
-{
- xmlDoc *doc = NULL;
- xmlNode *node;
- xmlChar *xmlMethodName = NULL;
- char *method_name = NULL;
-
- doc = xmlParseMemory (method_call, length == -1 ? strlen (method_call) : length);
- if (!doc) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "Could not parse XML document");
- goto fail;
- }
-
- node = xmlDocGetRootElement (doc);
- if (!node || strcmp ((const char *)node->name, "methodCall") != 0) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "<methodCall> node expected");
- goto fail;
- }
-
- node = find_real_node (node->children);
- if (!node || strcmp ((const char *)node->name, "methodName") != 0) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "<methodName> node expected");
- goto fail;
- }
- xmlMethodName = xmlNodeGetContent (node);
-
- if (params) {
- node = find_real_node (node->next);
- if (node) {
- if (strcmp ((const char *)node->name, "params") != 0) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "<params> node expected");
- goto fail;
- }
- *params = soup_xmlrpc_params_new (node);
- doc = NULL;
- } else {
- *params = soup_xmlrpc_params_new (NULL);
- }
- }
-
- method_name = g_strdup ((char *)xmlMethodName);
-
-fail:
- if (doc)
- xmlFreeDoc (doc);
- if (xmlMethodName)
- xmlFree (xmlMethodName);
-
- return method_name;
-}
-
-/**
- * soup_xmlrpc_parse_response:
- * @method_response: the XML-RPC methodResponse string
- * @length: the length of @method_response, or -1 if it is NUL-terminated
- * @signature: (allow-none): A valid #GVariant type string, or %NULL
- * @error: a #GError, or %NULL
- *
- * Parses @method_response and returns the return value. If
- * @method_response is a fault, %NULL is returned, and @error
- * will be set to an error in the %SOUP_XMLRPC_FAULT domain, with the error
- * code containing the fault code, and the error message containing
- * the fault string. If @method_response cannot be parsed, %NULL is returned,
- * and @error will be set to an error in the %SOUP_XMLRPC_ERROR domain.
- *
- * See soup_xmlrpc_params_parse() for deserialization details.
- *
- * Returns: (transfer full): a new (non-floating) #GVariant, or %NULL
- *
- * Since: 2.52
- **/
-GVariant *
-soup_xmlrpc_parse_response (const char *method_response,
- int length,
- const char *signature,
- GError **error)
-{
- xmlDoc *doc = NULL;
- xmlNode *node;
- GVariant *value = NULL;
-
- g_return_val_if_fail (!signature || g_variant_type_string_is_valid (signature), NULL);
-
- doc = xmlParseMemory (method_response,
- length == -1 ? strlen (method_response) : length);
- if (!doc) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "Failed to parse response XML");
- goto fail;
- }
-
- node = xmlDocGetRootElement (doc);
- if (!node || strcmp ((const char *)node->name, "methodResponse") != 0) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "Missing 'methodResponse' node");
- goto fail;
- }
-
- node = find_real_node (node->children);
- if (!node) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "'methodResponse' has no child");
- goto fail;
- }
-
- if (!strcmp ((const char *)node->name, "fault")) {
- int fault_code;
- const char *fault_string;
- const char *fault_sig = "a{sv}";
- GVariant *fault_val;
-
- node = find_real_node (node->children);
- if (!node || strcmp ((const char *)node->name, "value") != 0) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "'fault' has no 'value' child");
- goto fail;
- }
-
- fault_val = parse_value (node, &fault_sig, error);
- if (!fault_val)
- goto fail;
-
- if (!g_variant_lookup (fault_val, "faultCode", "i", &fault_code) ||
- !g_variant_lookup (fault_val, "faultString", "&s", &fault_string)) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "'fault' missing 'faultCode' or 'faultString'");
- goto fail;
- }
- g_set_error (error, SOUP_XMLRPC_FAULT,
- fault_code, "%s", fault_string);
- g_variant_unref (fault_val);
- } else if (!strcmp ((const char *)node->name, "params")) {
- node = find_real_node (node->children);
- if (!node || strcmp ((const char *)node->name, "param") != 0) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "'params' has no 'param' child");
- goto fail;
- }
- node = find_real_node (node->children);
- if (!node || strcmp ((const char *)node->name, "value") != 0) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "'param' has no 'value' child");
- goto fail;
- }
- value = parse_value (node, signature ? &signature : NULL, error);
- }
-
-fail:
- if (doc)
- xmlFreeDoc (doc);
- return value ? g_variant_ref_sink (value) : NULL;
-}
-
-/**
- * soup_xmlrpc_variant_new_datetime:
- * @date: a #SoupDate
- *
- * Construct a special #GVariant used to serialize a &lt;dateTime.iso8601&gt;
- * node. See soup_xmlrpc_build_request().
- *
- * The actual type of the returned #GVariant is unspecified and "v" or "*"
- * should be used in variant format strings. For example:
- * <informalexample><programlisting>
- * args = g_variant_new ("(v)", soup_xmlrpc_variant_new_datetime (date));
- * </programlisting></informalexample>
- *
- * Returns: a floating #GVariant.
- *
- * Since: 2.52
- */
-GVariant *
-soup_xmlrpc_variant_new_datetime (SoupDate *date)
-{
- GVariant *variant;
- char *str;
-
- str = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC);
- variant = soup_xmlrpc_variant_new_custom ("dateTime.iso8601", str);
- g_free (str);
-
- return variant;
-}
-
-/**
- * soup_xmlrpc_variant_get_datetime:
- * @variant: a #GVariant
- * @error: a #GError, or %NULL
- *
- * Get the #SoupDate from special #GVariant created by
- * soup_xmlrpc_variant_new_datetime() or by parsing a &lt;dateTime.iso8601&gt;
- * node. See soup_xmlrpc_params_parse().
- *
- * If @variant does not contain a datetime it will return an error but it is not
- * considered a programmer error because it generally means parameters received
- * are not in the expected type.
- *
- * Returns: a new #SoupDate, or %NULL on error.
- *
- * Since: 2.52
- */
-SoupDate *
-soup_xmlrpc_variant_get_datetime (GVariant *variant, GError **error)
-{
- SoupDate *date = NULL;
- const char *path;
- const char *type;
- const char *v;
-
- if (!g_variant_is_of_type (variant, G_VARIANT_TYPE ("(oss)"))) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "Variant is of type '%s' which is not expected for a datetime",
- g_variant_get_type_string (variant));
- return NULL;
- }
-
- g_variant_get (variant, "(&o&s&s)", &path, &type, &v);
-
- if (!g_str_equal (path, "/org/gnome/libsoup/ExtensionType") ||
- !g_str_equal (type, "dateTime.iso8601")) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "Variant doesn't represent a datetime: %s",
- g_variant_get_type_string (variant));
- return NULL;
- }
-
- date = soup_date_new_from_string (v);
-
- if (date == NULL) {
- g_set_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS,
- "Can't parse datetime string: %s", v);
- return NULL;
- }
-
- return date;
-
-}
-
-/**
- * SOUP_XMLRPC_FAULT:
- *
- * A #GError domain representing an XML-RPC fault code. Used with
- * #SoupXMLRPCFault (although servers may also return fault codes not
- * in that enumeration).
- */
-
-/**
- * SoupXMLRPCFault:
- * @SOUP_XMLRPC_FAULT_PARSE_ERROR_NOT_WELL_FORMED: request was not
- * well-formed
- * @SOUP_XMLRPC_FAULT_PARSE_ERROR_UNSUPPORTED_ENCODING: request was in
- * an unsupported encoding
- * @SOUP_XMLRPC_FAULT_PARSE_ERROR_INVALID_CHARACTER_FOR_ENCODING:
- * request contained an invalid character
- * @SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_XML_RPC: request was not
- * valid XML-RPC
- * @SOUP_XMLRPC_FAULT_SERVER_ERROR_REQUESTED_METHOD_NOT_FOUND: method
- * not found
- * @SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS: invalid
- * parameters
- * @SOUP_XMLRPC_FAULT_SERVER_ERROR_INTERNAL_XML_RPC_ERROR: internal
- * error
- * @SOUP_XMLRPC_FAULT_APPLICATION_ERROR: start of reserved range for
- * application error codes
- * @SOUP_XMLRPC_FAULT_SYSTEM_ERROR: start of reserved range for
- * system error codes
- * @SOUP_XMLRPC_FAULT_TRANSPORT_ERROR: start of reserved range for
- * transport error codes
- *
- * Pre-defined XML-RPC fault codes from <ulink
- * url="http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php">http://xmlrpc-epi.sourceforge.net/specs/rfc.fault_codes.php</ulink>.
- * These are an extension, not part of the XML-RPC spec; you can't
- * assume servers will use them.
- */
-
-G_DEFINE_QUARK (soup_xmlrpc_fault_quark, soup_xmlrpc_fault);
-G_DEFINE_QUARK (soup_xmlrpc_error_quark, soup_xmlrpc_error);
diff --git a/libsoup/xmlrpc/soup-xmlrpc.h b/libsoup/xmlrpc/soup-xmlrpc.h
deleted file mode 100644
index 2a32e466..00000000
--- a/libsoup/xmlrpc/soup-xmlrpc.h
+++ /dev/null
@@ -1,95 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright 2015 - Collabora Ltd.
- */
-
-#pragma once
-
-#include "soup-types.h"
-
-G_BEGIN_DECLS
-
-/* XML-RPC client */
-SOUP_AVAILABLE_IN_2_52
-char *soup_xmlrpc_build_request (const char *method_name,
- GVariant *params,
- GError **error);
-SOUP_AVAILABLE_IN_2_52
-SoupMessage *soup_xmlrpc_message_new (const char *uri,
- const char *method_name,
- GVariant *params,
- GError **error);
-SOUP_AVAILABLE_IN_2_52
-GVariant *soup_xmlrpc_parse_response (const char *method_response,
- int length,
- const char *signature,
- GError **error);
-
-/* XML-RPC server */
-typedef struct _SoupXMLRPCParams SoupXMLRPCParams;
-SOUP_AVAILABLE_IN_2_52
-void soup_xmlrpc_params_free (SoupXMLRPCParams *self);
-SOUP_AVAILABLE_IN_2_52
-GVariant *soup_xmlrpc_params_parse (SoupXMLRPCParams *self,
- const char *signature,
- GError **error);
-SOUP_AVAILABLE_IN_2_52
-char *soup_xmlrpc_parse_request (const char *method_call,
- int length,
- SoupXMLRPCParams **params,
- GError **error);
-SOUP_AVAILABLE_IN_2_52
-char *soup_xmlrpc_build_response (GVariant *value,
- GError **error);
-SOUP_AVAILABLE_IN_2_4
-char *soup_xmlrpc_build_fault (int fault_code,
- const char *fault_format,
- ...) G_GNUC_PRINTF (2, 3);
-SOUP_AVAILABLE_IN_2_52
-gboolean soup_xmlrpc_message_set_response (SoupMessage *msg,
- GVariant *value,
- GError **error);
-SOUP_AVAILABLE_IN_2_52
-void soup_xmlrpc_message_set_fault (SoupMessage *msg,
- int fault_code,
- const char *fault_format,
- ...) G_GNUC_PRINTF (3, 4);
-
-/* Utils */
-SOUP_AVAILABLE_IN_2_52
-GVariant *soup_xmlrpc_variant_new_datetime (SoupDate *date);
-
-SOUP_AVAILABLE_IN_2_52
-SoupDate *soup_xmlrpc_variant_get_datetime (GVariant *variant,
- GError **error);
-
-/* Errors */
-#define SOUP_XMLRPC_ERROR soup_xmlrpc_error_quark()
-SOUP_AVAILABLE_IN_2_4
-GQuark soup_xmlrpc_error_quark (void);
-
-typedef enum {
- SOUP_XMLRPC_ERROR_ARGUMENTS,
- SOUP_XMLRPC_ERROR_RETVAL
-} SoupXMLRPCError;
-
-#define SOUP_XMLRPC_FAULT soup_xmlrpc_fault_quark()
-SOUP_AVAILABLE_IN_2_4
-GQuark soup_xmlrpc_fault_quark (void);
-
-typedef enum {
- SOUP_XMLRPC_FAULT_PARSE_ERROR_NOT_WELL_FORMED = -32700,
- SOUP_XMLRPC_FAULT_PARSE_ERROR_UNSUPPORTED_ENCODING = -32701,
- SOUP_XMLRPC_FAULT_PARSE_ERROR_INVALID_CHARACTER_FOR_ENCODING = -32702,
- SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_XML_RPC = -32600,
- SOUP_XMLRPC_FAULT_SERVER_ERROR_REQUESTED_METHOD_NOT_FOUND = -32601,
- SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS = -32602,
- SOUP_XMLRPC_FAULT_SERVER_ERROR_INTERNAL_XML_RPC_ERROR = -32603,
- SOUP_XMLRPC_FAULT_APPLICATION_ERROR = -32500,
- SOUP_XMLRPC_FAULT_SYSTEM_ERROR = -32400,
- SOUP_XMLRPC_FAULT_TRANSPORT_ERROR = -32300
-} SoupXMLRPCFault;
-
-G_DEFINE_AUTOPTR_CLEANUP_FUNC (SoupXMLRPCParams, soup_xmlrpc_params_free)
-
-G_END_DECLS
diff --git a/meson.build b/meson.build
index 4bfd845f..1c3648eb 100644
--- a/meson.build
+++ b/meson.build
@@ -266,28 +266,7 @@ if have_apache
endif
endif
-have_php = false
-have_php_xmlrpc = false
-if have_apache
- php = find_program('php', required : false)
- message(cdata.get('APACHE_PHP_MODULE_FILE'))
- if php.found() and cdata.get('APACHE_PHP_MODULE_FILE') != ''
- have_php = true
- php_xmlrpc = run_command(php, '-d', 'extension=xmlrpc', '-r', 'exit(function_exists("xmlrpc_server_create")?0:1);')
- if php_xmlrpc.returncode() == 0
- message('php-xmlrpc found')
- have_php_xmlrpc = true
- cdata.set('HAVE_PHP_XMLRPC', '1')
- else
- message('php-xmlrpc not found')
- endif
- endif
- cdata.set('IF_HAVE_PHP', have_php ? '' : '#')
- cdata.set('IF_HAVE_PHP_XMLRPC', have_php_xmlrpc ? '' : ';')
-endif
-
-tests_ready = have_apache and have_php and have_php_xmlrpc
-if not tests_ready
+if not have_apache
warning('Some regression tests will not be compiled due to missing libraries or modules. Please check the logs for more details.')
endif
diff --git a/tests/httpd.conf.in b/tests/httpd.conf.in
index 93fb7ff4..fd666b92 100644
--- a/tests/httpd.conf.in
+++ b/tests/httpd.conf.in
@@ -24,15 +24,12 @@ LoadModule authz_host_module @APACHE_MODULE_DIR@/mod_authz_host.so
LoadModule authz_user_module @APACHE_MODULE_DIR@/mod_authz_user.so
LoadModule dir_module @APACHE_MODULE_DIR@/mod_dir.so
LoadModule mime_module @APACHE_MODULE_DIR@/mod_mime.so
-@IF_HAVE_PHP@LoadModule php7_module @APACHE_PHP_MODULE_FILE@
LoadModule proxy_module @APACHE_MODULE_DIR@/mod_proxy.so
LoadModule proxy_http_module @APACHE_MODULE_DIR@/mod_proxy_http.so
LoadModule proxy_connect_module @APACHE_MODULE_DIR@/mod_proxy_connect.so
LoadModule ssl_module @APACHE_SSL_MODULE_DIR@/mod_ssl.so
@IF_HAVE_MOD_UNIXD@LoadModule unixd_module @APACHE_SSL_MODULE_DIR@/mod_unixd.so
-@IF_HAVE_PHP@PHPIniDir .
-
DirectoryIndex index.txt
TypesConfig /dev/null
AddType application/x-httpd-php .php
diff --git a/tests/meson.build b/tests/meson.build
index dd227876..84e679ea 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -122,33 +122,6 @@ if have_apache
endif
endif
-if have_php
- configure_file(output : 'php.ini',
- input : 'php.ini.in',
- configuration : cdata,
- install : installed_tests_enabled,
- install_dir : installed_tests_execdir,
- )
-endif
-
-if have_php_xmlrpc
- tests += [
- ['xmlrpc-server', true, []],
- ['xmlrpc', false, []]
- ]
-
- configure_file(input : 'xmlrpc-server.php',
- output : 'xmlrpc-server.php',
- copy : true)
-
- if installed_tests_enabled
- install_data(
- 'xmlrpc-server.php',
- install_dir : installed_tests_execdir,
- )
- endif
-endif
-
env = environment()
env.set('G_TEST_SRCDIR', meson.current_source_dir())
env.set('G_TEST_BUILDDIR', meson.current_build_dir())
diff --git a/tests/php.ini.in b/tests/php.ini.in
deleted file mode 100644
index 0f49c94d..00000000
--- a/tests/php.ini.in
+++ /dev/null
@@ -1 +0,0 @@
-@IF_HAVE_PHP_XMLRPC@extension=xmlrpc
diff --git a/tests/xmlrpc-server-test.c b/tests/xmlrpc-server-test.c
deleted file mode 100644
index a6d4abd5..00000000
--- a/tests/xmlrpc-server-test.c
+++ /dev/null
@@ -1,381 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright 2008 Red Hat, Inc.
- * Copyright 2015, Collabora ltd.
- */
-
-#include "test-utils.h"
-
-static char *uri;
-
-static GVariant *
-parse_params (SoupMessage *msg, SoupXMLRPCParams *params, const char *signature)
-{
- GVariant *args;
- GError *error = NULL;
-
- args = soup_xmlrpc_params_parse (params, signature, &error);
- if (!args) {
- soup_xmlrpc_message_set_fault (msg,
- SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS,
- "Wrong method signature: expected %s: %s",
- signature, error->message);
- }
-
- return args;
-}
-
-static void
-do_sum (SoupMessage *msg, SoupXMLRPCParams *params)
-{
- GVariant *args;
- GVariant *child;
- GVariantIter iter;
- double sum = 0.0, val;
-
- if (!(args = parse_params (msg, params, "(ad)")))
- return;
-
- child = g_variant_get_child_value (args, 0);
-
- g_variant_iter_init (&iter, child);
- while (g_variant_iter_loop (&iter, "d", &val))
- sum += val;
-
- soup_xmlrpc_message_set_response (msg, g_variant_new_double (sum), NULL);
-
- g_variant_unref (args);
- g_variant_unref (child);
-}
-
-static void
-do_countBools (SoupMessage *msg, SoupXMLRPCParams *params)
-{
- GVariant *args;
- GVariant *child;
- GVariantIter iter;
- gboolean val;
- int trues = 0, falses = 0;
- GVariantDict dict;
-
- if (!(args = parse_params (msg, params, "(ab)")))
- return;
-
- child = g_variant_get_child_value (args, 0);
-
- g_variant_iter_init (&iter, child);
- while (g_variant_iter_loop (&iter, "b", &val)) {
- if (val)
- trues++;
- else
- falses++;
- }
-
- g_variant_dict_init (&dict, NULL);
- g_variant_dict_insert (&dict, "true", "i", trues);
- g_variant_dict_insert (&dict, "false", "i", falses);
-
- soup_xmlrpc_message_set_response (msg, g_variant_dict_end (&dict), NULL);
-
- g_variant_unref (args);
- g_variant_unref (child);
-}
-
-static void
-do_md5sum (SoupMessage *msg, SoupXMLRPCParams *params)
-{
- GVariant *args;
- GVariant *child;
- GChecksum *checksum;
- GByteArray *digest;
- gsize digest_len = 16;
-
- if (!(args = parse_params (msg, params, "(ay)")))
- return;
-
- child = g_variant_get_child_value (args, 0);
-
- checksum = g_checksum_new (G_CHECKSUM_MD5);
- g_checksum_update (checksum,
- g_variant_get_data (child),
- g_variant_get_size (child));
- digest = g_byte_array_new ();
- g_byte_array_set_size (digest, digest_len);
- g_checksum_get_digest (checksum, digest->data, &digest_len);
- g_checksum_free (checksum);
-
- soup_xmlrpc_message_set_response (msg,
- g_variant_new_from_data (G_VARIANT_TYPE_BYTESTRING,
- digest->data, digest_len,
- TRUE, NULL, NULL),
- NULL);
- g_byte_array_free (digest, TRUE);
- g_variant_unref (child);
- g_variant_unref (args);
-}
-
-
-static void
-do_dateChange (SoupMessage *msg, SoupXMLRPCParams *params)
-{
- GVariant *args;
- GVariant *timestamp;
- SoupDate *date;
- GVariant *arg;
- int val;
- GError *error = NULL;
-
- if (!(args = parse_params (msg, params, "(va{si})")))
- return;
-
- g_variant_get (args, "(v@a{si})", &timestamp, &arg);
-
- date = soup_xmlrpc_variant_get_datetime (timestamp, &error);
- if (!date) {
- soup_xmlrpc_message_set_fault (msg,
- SOUP_XMLRPC_FAULT_SERVER_ERROR_INVALID_METHOD_PARAMETERS,
- "%s", error->message);
- g_clear_error (&error);
- goto fail;
- }
-
- if (g_variant_lookup (arg, "tm_year", "i", &val))
- date->year = val + 1900;
- if (g_variant_lookup (arg, "tm_mon", "i", &val))
- date->month = val + 1;
- if (g_variant_lookup (arg, "tm_mday", "i", &val))
- date->day = val;
- if (g_variant_lookup (arg, "tm_hour", "i", &val))
- date->hour = val;
- if (g_variant_lookup (arg, "tm_min", "i", &val))
- date->minute = val;
- if (g_variant_lookup (arg, "tm_sec", "i", &val))
- date->second = val;
-
- soup_xmlrpc_message_set_response (msg,
- soup_xmlrpc_variant_new_datetime (date),
- NULL);
-
- soup_date_free (date);
-
-fail:
- g_variant_unref (args);
- g_variant_unref (arg);
- g_variant_unref (timestamp);
-}
-
-static void
-do_echo (SoupMessage *msg, SoupXMLRPCParams *params)
-{
- GVariant *args;
- GVariant *child;
-
- if (!(args = parse_params (msg, params, "(as)")))
- return;
-
- child = g_variant_get_child_value (args, 0);
- soup_xmlrpc_message_set_response (msg, child, NULL);
- g_variant_unref (args);
- g_variant_unref (child);
-}
-
-static void
-do_ping (SoupMessage *msg, SoupXMLRPCParams *params)
-{
- GVariant *args;
-
- if (!(args = parse_params (msg, params, "()")))
- return;
-
- soup_xmlrpc_message_set_response (msg, g_variant_new_string ("pong"), NULL);
- g_variant_unref (args);
-}
-
-static void
-server_callback (SoupServer *server, SoupMessage *msg,
- const char *path, GHashTable *query,
- SoupClientContext *context, gpointer data)
-{
- char *method_name;
- SoupXMLRPCParams *params;
- GError *error = NULL;
-
- if (msg->method != SOUP_METHOD_POST) {
- soup_message_set_status (msg, SOUP_STATUS_NOT_IMPLEMENTED);
- return;
- }
-
- soup_message_set_status (msg, SOUP_STATUS_OK);
-
- method_name = soup_xmlrpc_parse_request (msg->request_body->data,
- msg->request_body->length,
- &params, &error);
- if (!method_name) {
- soup_xmlrpc_message_set_fault (msg, SOUP_XMLRPC_FAULT_PARSE_ERROR_NOT_WELL_FORMED,
- "Could not parse method call: %s", error->message);
- g_clear_error (&error);
- return;
- }
-
- if (!strcmp (method_name, "sum"))
- do_sum (msg, params);
- else if (!strcmp (method_name, "countBools"))
- do_countBools (msg, params);
- else if (!strcmp (method_name, "md5sum"))
- do_md5sum (msg, params);
- else if (!strcmp (method_name, "dateChange"))
- do_dateChange (msg, params);
- else if (!strcmp (method_name, "echo"))
- do_echo (msg, params);
- else if (!strcmp (method_name, "ping"))
- do_ping (msg, params);
- else {
- soup_xmlrpc_message_set_fault (msg, SOUP_XMLRPC_FAULT_SERVER_ERROR_REQUESTED_METHOD_NOT_FOUND,
- "Unknown method %s", method_name);
- }
-
- g_free (method_name);
- soup_xmlrpc_params_free (params);
-}
-
-static gboolean
-run_xmlrpc_test (char **argv,
- char **stdout_out,
- char **stderr_out,
- GError **error)
-{
- gboolean ok;
- int status;
-
- argv[0] = g_test_build_filename (G_TEST_BUILT, "xmlrpc-test", NULL);
- ok = g_spawn_sync (NULL, argv, NULL, 0, NULL, NULL,
- stdout_out, stderr_out, &status,
- error);
- g_free (argv[0]);
-
- if (!ok)
- return FALSE;
-
- return g_spawn_check_exit_status (status, error);
-}
-
-static void
-do_one_xmlrpc_test (gconstpointer data)
-{
- const char *path = data;
- char *argv[12];
- char *stdout_out, *stderr_out;
- GError *error = NULL;
- int arg;
-
- argv[0] = NULL;
- argv[1] = "-S";
- argv[2] = "-U";
- argv[3] = uri;
- argv[4] = "-q";
- argv[5] = "-p";
- argv[6] = (char *) path;
-
- for (arg = 0; arg < debug_level && arg < 3; arg++)
- argv[arg + 7] = "-d";
- argv[arg + 7] = NULL;
-
- run_xmlrpc_test (argv, &stdout_out, &stderr_out, &error);
- if (stdout_out) {
- g_print ("%s", stdout_out);
- g_free (stdout_out);
- }
- if (stderr_out) {
- g_printerr ("%s", stderr_out);
- g_free (stderr_out);
- }
-
- if ( g_error_matches (error, G_SPAWN_EXIT_ERROR, 1)
- || g_error_matches (error, G_SPAWN_EXIT_ERROR, 77))
- g_test_fail ();
- else
- g_assert_no_error (error);
- g_clear_error (&error);
-}
-
-gboolean run_tests = TRUE;
-
-static GOptionEntry no_test_entry[] = {
- { "no-tests", 'n', G_OPTION_FLAG_REVERSE,
- G_OPTION_ARG_NONE, &run_tests,
- "Don't run tests, just run the test server", NULL },
- { NULL }
-};
-
-int
-main (int argc, char **argv)
-{
- SoupServer *server;
- SoupURI *server_uri;
- int ret;
-
- test_init (argc, argv, no_test_entry);
-
- server = soup_test_server_new (run_tests ? SOUP_TEST_SERVER_IN_THREAD : SOUP_TEST_SERVER_DEFAULT);
- soup_server_add_handler (server, "/xmlrpc-server.php",
- server_callback, NULL, NULL);
- server_uri = soup_test_server_get_uri (server, "http", NULL);
- soup_uri_set_path (server_uri, "/xmlrpc-server.php");
- uri = soup_uri_to_string (server_uri, FALSE);
-
- if (run_tests) {
- char *out, **tests, *path;
- char *list_argv[4];
- GError *error = NULL;
- int i;
-
- list_argv[0] = NULL;
- list_argv[1] = "-S";
- list_argv[2] = "-l";
- list_argv[3] = NULL;
-
- if (!run_xmlrpc_test (list_argv, &out, NULL, &error)) {
- g_printerr ("'xmlrpc-test -l' failed: %s\n", error->message);
- g_error_free (error);
- return 1;
- }
-
- tests = g_strsplit (out, "\n", -1);
- g_free (out);
-
- for (i = 0; tests[i] && *tests[i]; i++) {
- /* GLib >= 2.62 defaults to TAP output for tests, and
- * this adds TAP diagnostics "#..." and the test count
- * "1..N", even in the output of "some-test -l".
- * Ignore those. */
- if (tests[i][0] == '#' || g_str_has_prefix (tests[i], "1.."))
- continue;
-
- g_assert_true (g_str_has_prefix (tests[i], "/xmlrpc/"));
- path = g_strdup_printf ("/xmlrpc-server/%s", tests[i] + strlen ("/xmlrpc/"));
- g_test_add_data_func (path, tests[i], do_one_xmlrpc_test);
- g_free (path);
- }
-
- ret = g_test_run ();
-
- g_strfreev (tests);
- } else {
- GMainLoop *loop;
-
- g_print ("Listening on port %d\n", server_uri->port);
-
- loop = g_main_loop_new (NULL, TRUE);
- g_main_loop_run (loop);
- g_main_loop_unref (loop);
-
- ret = 0;
- }
-
- soup_test_server_quit_unref (server);
- soup_uri_free (server_uri);
- g_free (uri);
- if (run_tests)
- test_cleanup ();
- return ret;
-}
diff --git a/tests/xmlrpc-server.php b/tests/xmlrpc-server.php
deleted file mode 100644
index 7003e683..00000000
--- a/tests/xmlrpc-server.php
+++ /dev/null
@@ -1,99 +0,0 @@
-<?php
-
-function paramfault ()
-{
- # xmlrpc-php translates this into a real <fault>
- $fault["faultCode"] = -32602;
- $fault["faultString"] = "bad parameter";
- return $fault;
-}
-
-# We only check the params in sum(), because that is the one that
-# xmlrpc-test tests will fail if given bad args
-
-function sum ($method_name, $params, $app_data)
-{
- if (xmlrpc_get_type ($params[0]) != "array")
- return paramfault();
-
- $sum = 0;
- foreach ($params[0] as $val) {
- if (xmlrpc_get_type ($val) != "double")
- return paramfault();
-
- $sum = $sum + $val;
- }
- return $sum;
-}
-
-function countBools ($method_name, $params, $app_data)
-{
- $counts["true"] = $counts["false"] = 0;
- foreach ($params[0] as $val) {
- if ($val)
- $counts["true"] = $counts["true"] + 1;
- else
- $counts["false"] = $counts["false"] + 1;
- }
- return $counts;
-}
-
-function md5sum ($method_name, $params, $app_data)
-{
- $val = md5 ($params[0]->scalar, true);
- xmlrpc_set_type ($val, "base64");
- return $val;
-}
-
-function dateChange ($method_name, $params, $app_data)
-{
- $date_str = $params[0]->scalar;
- $date = strptime ($date_str, "%Y%m%dT%H:%M:%S");
-
- foreach ($params[1] as $name => $val) {
- if ($name == "date")
- continue;
- $date[$name] = $val;
- }
-
- $ret = sprintf ("%04d%02d%02dT%02d:%02d:%02d",
- $date["tm_year"] + 1900, $date["tm_mon"] + 1,
- $date["tm_mday"], $date["tm_hour"],
- $date["tm_min"], $date["tm_sec"]);
- xmlrpc_set_type ($ret, "datetime");
- return $ret;
-}
-
-function echo_ ($method_name, $params, $app_data)
-{
- return $params[0];
-}
-
-function ping ($method_name, $params, $app_data)
-{
- if (is_null ($params) or count ($params) == 0)
- return "pong";
- else
- return paramfault ();
-}
-
-# Work around xmlrpc-php lossage; otherwise the datetime values
-# we return will sometimes get a DST adjustment we do not want.
-putenv ("TZ=");
-
-$xmlrpc_server = xmlrpc_server_create ();
-xmlrpc_server_register_method($xmlrpc_server, "sum", "sum");
-xmlrpc_server_register_method($xmlrpc_server, "countBools", "countBools");
-xmlrpc_server_register_method($xmlrpc_server, "md5sum", "md5sum");
-xmlrpc_server_register_method($xmlrpc_server, "dateChange", "dateChange");
-xmlrpc_server_register_method($xmlrpc_server, "echo", "echo_");
-xmlrpc_server_register_method($xmlrpc_server, "ping", "ping");
-
-$response = xmlrpc_server_call_method ($xmlrpc_server,
- implode("\r\n", file('php://input')),
- 0, array ("output_type" => "xml"));
-echo ($response);
-
-xmlrpc_server_destroy ($xmlrpc_server);
-
-?>
diff --git a/tests/xmlrpc-test.c b/tests/xmlrpc-test.c
deleted file mode 100644
index 8fa26bac..00000000
--- a/tests/xmlrpc-test.c
+++ /dev/null
@@ -1,742 +0,0 @@
-/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
-/*
- * Copyright 2001-2003, Ximian, Inc.
- * Copyright 2015, Collabora ltd.
- */
-
-#include "test-utils.h"
-
-static SoupSession *session;
-static const char *default_uri = "http://127.0.0.1:47524/xmlrpc-server.php";
-static const char *uri = NULL;
-static gboolean server_test = FALSE;
-
-#ifdef HAVE_PHP_XMLRPC
-#define SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER
-#else
-#define SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER \
- G_STMT_START { \
- if (!server_test) { \
- g_test_skip ("php-xmlrpc is not available"); \
- return; \
- } \
- } G_STMT_END
-#endif
-
-static gboolean
-send_xmlrpc (const char *body, const char *signature, GVariant **retval)
-{
- SoupMessage *msg;
- GError *err = NULL;
-
- msg = soup_message_new ("POST", uri);
- soup_message_set_request (msg, "text/xml", SOUP_MEMORY_COPY,
- body, strlen (body));
- soup_session_send_message (session, msg);
-
- soup_test_assert_message_status (msg, SOUP_STATUS_OK);
-
- *retval = soup_xmlrpc_parse_response (msg->response_body->data,
- msg->response_body->length,
- signature, &err);
- if (!*retval) {
- if (err->domain == SOUP_XMLRPC_FAULT)
- soup_test_assert (FALSE, "FAULT: %d %s\n", err->code, err->message);
- else
- soup_test_assert (FALSE, "ERROR: %s\n", err->message);
- g_error_free (err);
- g_object_unref (msg);
- return FALSE;
- }
-
- return TRUE;
-}
-
-static gboolean
-do_xmlrpc (const char *method, GVariant *args, const char *signature, GVariant **retval)
-{
- gboolean ret;
- char *body;
- GError *error = NULL;
-
- body = soup_xmlrpc_build_request (method, args, &error);
- g_assert_no_error (error);
- if (!body)
- return FALSE;
-
- ret = send_xmlrpc (body, signature, retval);
- g_free (body);
-
- return ret;
-}
-
-static void
-test_sum (void)
-{
- GVariantBuilder builder;
- int i;
- double val, sum, result;
- GVariant *retval;
- gboolean ok;
-
- SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
-
- debug_printf (2, "sum (array of double -> double): ");
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("ad"));
- for (i = sum = 0; i < 10; i++) {
- val = g_random_int_range (0, 400) / 4.0;
- debug_printf (2, "%s%.2f", i == 0 ? "[" : ", ", val);
- g_variant_builder_add (&builder, "d", val);
- sum += val;
- }
- debug_printf (2, "] -> ");
-
- ok = do_xmlrpc ("sum",
- g_variant_new ("(@ad)", g_variant_builder_end (&builder)),
- "d", &retval);
-
- if (!ok)
- return;
-
- result = g_variant_get_double (retval);
- debug_printf (2, "%.2f\n", result);
- g_assert_cmpfloat (result, ==, sum);
-
- g_variant_unref (retval);
-}
-
-static void
-test_countBools (void)
-{
- GVariantBuilder builder;
- int i, trues, falses;
- GVariant *retval;
- int ret_trues, ret_falses;
- gboolean val, ok;
-
- SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
-
- debug_printf (2, "countBools (array of boolean -> struct of ints): ");
-
- g_variant_builder_init (&builder, G_VARIANT_TYPE ("ab"));
- for (i = trues = falses = 0; i < 10; i++) {
- val = g_random_boolean ();
- debug_printf (2, "%s%c", i == 0 ? "[" : ", ", val ? 'T' : 'F');
- g_variant_builder_add (&builder, "b", val);
- if (val)
- trues++;
- else
- falses++;
- }
- debug_printf (2, "] -> ");
-
- ok = do_xmlrpc ("countBools",
- g_variant_new ("(@ab)", g_variant_builder_end (&builder)),
- "a{si}", &retval);
- if (!ok)
- return;
-
- g_assert_true (g_variant_lookup (retval, "true", "i", &ret_trues));
- g_assert_true (g_variant_lookup (retval, "false", "i", &ret_falses));
- g_assert_cmpint (g_variant_n_children (retval), ==, 2);
- g_variant_unref (retval);
-
- debug_printf (2, "{ true: %d, false: %d }\n", ret_trues, ret_falses);
- g_assert_cmpint (trues, ==, ret_trues);
- g_assert_cmpint (falses, ==, ret_falses);
-}
-
-static void
-test_md5sum (void)
-{
- GByteArray *data;
- int i;
- GChecksum *checksum;
- guchar digest[16];
- gsize digest_len = sizeof (digest);
- GVariant *retval;
- gboolean ok;
-
- SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
-
- debug_printf (2, "md5sum (base64 -> base64)\n");
-
- data = g_byte_array_new ();
- g_byte_array_set_size (data, 256);
- for (i = 0; i < data->len; i++)
- data->data[i] = (char)(g_random_int_range (0, 256));
-
- checksum = g_checksum_new (G_CHECKSUM_MD5);
- g_checksum_update (checksum, data->data, data->len);
- g_checksum_get_digest (checksum, digest, &digest_len);
- g_checksum_free (checksum);
-
- ok = do_xmlrpc ("md5sum",
- g_variant_new ("(@ay)",
- g_variant_new_from_data (G_VARIANT_TYPE_BYTESTRING,
- data->data, data->len,
- TRUE, NULL, NULL)),
- "ay", &retval);
- g_byte_array_free (data, TRUE);
- if (!ok)
- return;
-
- soup_assert_cmpmem (g_variant_get_data (retval), g_variant_get_size (retval),
- digest, digest_len);
- g_variant_unref (retval);
-}
-
-static void
-test_dateChange (void)
-{
- GVariantDict structval;
- SoupDate *date, *result;
- char *timestamp;
- GVariant *retval;
- gboolean ok;
- GError *error = NULL;
-
- SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
-
- debug_printf (2, "dateChange (date, struct of ints -> time)\n");
-
- date = soup_date_new (1970 + (g_random_int_range (0, 50)),
- 1 + g_random_int_range (0, 12),
- 1 + g_random_int_range (0, 28),
- g_random_int_range (0, 24),
- g_random_int_range (0, 60),
- g_random_int_range (0, 60));
- if (debug_level >= 2) {
- char *tmp;
-
- tmp = soup_date_to_string (date, SOUP_DATE_ISO8601_XMLRPC);
- debug_printf (2, "date: %s, {", tmp);
- g_free (tmp);
- }
-
- g_variant_dict_init (&structval, NULL);
-
-#define MAYBE (g_random_int_range (0, 3) != 0)
-
- if (MAYBE) {
- date->year = 1970 + (g_random_int_range (0, 50));
- debug_printf (2, "tm_year: %d, ", date->year - 1900);
- g_variant_dict_insert (&structval, "tm_year",
- "i", date->year - 1900);
- }
- if (MAYBE) {
- date->month = 1 + g_random_int_range (0, 12);
- debug_printf (2, "tm_mon: %d, ", date->month - 1);
- g_variant_dict_insert (&structval, "tm_mon",
- "i", date->month - 1);
- }
- if (MAYBE) {
- date->day = 1 + g_random_int_range (0, 28);
- debug_printf (2, "tm_mday: %d, ", date->day);
- g_variant_dict_insert (&structval, "tm_mday",
- "i", date->day);
- }
- if (MAYBE) {
- date->hour = g_random_int_range (0, 24);
- debug_printf (2, "tm_hour: %d, ", date->hour);
- g_variant_dict_insert (&structval, "tm_hour",
- "i", date->hour);
- }
- if (MAYBE) {
- date->minute = g_random_int_range (0, 60);
- debug_printf (2, "tm_min: %d, ", date->minute);
- g_variant_dict_insert (&structval, "tm_min",
- "i", date->minute);
- }
- if (MAYBE) {
- date->second = g_random_int_range (0, 60);
- debug_printf (2, "tm_sec: %d, ", date->second);
- g_variant_dict_insert (&structval, "tm_sec",
- "i", date->second);
- }
-
- debug_printf (2, "} -> ");
-
- ok = do_xmlrpc ("dateChange",
- g_variant_new ("(vv)",
- soup_xmlrpc_variant_new_datetime (date),
- g_variant_dict_end (&structval)),
- NULL, &retval);
- if (!ok) {
- soup_date_free (date);
- return;
- }
-
- result = soup_xmlrpc_variant_get_datetime (retval, &error);
- g_assert_no_error (error);
-
- if (debug_level >= 2) {
- timestamp = soup_date_to_string (result, SOUP_DATE_ISO8601_XMLRPC);
- debug_printf (2, "%s\n", timestamp);
- g_free (timestamp);
- }
-
- g_assert_cmpint (date->year, ==, result->year);
- g_assert_cmpint (date->month, ==, result->month);
- g_assert_cmpint (date->day, ==, result->day);
- g_assert_cmpint (date->hour, ==, result->hour);
- g_assert_cmpint (date->minute, ==, result->minute);
- g_assert_cmpint (date->second, ==, result->second);
-
- soup_date_free (date);
- soup_date_free (result);
- g_variant_unref (retval);
-}
-
-static const char *const echo_strings[] = {
- "This is a test",
- "& so is this",
- "and so is <this>",
- "&amp; so is &lt;this&gt;",
- NULL
-};
-
-static void
-test_echo (void)
-{
- GVariant *originals;
- GVariant *retval;
- char *str;
-
- SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
-
- debug_printf (2, "echo (array of string -> array of string):\n");
-
- originals = g_variant_new ("^as", echo_strings);
- g_variant_ref_sink (originals);
- str = g_variant_print (originals, TRUE);
- debug_printf (2, "%s -> ", str);
- g_free (str);
-
- if (!do_xmlrpc ("echo",
- g_variant_new ("(@as)", originals),
- "as", &retval)) {
- g_variant_unref (originals);
- return;
- }
-
- str = g_variant_print (retval, TRUE);
- debug_printf (2, "%s\n", str);
- g_free (str);
-
- g_assert_true (g_variant_equal (originals, retval));
-
- g_variant_unref (originals);
- g_variant_unref (retval);
-}
-
-static void
-test_ping (gconstpointer include_params)
-{
- GVariant *retval;
- char *request;
- gboolean ret;
- GError *error = NULL;
-
- g_test_bug ("671661");
-
- SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
-
- debug_printf (2, "ping (void (%s) -> string)\n",
- include_params ? "empty <params>" : "no <params>");
-
- request = soup_xmlrpc_build_request ("ping", g_variant_new ("()"), &error);
- g_assert_no_error (error);
- if (!request)
- return;
-
- if (!include_params) {
- char *params, *end;
-
- params = strstr (request, "<params/>");
- if (!params) {
- soup_test_assert (FALSE, "ERROR: XML did not contain <params/>!");
- return;
- }
- end = params + strlen ("<params/>");
- memmove (params, end, strlen (end) + 1);
- }
-
- ret = send_xmlrpc (request, "s", &retval);
- g_free (request);
-
- if (!ret)
- return;
-
- g_assert_cmpstr (g_variant_get_string (retval, NULL), ==, "pong");
- g_variant_unref (retval);
-}
-
-static void
-do_bad_xmlrpc (const char *body)
-{
- SoupMessage *msg;
- GError *err = NULL;
-
- msg = soup_message_new ("POST", uri);
- soup_message_set_request (msg, "text/xml", SOUP_MEMORY_COPY,
- body, strlen (body));
- soup_session_send_message (session, msg);
-
- soup_test_assert_message_status (msg, SOUP_STATUS_OK);
-
- if (!soup_xmlrpc_parse_response (msg->response_body->data,
- msg->response_body->length,
- "()", &err)) {
- if (err->domain == SOUP_XMLRPC_FAULT) {
- debug_printf (1, "FAULT: %d %s (OK!)\n",
- err->code, err->message);
- g_error_free (err);
- g_object_unref (msg);
- return;
- } else
- soup_test_assert (FALSE, "ERROR: could not parse response: %s\n", err->message);
- } else
- soup_test_assert (FALSE, "Unexpectedly got successful response!\n");
-
- g_object_unref (msg);
-}
-
-static void
-test_fault_malformed (void)
-{
- SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
-
- do_bad_xmlrpc ("<methodCall/>");
-}
-
-static void
-test_fault_method (void)
-{
- SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
-
- do_bad_xmlrpc ("<methodCall><methodName>no_such_method</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
-}
-
-static void
-test_fault_args (void)
-{
- SOUP_TEST_SKIP_IF_NO_XMLRPC_SERVER;
-
- do_bad_xmlrpc ("<methodCall><methodName>sum</methodName><params><param><value><int>1</int></value></param></params></methodCall>");
-}
-
-#define BODY_PREFIX \
- "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"no\"?>\n" \
- "<methodCall><methodName>MyMethod</methodName>"
-#define BODY_SUFFIX \
- "</methodCall>\n"
-
-static void
-verify_serialization (GVariant *value,
- const char *expected_params)
-{
- char *debug;
- char *body;
- char *params;
- GError *error = NULL;
-
- debug = g_variant_print (value, TRUE);
-
- body = soup_xmlrpc_build_request ("MyMethod", value, &error);
- g_assert_no_error (error);
- g_assert (g_str_has_prefix (body, BODY_PREFIX));
- g_assert (g_str_has_suffix (body, BODY_SUFFIX));
-
- params = g_strndup (body + strlen (BODY_PREFIX),
- strlen (body) - strlen (BODY_PREFIX)
- - strlen (BODY_SUFFIX));
-
- if (!g_str_equal (params, expected_params))
- g_error ("Failed to serialize '%s':\n"
- " expected: %s\n"
- " got: %s\n",
- debug, expected_params, params);
-
- g_free (params);
- g_free (body);
- g_free (debug);
-}
-
-static void
-verify_serialization_fail (GVariant *value)
-{
- char *body;
- GError *error = NULL;
-
- body = soup_xmlrpc_build_request ("MyMethod", value, &error);
- g_assert (body == NULL);
- g_assert (error != NULL);
- g_clear_error (&error);
-}
-
-static void
-test_serializer (void)
-{
- SoupDate *date;
-
- verify_serialization (g_variant_new_parsed ("()"),
- "<params/>");
- verify_serialization (g_variant_new_parsed ("(1, 2)"),
- "<params>"
- "<param><value><int>1</int></value></param>"
- "<param><value><int>2</int></value></param>"
- "</params>");
- verify_serialization (g_variant_new_parsed ("((1, 2),)"),
- "<params><param><value><array><data>"
- "<value><int>1</int></value>"
- "<value><int>2</int></value>"
- "</data></array></value></param></params>");
- verify_serialization (g_variant_new_parsed ("({'one', 1},)"),
- "<params><param><value><struct>"
- "<member><name>one</name><value><int>1</int></value></member>"
- "</struct></value></param></params>");
- verify_serialization (g_variant_new_parsed ("([{'one', 1},{'two', 2}],)"),
- "<params><param><value><struct>"
- "<member><name>one</name><value><int>1</int></value></member>"
- "<member><name>two</name><value><int>2</int></value></member>"
- "</struct></value></param></params>");
- verify_serialization (g_variant_new ("(^ay)", "bytestring"),
- "<params><param>"
- "<value><base64>Ynl0ZXN0cmluZwA=</base64></value>"
- "</param></params>");
- verify_serialization (g_variant_new ("(y)", 42),
- "<params>"
- "<param><value><int>42</int></value></param>"
- "</params>");
- date = soup_date_new_from_time_t (1434161309);
- verify_serialization (g_variant_new ("(v)", soup_xmlrpc_variant_new_datetime (date)),
- "<params>"
- "<param><value><dateTime.iso8601>20150613T02:08:29</dateTime.iso8601></value></param>"
- "</params>");
- soup_date_free (date);
- verify_serialization (g_variant_new ("(s)", "<>&"),
- "<params>"
- "<param><value><string>&lt;&gt;&amp;</string></value></param>"
- "</params>");
- verify_serialization (g_variant_new ("(u)", 0),
- "<params>"
- "<param><value><i8>0</i8></value></param>"
- "</params>");
-
- verify_serialization_fail (g_variant_new_parsed ("({1, 2},)"));
- verify_serialization_fail (g_variant_new ("(mi)", NULL));
- verify_serialization_fail (g_variant_new ("(t)", 0));
-}
-
-static void
-verify_deserialization (GVariant *expected_variant,
- const char *signature,
- const char *params)
-{
- char *body;
- char *method_name;
- SoupXMLRPCParams *out_params = NULL;
- GVariant *variant;
- GError *error = NULL;
-
- body = g_strconcat (BODY_PREFIX, params, BODY_SUFFIX, NULL);
- method_name = soup_xmlrpc_parse_request (body, strlen (body),
- &out_params,
- &error);
- g_assert_no_error (error);
- g_assert_cmpstr (method_name, ==, "MyMethod");
-
- variant = soup_xmlrpc_params_parse (out_params, signature, &error);
- g_assert_no_error (error);
-
- if (!g_variant_equal (variant, expected_variant)) {
- char *str1, *str2;
-
- str1 = g_variant_print (expected_variant, TRUE);
- str2 = g_variant_print (variant, TRUE);
- g_error ("Failed to deserialize '%s':\n"
- " expected: %s\n"
- " got: %s\n",
- params, str1, str2);
- g_free (str1);
- g_free (str2);
- }
-
- soup_xmlrpc_params_free (out_params);
- g_variant_unref (variant);
- g_variant_unref (expected_variant);
- g_free (method_name);
- g_free (body);
-}
-
-static void
-verify_deserialization_fail (const char *signature,
- const char *params)
-{
- char *body;
- char *method_name;
- SoupXMLRPCParams *out_params = NULL;
- GVariant *variant;
- GError *error = NULL;
-
- body = g_strconcat (BODY_PREFIX, params, BODY_SUFFIX, NULL);
- method_name = soup_xmlrpc_parse_request (body, strlen (body),
- &out_params,
- &error);
- g_assert_no_error (error);
- g_assert_cmpstr (method_name, ==, "MyMethod");
-
- variant = soup_xmlrpc_params_parse (out_params, signature, &error);
- g_assert_error (error, SOUP_XMLRPC_ERROR, SOUP_XMLRPC_ERROR_ARGUMENTS);
- g_assert (variant == NULL);
-
- g_free (body);
- g_free (method_name);
- g_clear_error (&error);
- soup_xmlrpc_params_free (out_params);
-}
-
-static void
-test_deserializer (void)
-{
- char *tmp;
- SoupDate *date;
-
- verify_deserialization (g_variant_new_parsed ("@av []"),
- NULL,
- "<params/>");
- verify_deserialization (g_variant_new_parsed ("()"),
- "()",
- "<params/>");
- verify_deserialization (g_variant_new_parsed ("(@y 1,@n 2)"),
- "(yn)",
- "<params>"
- "<param><value><int>1</int></value></param>"
- "<param><value><int>2</int></value></param>"
- "</params>");
- verify_deserialization (g_variant_new_parsed ("[<[{'one', <1>},{'two', <2>}]>]"),
- NULL,
- "<params><param><value><struct>"
- "<member><name>one</name><value><int>1</int></value></member>"
- "<member><name>two</name><value><int>2</int></value></member>"
- "</struct></value></param></params>");
- verify_deserialization (g_variant_new_parsed ("([{'one', 1},{'two', 2}],)"),
- "(a{si})",
- "<params><param><value><struct>"
- "<member><name>one</name><value><int>1</int></value></member>"
- "<member><name>two</name><value><int>2</int></value></member>"
- "</struct></value></param></params>");
- date = soup_date_new_from_time_t (1434146909);
- verify_deserialization (g_variant_new_parsed ("[%v]", soup_xmlrpc_variant_new_datetime (date)),
- NULL,
- "<params>"
- "<param><value><dateTime.iso8601>20150612T22:08:29</dateTime.iso8601></value></param>"
- "</params>");
- soup_date_free (date);
- verify_deserialization (g_variant_new_parsed ("[<b'bytestring'>]"),
- NULL,
- "<params>"
- "<param><value><base64>Ynl0ZXN0cmluZwA=</base64></value></param>"
- "</params>");
- verify_deserialization (g_variant_new_parsed ("[<1>]"),
- "av",
- "<params><param><value><int>1</int></value></param></params>");
- verify_deserialization (g_variant_new_parsed ("[<%s>]", "<>&"),
- NULL,
- "<params>"
- "<param><value><string>&lt;&gt;&amp;</string></value></param>"
- "</params>");
- verify_deserialization (g_variant_new_parsed ("(@y 255,)"),
- "(y)",
- "<params>"
- "<param><value><int>255</int></value></param>"
- "</params>");
-
- tmp = g_strdup_printf ("<params>"
- "<param><value><int>%"G_GUINT64_FORMAT"</int></value></param>"
- "</params>", G_MAXUINT64);
- verify_deserialization (g_variant_new ("(t)", G_MAXUINT64),
- "(t)", tmp);
- g_free (tmp);
-
- verify_deserialization_fail (NULL,
- "<params>"
- "<param><value><boolean>2</boolean></value></param>"
- "</params>");
- verify_deserialization_fail ("(y)",
- "<params>"
- "<param><value><int>256</int></value></param>"
- "</params>");
- verify_deserialization_fail ("(ii)",
- "<params>"
- "<param><value><int>1</int></value></param>"
- "</params>");
- verify_deserialization_fail ("(i)",
- "<params>"
- "<param><value><int>1</int></value></param>"
- "<param><value><int>2</int></value></param>"
- "</params>");
-}
-
-static void
-test_fault (void)
-{
- char *body;
- GVariant *reply;
- GError *error = NULL;
-
- body = soup_xmlrpc_build_fault (1, "error: %s", "failed");
- reply = soup_xmlrpc_parse_response (body, strlen (body), NULL, &error);
- g_assert_error (error, SOUP_XMLRPC_FAULT, 1);
- g_assert_cmpstr (error->message, ==, "error: failed");
- g_assert (reply == NULL);
-
- g_free (body);
- g_clear_error (&error);
-}
-
-static GOptionEntry xmlrpc_entries[] = {
- { "uri", 'U', 0, G_OPTION_ARG_STRING, &uri,
- "Alternate URI for server", NULL },
- { "server-test", 'S', 0, G_OPTION_ARG_NONE, &server_test,
- "If this is being run from xmlrpc-server-test", NULL },
- { NULL }
-};
-
-int
-main (int argc, char **argv)
-{
- int ret;
-
- test_init (argc, argv, xmlrpc_entries);
-
- if (!uri && !server_test) {
- apache_init ();
- uri = default_uri;
- }
-
- session = soup_test_session_new (SOUP_TYPE_SESSION, NULL);
-
- g_test_add_func ("/xmlrpc/variant/serializer", test_serializer);
- g_test_add_func ("/xmlrpc/variant/deserializer", test_deserializer);
- g_test_add_func ("/xmlrpc/variant/fault", test_fault);
- g_test_add_func ("/xmlrpc/variant/sum", test_sum);
- g_test_add_func ("/xmlrpc/variant/countBools", test_countBools);
- g_test_add_func ("/xmlrpc/variant/md5sum", test_md5sum);
- g_test_add_func ("/xmlrpc/variant/dateChange", test_dateChange);
- g_test_add_func ("/xmlrpc/variant/echo", test_echo);
- g_test_add_data_func ("/xmlrpc/variant/ping/empty-params", GINT_TO_POINTER (TRUE), test_ping);
- g_test_add_data_func ("/xmlrpc/variant/ping/no-params", GINT_TO_POINTER (FALSE), test_ping);
- g_test_add_func ("/xmlrpc/variant/fault/malformed", test_fault_malformed);
- g_test_add_func ("/xmlrpc/variant/fault/method", test_fault_method);
- g_test_add_func ("/xmlrpc/variant/fault/args", test_fault_args);
-
- ret = g_test_run ();
-
- soup_test_session_abort_unref (session);
-
- test_cleanup ();
- return ret;
-}