示例#1
0
void tst_QDBusType::isValidArray()
{
    QFETCH(QString, data);
    QFETCH(bool, result);

    data.prepend("a");
    QCOMPARE(bool(dbus_signature_validate_single(data.toLatin1(), 0)), result);
    QCOMPARE(QDBusUtil::isValidSingleSignature(data), result);

    data.prepend("a");
    QCOMPARE(bool(dbus_signature_validate_single(data.toLatin1(), 0)), result);
    QCOMPARE(QDBusUtil::isValidSingleSignature(data), result);
}
示例#2
0
QByteArray QDBusArgumentPrivate::createSignature(int id)
{
    QByteArray signature;
    QDBusMarshaller *marshaller = new QDBusMarshaller;
    marshaller->ba = &signature;

    // run it
    void *null = 0;
    QVariant v(id, null);
    QDBusArgument arg(marshaller);
    QDBusMetaType::marshall(arg, v.userType(), v.constData());
    arg.d = 0;

    // delete it
    bool ok = marshaller->ok;
    delete marshaller;

    if (signature.isEmpty() || !ok || !dbus_signature_validate_single(signature, 0)) {
        qWarning("QDBusMarshaller: type `%s' produces invalid D-BUS signature `%s' "
                 "(Did you forget to call beginStructure() ?)",
                 QVariant::typeToName( QVariant::Type(id) ),
                 signature.isEmpty() ? "<empty>" : signature.constData());
        return "";
    } else if (signature.at(0) != DBUS_TYPE_ARRAY && signature.at(0) != DBUS_STRUCT_BEGIN_CHAR ||
               (signature.at(0) == DBUS_TYPE_ARRAY && (signature.at(1) == DBUS_TYPE_BYTE ||
                                                       signature.at(1) == DBUS_TYPE_STRING))) {
        qWarning("QDBusMarshaller: type `%s' attempts to redefine basic D-BUS type '%s' (%s) "
                 "(Did you forget to call beginStructure() ?)",
                 QVariant::typeToName( QVariant::Type(id) ),
                 signature.constData(),
                 QVariant::typeToName( QVariant::Type(QDBusMetaType::signatureToType(signature))) );
        return "";
    }
    return signature;
}
示例#3
0
DBusMessage*
hippo_dbus_handle_get_preference(HippoDBus   *dbus,
                                 DBusMessage *message)
{
    const char *key;
    const char *signature;
    HippoSettings *settings;
    SettingArrivedData *sad;
    DBusConnection *dbus_connection;
    
    key = NULL;
    signature = NULL;
    if (!dbus_message_get_args(message, NULL,
                               DBUS_TYPE_STRING, &key,
                               DBUS_TYPE_SIGNATURE, &signature,
                               DBUS_TYPE_INVALID)) {
        return dbus_message_new_error(message,
                                      DBUS_ERROR_INVALID_ARGS,
                                      _("Expected two arguments, the key and the expected type signature"));
    }

    if (!dbus_signature_validate_single(signature, NULL)) {
        return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
                                      _("Type signature must be a single complete type, not a list of types"));
    }

    if ( ! (*signature == DBUS_TYPE_INT32 ||
            *signature == DBUS_TYPE_STRING ||
            *signature == DBUS_TYPE_BOOLEAN) ) {
        return dbus_message_new_error(message, DBUS_ERROR_INVALID_ARGS,
                                      _("Only STRING, INT32, BOOLEAN values supported for now"));
    }

    dbus_connection = hippo_dbus_get_connection(dbus);    
    
    settings = get_and_ref_settings(dbus_connection);

    if (!hippo_settings_get_ready(settings)) {
        g_object_unref(G_OBJECT(settings));
        return dbus_message_new_error(message, HIPPO_DBUS_PREFS_ERROR_NOT_READY,
                                      _("Have not yet connected to server, can't get preferences"));
    }

    sad = g_new0(SettingArrivedData, 1);
    sad->connection = dbus_connection;
    dbus_connection_ref(sad->connection);
    
    sad->settings = settings;

    sad->method_call = message;
    dbus_message_ref(sad->method_call);
    sad->signature = signature; /* points inside sad->method_call */

    
    /* this may call setting_arrived synchronously if we already have it */
    hippo_settings_get(settings, key, setting_arrived, sad);    
    
    return NULL; /* no synchronous reply, we'll send it async or we just sent it above */
}
/**
 * @ingroup DBusSignatureInternals
 * Unit test for DBusSignature.
 *
 * @returns #TRUE on success.
 */
