diff --git a/.gitignore b/.gitignore index c648730..5dd5799 100644 --- a/.gitignore +++ b/.gitignore @@ -54,7 +54,6 @@ Makefile.in /src/matrix-event-room-message.c /src/namespace-info.vala /src/namespace-info.c -/src/matrix-event-room-aliases.c /src/matrix-event-room-history-visibility.c /src/matrix-event-room-join-rules.c /src/matrix-event-room-name.c diff --git a/src/Makefile.am b/src/Makefile.am index 253e902..1ecda61 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -22,7 +22,6 @@ libmatrix_glib_0_0_la_VALA_SOURCES = \ matrix-http-api.vala \ matrix-http-client.vala \ matrix-event-room-message.vala \ - matrix-event-room-aliases.vala \ matrix-event-room-history-visibility.vala \ matrix-event-room-join-rules.vala \ matrix-event-room-name.vala \ @@ -111,6 +110,7 @@ INST_H_SRC_FILES = \ matrix-event-presence.h \ matrix-event-room-member.h \ matrix-event-room-topic.h \ + matrix-event-room-aliases.h \ matrix-event-typing.h \ matrix-event-receipt.h \ utils.h \ @@ -144,6 +144,7 @@ libmatrix_glib_0_0_la_SOURCES = \ matrix-event-state-base.c \ matrix-event-receipt.c \ matrix-event-room-topic.c \ + matrix-event-room-aliases.c \ matrix-profile.c \ utils.c \ matrix-enumtypes.c \ diff --git a/src/matrix-event-room-aliases.c b/src/matrix-event-room-aliases.c new file mode 100644 index 0000000..0535574 --- /dev/null +++ b/src/matrix-event-room-aliases.c @@ -0,0 +1,292 @@ +/* + * This file is part of matrix-glib-sdk + * + * matrix-glib-sdk is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * matrix-glib-sdk is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with matrix-glib-sdk. If not, see + * . + */ + +#include "matrix-event-room-aliases.h" +#include "matrix-types.h" +#include "config.h" + +/** + * SECTION:matrix-event-room-aliases + * @short_description: event to list the aliases of a room + * + * This is the default event handler for `m.room.aliases` events. + * + * This event is sent by a homeserver directly to inform of changes to the list of aliases it + * knows about for that room. + * + * The state_key for this event is set to the homeserver which owns the room alias. + * + * The entire set of known aliases for the room is the union of all the `m.room.aliases` + * events, one for each homeserver. Clients should check the validity of any room alias given + * in this list before presenting it to the user as trusted fact. The lists given by this + * event should be considered simply as advice on which aliases might exist, for which the + * client can perform the lookup to confirm whether it receives the correct room ID. + */ +enum { + PROP_0, + PROP_ALIASES, + NUM_PROPS +}; + +static GParamSpec* matrix_event_room_aliases_properties[NUM_PROPS]; + +typedef struct { + gchar** _aliases; + gint _aliases_len; + gint __aliases_size_; +} MatrixEventRoomAliasesPrivate; + +/** + * MatrixEventRoomAliases: + */ +G_DEFINE_TYPE_WITH_PRIVATE(MatrixEventRoomAliases, matrix_event_room_aliases, MATRIX_EVENT_TYPE_STATE); + +static void +matrix_event_room_aliases_real_from_json(MatrixEventBase *matrix_event_base, JsonNode *json_data, GError **error) +{ + MatrixEventRoomAliasesPrivate *priv; + JsonObject *root; + JsonObject *content_root; + JsonNode *content_node; + JsonNode *node; + GError *inner_error = NULL; + + g_return_if_fail (json_data != NULL); + + priv = matrix_event_room_aliases_get_instance_private(MATRIX_EVENT_ROOM_ALIASES(matrix_event_base)); + root = json_node_get_object(json_data); + content_node = json_object_get_member(root, "content"); + content_root = json_node_get_object(content_node); + + if ((node = json_object_get_member(content_root, "aliases")) != NULL) { + JsonArray *aliases; + gint n_aliases; + + aliases = json_node_get_array(node); + n_aliases = json_array_get_length(aliases); + + for (gint i = 0; i < priv->_aliases_len; i++) { + g_free(priv->_aliases[i]); + } + g_free(priv->_aliases); + + priv->_aliases = g_new(gchar *, n_aliases); + + for (gint i = 0; i < n_aliases; i++) { + JsonNode *element = json_array_get_element(aliases, i); + + priv->_aliases[i] = g_strdup(json_node_get_string(element)); + } + } else if (DEBUG) { + g_warning("content.aliases is missing from a m.room.aliases event"); + } + + MATRIX_EVENT_BASE_CLASS(matrix_event_room_aliases_parent_class)->from_json(matrix_event_base, json_data, &inner_error); + + if (inner_error != NULL) { + g_propagate_error(error, inner_error); + } +} + +static void +matrix_event_room_aliases_real_to_json(MatrixEventBase *matrix_event_base, JsonNode *json_data, GError **error) +{ + MatrixEventRoomAliasesPrivate *priv; + JsonObject *root; + JsonObject *content_root; + JsonArray *aliases_ary; + JsonNode *content_node; + JsonNode *aliases_node; + GError *inner_error = NULL; + + priv = matrix_event_room_aliases_get_instance_private(MATRIX_EVENT_ROOM_ALIASES(matrix_event_base)); + + if (priv->_aliases_len == 0) { + g_set_error(error, MATRIX_ERROR, MATRIX_ERROR_INCOMPLETE, + "Won't generate a m.room.aliases event without aliases"); + + return; + } + + root = json_node_get_object(json_data); + content_node = json_object_get_member(root, "content"); + content_root = json_node_get_object(content_node); + + aliases_ary = json_array_new(); + + for (gint i = 0; i < priv->_aliases_len; i++) { + json_array_add_string_element(aliases_ary, priv->_aliases[i]); + } + + aliases_node = json_node_new(JSON_TYPE_ARRAY); + json_node_set_array(aliases_node, aliases_ary); + json_object_set_member(content_root, "aliases", aliases_node); + + MATRIX_EVENT_BASE_CLASS(matrix_event_room_aliases_parent_class)->to_json(matrix_event_base, json_data, &inner_error); + + if (inner_error != NULL) { + g_propagate_error(error, inner_error); + } +} + +/** + * matrix_event_room_aliases_new: + * + * Create a new #MatrixEventRoomAliases object. + * + * Returns: (transfer full): a new #MatrixEventRoomAliases object + */ +MatrixEventRoomAliases * +matrix_event_room_aliases_new(void) +{ + return (MatrixEventRoomAliases *)matrix_event_state_construct(MATRIX_EVENT_TYPE_ROOM_ALIASES); +} + +/** + * matrix_event_room_aliases_get_aliases: + * @event: a MatrixEventRoomAliases + * @n_aliases: placeholder for the length of the list, or %NULL to ignore + * + * Get the list of aliases from @event. + * + * The returned value is owned by @event and should not be freed. + * + * Returns: (transfer none) (nullable): the list of aliases + */ +const gchar ** +matrix_event_room_aliases_get_aliases(MatrixEventRoomAliases *matrix_event_room_aliases, int *n_aliases) +{ + MatrixEventRoomAliasesPrivate *priv; + + g_return_val_if_fail(matrix_event_room_aliases != NULL, NULL); + + priv = matrix_event_room_aliases_get_instance_private(matrix_event_room_aliases); + + if (n_aliases != NULL) { + *n_aliases = priv->_aliases_len; + } + + return (const gchar **)priv->_aliases; +} + +/** + * matrix_event_room_aliases_set_aliases: + * @event: a #MatrixEventRoomAliases + * @aliases: a list of aliases + * @n_aliases: the length of @aliases + * + * Set the list of aliases in @event. + */ +void +matrix_event_room_aliases_set_aliases(MatrixEventRoomAliases *matrix_event_room_aliases, const gchar **aliases, int n_aliases) +{ + MatrixEventRoomAliasesPrivate *priv; + + g_return_if_fail(matrix_event_room_aliases != NULL); + + priv = matrix_event_room_aliases_get_instance_private(matrix_event_room_aliases); + + for (gint i = 0; i < priv->_aliases_len; i++) { + g_free(priv->_aliases[i]); + } + + g_free(priv->_aliases); + priv->_aliases = g_new(gchar *, n_aliases); + + for (gint i = 0; i < n_aliases; i++) { + priv->_aliases[i] = g_strdup(aliases[i]); + } +} + +static void +matrix_event_room_aliases_finalize(GObject *gobject) +{ + MatrixEventRoomAliasesPrivate *priv = matrix_event_room_aliases_get_instance_private(MATRIX_EVENT_ROOM_ALIASES(gobject)); + + for (gint i = 0; i < priv->_aliases_len; i++) { + g_free(priv->_aliases[i]); + } + + g_free(priv->_aliases); + + G_OBJECT_CLASS(matrix_event_room_aliases_parent_class)->finalize(gobject); +} + +static void +matrix_event_room_aliases_get_property(GObject *gobject, guint property_id, GValue *value, GParamSpec *pspec) +{ + MatrixEventRoomAliases *self = MATRIX_EVENT_ROOM_ALIASES(gobject); + + switch (property_id) { + case PROP_ALIASES: + g_value_set_boxed(value, matrix_event_room_aliases_get_aliases(self, NULL)); + + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, property_id, pspec); + + break; + } +} + +static void +matrix_event_room_aliases_set_property(GObject *gobject, guint property_id, const GValue *value, GParamSpec *pspec) +{ + MatrixEventRoomAliases *self = MATRIX_EVENT_ROOM_ALIASES(gobject); + + switch (property_id) { + case PROP_ALIASES: + { + gpointer boxed; + + boxed = g_value_get_boxed(value); + matrix_event_room_aliases_set_aliases(self, boxed, (boxed == NULL) ? 0 : g_strv_length (boxed)); + + break; + } + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID(gobject, property_id, pspec); + + break; + } +} + +static void +matrix_event_room_aliases_class_init(MatrixEventRoomAliasesClass *klass) +{ + ((MatrixEventBaseClass *)klass)->from_json = matrix_event_room_aliases_real_from_json; + ((MatrixEventBaseClass *)klass)->to_json = matrix_event_room_aliases_real_to_json; + G_OBJECT_CLASS (klass)->get_property = matrix_event_room_aliases_get_property; + G_OBJECT_CLASS (klass)->set_property = matrix_event_room_aliases_set_property; + G_OBJECT_CLASS (klass)->finalize = matrix_event_room_aliases_finalize; + + /** + * MatrixEventRoomAliases:aliases: + * + * A list of room aliases. + */ + matrix_event_room_aliases_properties[PROP_ALIASES] = g_param_spec_boxed( + "aliases", "aliases", "aliases", + G_TYPE_STRV, + G_PARAM_STATIC_STRINGS | G_PARAM_READWRITE); + g_object_class_install_property(G_OBJECT_CLASS(klass), PROP_ALIASES, matrix_event_room_aliases_properties[PROP_ALIASES]); +} + +static void +matrix_event_room_aliases_init(MatrixEventRoomAliases *matrix_event_room_aliases) +{} diff --git a/src/matrix-event-room-aliases.h b/src/matrix-event-room-aliases.h new file mode 100644 index 0000000..180b3bc --- /dev/null +++ b/src/matrix-event-room-aliases.h @@ -0,0 +1,40 @@ +/* + * This file is part of matrix-glib-sdk + * + * matrix-glib-sdk is free software: you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation, either + * version 3 of the License, or (at your option) any later version. + * + * matrix-glib-sdk is distributed in the hope that it will be + * useful, but WITHOUT ANY WARRANTY; without even the implied + * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with matrix-glib-sdk. If not, see + * . + */ + +#ifndef __MATRIX_GLIB_SDK_EVENT_ROOM_ALIASES_H__ +# define __MATRIX_GLIB_SDK_EVENT_ROOM_ALIASES_H__ + +# include +# include "matrix-event-state-base.h" + +G_BEGIN_DECLS + +# define MATRIX_EVENT_TYPE_ROOM_ALIASES matrix_event_room_aliases_get_type() +G_DECLARE_DERIVABLE_TYPE(MatrixEventRoomAliases, matrix_event_room_aliases, MATRIX_EVENT, ROOM_ALIASES, MatrixEventState) + +struct _MatrixEventRoomAliasesClass { + MatrixEventStateClass parent_class; +}; + +MatrixEventRoomAliases* matrix_event_room_aliases_new (void); +const gchar** matrix_event_room_aliases_get_aliases (MatrixEventRoomAliases *event, int *n_aliases); +void matrix_event_room_aliases_set_aliases (MatrixEventRoomAliases *event, const gchar **aliases, int n_aliases); + +G_END_DECLS + +#endif /* __MATRIX_GLIB_SDK_EVENT_ROOM_ALIASES_H__ */ diff --git a/src/matrix-event-room-aliases.vala b/src/matrix-event-room-aliases.vala deleted file mode 100644 index a93b8f4..0000000 --- a/src/matrix-event-room-aliases.vala +++ /dev/null @@ -1,87 +0,0 @@ -/* - * This file is part of matrix-glib-sdk - * - * matrix-glib-sdk is free software: you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation, either - * version 3 of the License, or (at your option) any later version. - * - * matrix-glib-sdk is distributed in the hope that it will be - * useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with matrix-glib-sdk. If not, see - * . - */ - -/** - * Class to hold a m.room.aliases event. - * - * This event is sent by a homeserver directly to inform of changes to - * the list of aliases it knows about for that room. - * - * The state_key for this event is set to the homeserver which owns - * the room alias. - * - * The entire set of known aliases for the room is the union of all - * the m.room.aliases events, one for each homeserver. Clients should - * check the validity of any room alias given in this list before - * presenting it to the user as trusted fact. The lists given by this - * event should be considered simply as advice on which aliases might - * exist, for which the client can perform the lookup to confirm - * whether it receives the correct room ID. - */ -public class Matrix.Event.RoomAliases : Matrix.Event.State { - /** - * A list of room aliases. - */ - public string[] aliases { get; set; } - - protected override void - from_json(Json.Node json_data) - throws Matrix.Error - { - var content_root = json_data.get_object() - .get_member("content").get_object(); - Json.Node? node; - - if ((node = content_root.get_member("aliases")) != null) { - _aliases = new string[node.get_array().get_length()]; - - node.get_array().foreach_element((ary, idx, member_node) => { - _aliases[idx] = member_node.get_string(); - }); - } else if (Config.DEBUG) { - warning("content.aliases is missing from a m.room.aliases event"); - } - - base.from_json(json_data); - } - - protected override void - to_json(Json.Node json_data) - throws Matrix.Error - { - if (_aliases.length == 0) { - throw new Matrix.Error.INCOMPLETE( - "Won't generate a m.room.aliases event without aliases"); - } - - var content_root = json_data.get_object() - .get_member("content").get_object(); - - var aliases_ary = new Json.Array(); - - foreach (var entry in _aliases) { - aliases_ary.add_string_element(entry); - } - - var aliases_node = new Json.Node(Json.NodeType.ARRAY); - aliases_node.set_array(aliases_ary); - content_root.set_member("aliases", aliases_node); - - base.to_json(json_data); - } -} diff --git a/src/matrix-event-types.c b/src/matrix-event-types.c index f749728..8415232 100644 --- a/src/matrix-event-types.c +++ b/src/matrix-event-types.c @@ -24,6 +24,7 @@ #include "matrix-event-room-member.h" #include "matrix-event-receipt.h" #include "matrix-event-room-topic.h" +#include "matrix-event-room-aliases.h" /* Borrowed from GLib diff --git a/vapi/c-api.vapi b/vapi/c-api.vapi index 0de9211..93fc167 100644 --- a/vapi/c-api.vapi +++ b/vapi/c-api.vapi @@ -593,5 +593,16 @@ namespace Matrix { protected override void to_json(Json.Node json_data) throws Matrix.Error; } + + [CCode (cheader_filename = "matrix-event-room-aliases.h")] + public class RoomAliases : State { + public string[] aliases { get; set; } + + protected override void from_json(Json.Node json_data) + throws Matrix.Error; + + protected override void to_json(Json.Node json_data) + throws Matrix.Error; + } } }