dbus_bool_t
_dbus_signature_test (void)
{
  DBusSignatureIter iter;
  DBusSignatureIter subiter;
  DBusSignatureIter subsubiter;
  DBusSignatureIter subsubsubiter;
  const char *sig;
  dbus_bool_t boolres;

  _dbus_assert (sizeof (DBusSignatureIter) >= sizeof (DBusSignatureRealIter));

  sig = "";
  _dbus_assert (dbus_signature_validate (sig, NULL));
  _dbus_assert (!dbus_signature_validate_single (sig, NULL));
  dbus_signature_iter_init (&iter, sig);
  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_INVALID);

  sig = DBUS_TYPE_STRING_AS_STRING;
  _dbus_assert (dbus_signature_validate (sig, NULL));
  _dbus_assert (dbus_signature_validate_single (sig, NULL));
  dbus_signature_iter_init (&iter, sig);
  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRING);

  sig = DBUS_TYPE_STRING_AS_STRING DBUS_TYPE_BYTE_AS_STRING;
  _dbus_assert (dbus_signature_validate (sig, NULL));
  dbus_signature_iter_init (&iter, sig);
  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRING);
  boolres = dbus_signature_iter_next (&iter);
  _dbus_assert (boolres);
  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_BYTE);

  sig = DBUS_TYPE_UINT16_AS_STRING
    DBUS_STRUCT_BEGIN_CHAR_AS_STRING
    DBUS_TYPE_STRING_AS_STRING
    DBUS_TYPE_UINT32_AS_STRING
    DBUS_TYPE_VARIANT_AS_STRING
    DBUS_TYPE_DOUBLE_AS_STRING
    DBUS_STRUCT_END_CHAR_AS_STRING;
  _dbus_assert (dbus_signature_validate (sig, NULL));
  dbus_signature_iter_init (&iter, sig);
  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_UINT16);
  boolres = dbus_signature_iter_next (&iter);
  _dbus_assert (boolres);
  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRUCT);
  dbus_signature_iter_recurse (&iter, &subiter);
  _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_STRING);
  boolres = dbus_signature_iter_next (&subiter);
  _dbus_assert (boolres);
  _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_UINT32);
  boolres = dbus_signature_iter_next (&subiter);
  _dbus_assert (boolres);
  _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_VARIANT);
  boolres = dbus_signature_iter_next (&subiter);
  _dbus_assert (boolres);
  _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_DOUBLE);

  sig = DBUS_TYPE_UINT16_AS_STRING
    DBUS_STRUCT_BEGIN_CHAR_AS_STRING
    DBUS_TYPE_UINT32_AS_STRING
    DBUS_TYPE_BYTE_AS_STRING
    DBUS_TYPE_ARRAY_AS_STRING
    DBUS_TYPE_ARRAY_AS_STRING
    DBUS_TYPE_DOUBLE_AS_STRING
    DBUS_STRUCT_BEGIN_CHAR_AS_STRING
    DBUS_TYPE_BYTE_AS_STRING
    DBUS_STRUCT_END_CHAR_AS_STRING
    DBUS_STRUCT_END_CHAR_AS_STRING;
  _dbus_assert (dbus_signature_validate (sig, NULL));
  dbus_signature_iter_init (&iter, sig);
  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_UINT16);
  boolres = dbus_signature_iter_next (&iter);
  _dbus_assert (boolres);
  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_STRUCT);
  dbus_signature_iter_recurse (&iter, &subiter);
  _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_UINT32);
  boolres = dbus_signature_iter_next (&subiter);
  _dbus_assert (boolres);
  _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_BYTE);
  boolres = dbus_signature_iter_next (&subiter);
  _dbus_assert (boolres);
  _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_ARRAY);
  _dbus_assert (dbus_signature_iter_get_element_type (&subiter) == DBUS_TYPE_ARRAY);

  dbus_signature_iter_recurse (&subiter, &subsubiter);
  _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_ARRAY);
  _dbus_assert (dbus_signature_iter_get_element_type (&subsubiter) == DBUS_TYPE_DOUBLE);

  dbus_signature_iter_recurse (&subsubiter, &subsubsubiter);
  _dbus_assert (dbus_signature_iter_get_current_type (&subsubsubiter) == DBUS_TYPE_DOUBLE);
  boolres = dbus_signature_iter_next (&subiter);
  _dbus_assert (boolres);
  _dbus_assert (dbus_signature_iter_get_current_type (&subiter) == DBUS_TYPE_STRUCT);
  dbus_signature_iter_recurse (&subiter, &subsubiter);
  _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_BYTE);

  sig = DBUS_TYPE_ARRAY_AS_STRING
    DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
    DBUS_TYPE_INT16_AS_STRING
    DBUS_TYPE_STRING_AS_STRING
    DBUS_DICT_ENTRY_END_CHAR_AS_STRING
    DBUS_TYPE_VARIANT_AS_STRING;
  _dbus_assert (dbus_signature_validate (sig, NULL));
  _dbus_assert (!dbus_signature_validate_single (sig, NULL));
  dbus_signature_iter_init (&iter, sig);
  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_ARRAY);
  _dbus_assert (dbus_signature_iter_get_element_type (&iter) == DBUS_TYPE_DICT_ENTRY);

  dbus_signature_iter_recurse (&iter, &subiter);
  dbus_signature_iter_recurse (&subiter, &subsubiter);
  _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_INT16);
  boolres = dbus_signature_iter_next (&subsubiter);
  _dbus_assert (boolres);
  _dbus_assert (dbus_signature_iter_get_current_type (&subsubiter) == DBUS_TYPE_STRING);
  boolres = dbus_signature_iter_next (&subsubiter);
  _dbus_assert (!boolres);

  boolres = dbus_signature_iter_next (&iter);
  _dbus_assert (boolres);
  _dbus_assert (dbus_signature_iter_get_current_type (&iter) == DBUS_TYPE_VARIANT);
  boolres = dbus_signature_iter_next (&iter);
  _dbus_assert (!boolres);

  sig = DBUS_TYPE_DICT_ENTRY_AS_STRING;
  _dbus_assert (!dbus_signature_validate (sig, NULL));

  sig = DBUS_TYPE_ARRAY_AS_STRING;
  _dbus_assert (!dbus_signature_validate (sig, NULL));

  sig = DBUS_TYPE_UINT32_AS_STRING
    DBUS_TYPE_ARRAY_AS_STRING;
  _dbus_assert (!dbus_signature_validate (sig, NULL));

  sig = DBUS_TYPE_ARRAY_AS_STRING
    DBUS_TYPE_DICT_ENTRY_AS_STRING;
  _dbus_assert (!dbus_signature_validate (sig, NULL));

  sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING;
  _dbus_assert (!dbus_signature_validate (sig, NULL));

  sig = DBUS_DICT_ENTRY_END_CHAR_AS_STRING;
  _dbus_assert (!dbus_signature_validate (sig, NULL));

  sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
    DBUS_TYPE_INT32_AS_STRING;
  _dbus_assert (!dbus_signature_validate (sig, NULL));

  sig = DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
    DBUS_TYPE_INT32_AS_STRING
    DBUS_TYPE_STRING_AS_STRING;
  _dbus_assert (!dbus_signature_validate (sig, NULL));

  sig = DBUS_STRUCT_END_CHAR_AS_STRING
    DBUS_STRUCT_BEGIN_CHAR_AS_STRING;
  _dbus_assert (!dbus_signature_validate (sig, NULL));

  sig = DBUS_STRUCT_BEGIN_CHAR_AS_STRING
    DBUS_TYPE_BOOLEAN_AS_STRING;
  _dbus_assert (!dbus_signature_validate (sig, NULL));
  return TRUE;
#if 0
 oom:
  _dbus_assert_not_reached ("out of memory");
  return FALSE;
#endif
}
示例#5
0
static int
Dict_tp_init(DBusPyDict *self, PyObject *args, PyObject *kwargs)
{
    PyObject *obj = dbus_py_empty_tuple;
    PyObject *signature = NULL;
    PyObject *tuple;
    PyObject *variant_level;    /* ignored here - __new__ uses it */
    static char *argnames[] = {"mapping_or_iterable", "signature",
                               "variant_level", NULL};

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOO:__init__", argnames,
                                     &obj, &signature, &variant_level)) {
        return -1;
    }

  /* convert signature from a borrowed ref of unknown type to an owned ref
  of type Signature (or None) */
    if (!signature) signature = Py_None;
    if (signature == Py_None
        || PyObject_IsInstance(signature, (PyObject *)&DBusPySignature_Type)) {
        Py_INCREF(signature);
    }
    else {
        signature = PyObject_CallFunction((PyObject *)&DBusPySignature_Type,
                                          "(O)", signature);
        if (!signature) return -1;
    }

    if (signature != Py_None) {
        const char *c_str;
        PyObject *signature_as_bytes;

        if (!NATIVESTR_CHECK(signature)) {
            PyErr_SetString(PyExc_TypeError, "str expected");
            Py_CLEAR(signature);
            return -1;
        }
#ifdef PY3
        if (!(signature_as_bytes = PyUnicode_AsUTF8String(signature))) {
            Py_CLEAR(signature);
            return -1;
        }
#else
        signature_as_bytes = signature;
        Py_INCREF(signature_as_bytes);
#endif

        c_str = PyBytes_AS_STRING(signature_as_bytes);
        switch (c_str[0]) {
            case DBUS_TYPE_BYTE:
            case DBUS_TYPE_BOOLEAN:
            case DBUS_TYPE_INT16:
            case DBUS_TYPE_UINT16:
            case DBUS_TYPE_INT32:
            case DBUS_TYPE_UINT32:
            case DBUS_TYPE_INT64:
            case DBUS_TYPE_UINT64:
            case DBUS_TYPE_DOUBLE:
#ifdef WITH_DBUS_FLOAT32
            case DBUS_TYPE_FLOAT:
#endif
#ifdef DBUS_TYPE_UNIX_FD
            case DBUS_TYPE_UNIX_FD:
#endif
            case DBUS_TYPE_STRING:
            case DBUS_TYPE_OBJECT_PATH:
            case DBUS_TYPE_SIGNATURE:
                break;
            default:
                Py_CLEAR(signature);
                Py_CLEAR(signature_as_bytes);
                PyErr_SetString(PyExc_ValueError,
                                "The key type in a Dictionary's signature "
                                "must be a primitive type");
                return -1;
        }

        if (!dbus_signature_validate_single(c_str + 1, NULL)) {
            Py_CLEAR(signature);
            Py_CLEAR(signature_as_bytes);
            PyErr_SetString(PyExc_ValueError,
                            "There must be exactly two complete types in "
                            "a Dictionary's signature parameter");
            return -1;
        }
        Py_CLEAR(signature_as_bytes);
    }

    tuple = Py_BuildValue("(O)", obj);
    if (!tuple) {
        Py_CLEAR(signature);
        return -1;
    }

    if ((PyDict_Type.tp_init((PyObject *)self, tuple, NULL)) < 0) {
        Py_CLEAR(tuple);
        Py_CLEAR(signature);
        return -1;
    }
    Py_CLEAR(tuple);

    Py_CLEAR(self->signature);
    self->signature = signature;
    return 0;
}
示例#6
0
static int
Array_tp_init (DBusPyArray *self, PyObject *args, PyObject *kwargs)
{
    PyObject *obj = dbus_py_empty_tuple;
    PyObject *signature = NULL;
    PyObject *tuple;
    PyObject *variant_level;
    /* variant_level is accepted but ignored - it's immutable, so
     * __new__ handles it */
    static char *argnames[] = {"iterable", "signature", "variant_level", NULL};

    if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OOO:__init__", argnames,
                                     &obj, &signature, &variant_level)) {
        return -1;
    }

  /* convert signature from a borrowed ref of unknown type to an owned ref
  of type Signature (or None) */
    if (!signature) signature = Py_None;
    if (signature == Py_None
        || PyObject_IsInstance(signature, (PyObject *)&DBusPySignature_Type)) {
        Py_INCREF(signature);
    }
    else {
        signature = PyObject_CallFunction((PyObject *)&DBusPySignature_Type,
                                          "(O)", signature);
        if (!signature) return -1;
    }

    if (signature != Py_None) {
        const char *c_str;
        PyObject *signature_as_bytes;

        if (
#ifdef PY3
            !PyUnicode_Check(signature)
#else
            !PyBytes_Check(signature)
#endif
            )
        {
            PyErr_SetString(PyExc_TypeError, "str expected");
            Py_CLEAR(signature);
            return -1;
        }
#ifdef PY3
        if (!(signature_as_bytes = PyUnicode_AsUTF8String(signature))) {
            Py_CLEAR(signature);
            return -1;
        }
#else
        signature_as_bytes = signature;
        Py_INCREF(signature_as_bytes);
#endif

        c_str = PyBytes_AS_STRING(signature_as_bytes);

        if (!dbus_signature_validate_single(c_str, NULL)) {
            Py_CLEAR(signature);
            Py_CLEAR(signature_as_bytes);
            PyErr_SetString(PyExc_ValueError,
                            "There must be exactly one complete type in "
                            "an Array's signature parameter");
            return -1;
        }
        Py_CLEAR(signature_as_bytes);
    }

    tuple = Py_BuildValue("(O)", obj);
    if (!tuple) {
        Py_CLEAR(signature);
        return -1;
    }
    if ((PyList_Type.tp_init)((PyObject *)self, tuple, NULL) < 0) {
        Py_CLEAR(tuple);
        Py_CLEAR(signature);
        return -1;
    }
    Py_CLEAR(tuple);

    Py_CLEAR(self->signature);
    self->signature = signature;
    return 0;
}
int bridge_request_dbus_params_element(bridge_request_t *self,
				       struct json_object *element,
				       DBusSignatureIter *sigIt,
				       DBusMessageIter *it)
{
	int type;
	int ret = 0;

	type = dbus_signature_iter_get_current_type(sigIt);

	if (dbus_type_is_basic(type)) {
		if ((ret = bridge_request_dbus_params_basic(self,
				 element, type, it)) != 0) {
			return ret;
		}
	}
	else if (type == DBUS_TYPE_VARIANT) {
		struct json_object *tmp;
		DBusMessageIter args;
		const char *vSig;

		if (json_object_get_type(element) != json_type_array) {
			bridge_request_error(self,
				"array expected.");
			return EINVAL;
		}
		tmp = json_object_array_get_idx(element, 0);
		if (!tmp) {
			bridge_request_error(self,
				"variant signature expected.");
			return EINVAL;
		}
		if (json_object_get_type(tmp) != json_type_string) {
			bridge_request_error(self,
				"variant signature expected.");
			return EINVAL;
		}
		vSig = json_object_get_string(tmp);
		if (!dbus_signature_validate_single(vSig, 0)) {
			bridge_request_error(self,
				"invalid variant signature.");
			return EINVAL;
		}
		dbus_message_iter_open_container(it, type,
			 vSig, &args);
		ret = bridge_request_dbus_params_array(self,
			element, 1, vSig, &args);
		dbus_message_iter_close_container(it, &args);
		if (ret != 0)
			return EINVAL;
	}
	else if (type == DBUS_TYPE_STRUCT) {
		DBusMessageIter args;
		DBusSignatureIter sigArgs;

		if (json_object_get_type(element) != json_type_array) {
			bridge_request_error(self, "array expected.");
			return EINVAL;
		}

		dbus_signature_iter_recurse(sigIt, &sigArgs);
		dbus_message_iter_open_container(it, 
			type, NULL, &args);
		ret = bridge_request_dbus_params_struct(self,
			element, &sigArgs, &args);
		dbus_message_iter_close_container(it, &args);
		if (ret != 0)
			return EINVAL;
	}
	else if (type == DBUS_TYPE_ARRAY) {
		DBusMessageIter args;
		DBusSignatureIter sigArgs;
		int cType;
		char *cSig;

		dbus_signature_iter_recurse(sigIt, &sigArgs);
		cType = dbus_signature_iter_get_current_type(&sigArgs);
		cSig = dbus_signature_iter_get_signature(&sigArgs);

		dbus_message_iter_open_container(it, type, cSig, &args);
		dbus_free(cSig);

		if (cType == DBUS_TYPE_DICT_ENTRY) {
			ret = bridge_request_dbus_params_dict(self,
				element, &sigArgs, &args);
		}
		else {
			int i, len;

			if (json_object_get_type(element) != json_type_array) {
				bridge_request_error(self,
					"array expected.");
				ret = EINVAL;
			}
			else {
				len = json_object_array_length(element);
				for (i = 0; i < len; ++i) {
					struct json_object *tmp;
					DBusSignatureIter tmpSigArgs = sigArgs;

					tmp = json_object_array_get_idx(element, i);
					if (!tmp) {
						bridge_request_error(self,
							"unexpected 'null' element in json array.");
						return EINVAL;
					}
					ret = bridge_request_dbus_params_element(self,
						tmp, &tmpSigArgs, &args);
				}
			}
		}
		dbus_message_iter_close_container(it, &args);
	}
	else {
		bridge_request_error(self,
			"unsupported json argument type.");
		return EINVAL;
	}
	return ret;
}
示例#8
0
//! Validates model file
int
db_validate_model(iks *xml, char *filename)
{
    /*!
     * Validates model file.
     *
     * @xml Iksemel document
     * @return 0 on success, -1 on error
     *
     */

    iks *iface, *met, *arg;

    DBusError bus_error;
    dbus_error_init(&bus_error);

    // Check root tag
    if (iks_strcmp(iks_name(xml), "comarModel") != 0) {
        log_error("Not a valid model XML: %s\n", filename);
        return -1;
    }

    for (iface = iks_first_tag(xml); iface; iface = iks_next_tag(iface)) {
        // Only "interface" tag is allowed
        if (iks_strcmp(iks_name(iface), "interface") != 0) {
            log_error("Unknown tag '%s' in XML: %s\n", iks_name(iface), filename);
            return -1;
        }
        // Interfaces must have a "name" attribute
        if (!iks_strlen(iks_find_attrib(iface, "name"))) {
            log_error("Model with no name in XML: %s\n", filename);
            return -1;
        }

        for (met = iks_first_tag(iface); met; met = iks_next_tag(met)) {
            // Only "method" and "signal" tags are allowed
            if (iks_strcmp(iks_name(met), "method") == 0 || iks_strcmp(iks_name(met), "signal") == 0) {
                // Tags must have a "name" attribute
                if (!iks_strlen(iks_find_attrib(met, "name"))) {
                    log_error("Method/Signal tag without name under '%s' in XML: %s\n", iks_find_attrib(iface, "name"), filename);
                    return -1;
                }
                for (arg = iks_first_tag(met); arg; arg = iks_next_tag(arg)) {
                    if (iks_strcmp(iks_name(arg), "arg") == 0) {
                        // Arguments must have a "name" attribute
                        if (!iks_strlen(iks_find_attrib(arg, "name"))) {
                            log_error("Argument tag with no name under '%s/%s' in XML: %s\n", iks_find_attrib(iface, "name"), iks_find_attrib(met, "name"), filename);
                            return -1;
                        }
                        // Arguments must have a "type" attribute
                        if (!iks_strlen(iks_find_attrib(arg, "type"))) {
                            log_error("Argument tag without type under '%s/%s' in XML: %s\n", iks_find_attrib(iface, "name"), iks_find_attrib(met, "name"), filename);
                            return -1;
                        }
                        // Types must be a valid DBus signature
                        if (!dbus_signature_validate(iks_find_attrib(arg, "type"), &bus_error)) {
                            dbus_error_free(&bus_error);
                            log_error("Argument tag with invalid type (%s/%s/%s) in XML: %s\n", iks_find_attrib(iface, "name"), iks_find_attrib(met, "name"), iks_find_attrib(arg, "name"), filename);
                            return -1;
                        }
                        // Types must be single type object
                        if (!dbus_signature_validate_single(iks_find_attrib(arg, "type"), &bus_error)) {
                            dbus_error_free(&bus_error);
                            log_error("Argument tag with a non-single element type (%s/%s/%s) in XML: %s\n", iks_find_attrib(iface, "name"), iks_find_attrib(met, "name"), iks_find_attrib(arg, "name"), filename);
                            return -1;
                        }
                    }
                    else if (iks_strcmp(iks_name(arg), "annotation") == 0) {
                        // Attributes must have a "name" attribute
                        if (!iks_strlen(iks_find_attrib(arg, "name"))) {
                            log_error("Annotation tag without name under '%s' in XML: %s\n", iks_find_attrib(iface, "name"), iks_find_attrib(met, "name"), filename);
                            return -1;
                        }
                    }
                    else {
                        log_error("Unknown tag '%s' under '%s/%s' in XML: %s\n", iks_name(arg), iks_find_attrib(iface, "name"), iks_find_attrib(met, "name"), filename);
                        return -1;
                    }
                }
            }
            else {
                log_error("Unknown tag '%s' under '%s' in XML: %s\n", iks_name(met), iks_find_attrib(iface, "name"), filename);
                return -1;
            }
        }
    }

    return 0;
}