# HG changeset patch
# Node ID 39d5eb52b86f3d0ea37c547bef4e765e0ef4de77
# Parent  c142ed0603da0f8cccaa138e59080c30bf74a5c4
diff --git a/libpurple/purpleattachment.h b/libpurple/purpleattachment.h
--- a/libpurple/purpleattachment.h
+++ b/libpurple/purpleattachment.h
@@ -47,17 +47,6 @@
 G_DECLARE_FINAL_TYPE(PurpleAttachment, purple_attachment, PURPLE, ATTACHMENT, GObject)
 
 /**
- * PurpleAttachmentForeachFunc:
- * @attachment: The #PurpleAttachment instance.
- * @data: User supplied data.
- *
- * Called when iterating #PurpleAttachment's.
- *
- * Since: 3.0
- */
-typedef void (*PurpleAttachmentForeachFunc)(PurpleAttachment *attachment, gpointer data);
-
-/**
  * purple_attachment_new:
  * @id: The identifier of the attachment.
  * @content_type: The mime-type of the content.
diff --git a/libpurple/purplemessage.c b/libpurple/purplemessage.c
--- a/libpurple/purplemessage.c
+++ b/libpurple/purplemessage.c
@@ -48,12 +48,13 @@
 	GDateTime *delivered_at;
 	GDateTime *edited_at;
 
-	GHashTable *attachments;
+	PurpleAttachments *attachments;
 };
 
 enum {
 	PROP_0,
 	PROP_ACTION,
+	PROP_ATTACHMENTS,
 	PROP_AUTHOR,
 	PROP_AUTHOR_NAME_COLOR,
 	PROP_CONTENTS,
@@ -98,6 +99,9 @@
 	case PROP_ACTION:
 		g_value_set_boolean(value, purple_message_get_action(message));
 		break;
+	case PROP_ATTACHMENTS:
+		g_value_set_object(value, purple_message_get_attachments(message));
+		break;
 	case PROP_AUTHOR:
 		g_value_set_object(value, purple_message_get_author(message));
 		break;
@@ -215,15 +219,14 @@
 	g_clear_pointer(&message->delivered_at, g_date_time_unref);
 	g_clear_pointer(&message->edited_at, g_date_time_unref);
 
-	g_hash_table_destroy(message->attachments);
+	g_clear_object(&message->attachments);
 
 	G_OBJECT_CLASS(purple_message_parent_class)->finalize(obj);
 }
 
 static void
 purple_message_init(PurpleMessage *message) {
-	message->attachments = g_hash_table_new_full(g_int64_hash, g_int64_equal,
-	                                             NULL, g_object_unref);
+	message->attachments = purple_attachments_new();
 }
 
 static void
@@ -252,6 +255,18 @@
 		G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
 
 	/**
+	 * PurpleMessage:attachments:
+	 *
+	 * The attachments for the message.
+	 *
+	 * Since: 3.0
+	 */
+	properties[PROP_ATTACHMENTS] = g_param_spec_object(
+		"attachments", NULL, NULL,
+		PURPLE_TYPE_ATTACHMENTS,
+		G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+	/**
 	 * PurpleMessage:author:
 	 *
 	 * The author of the message.
@@ -462,6 +477,13 @@
 	}
 }
 
+PurpleAttachments *
+purple_message_get_attachments(PurpleMessage *message) {
+	g_return_val_if_fail(PURPLE_IS_MESSAGE(message), NULL);
+
+	return message->attachments;
+}
+
 PurpleConversationMember *
 purple_message_get_author(PurpleMessage *message) {
 	g_return_val_if_fail(PURPLE_IS_MESSAGE(message), NULL);
@@ -731,63 +753,6 @@
 	return g_date_time_format(dt, format);
 }
 
-gboolean
-purple_message_add_attachment(PurpleMessage *message,
-                              PurpleAttachment *attachment)
-{
-	g_return_val_if_fail(PURPLE_IS_MESSAGE(message), FALSE);
-	g_return_val_if_fail(PURPLE_IS_ATTACHMENT(attachment), FALSE);
-
-	return g_hash_table_insert(message->attachments,
-	                           purple_attachment_get_hash_key(attachment),
-	                           g_object_ref(attachment));
-}
-
-gboolean
-purple_message_remove_attachment(PurpleMessage *message, guint64 id) {
-	g_return_val_if_fail(PURPLE_IS_MESSAGE(message), FALSE);
-
-	return g_hash_table_remove(message->attachments, &id);
-}
-
-PurpleAttachment *
-purple_message_get_attachment(PurpleMessage *message, guint64 id) {
-	PurpleAttachment *attachment = NULL;
-
-	g_return_val_if_fail(PURPLE_IS_MESSAGE(message), NULL);
-
-	attachment = g_hash_table_lookup(message->attachments, &id);
-	if(PURPLE_IS_ATTACHMENT(attachment)) {
-		return g_object_ref(attachment);
-	}
-
-	return NULL;
-}
-
-void
-purple_message_foreach_attachment(PurpleMessage *message,
-                                  PurpleAttachmentForeachFunc func,
-                                  gpointer data)
-{
-	GHashTableIter iter;
-	gpointer value;
-
-	g_return_if_fail(PURPLE_IS_MESSAGE(message));
-	g_return_if_fail(func != NULL);
-
-	g_hash_table_iter_init(&iter, message->attachments);
-	while(g_hash_table_iter_next(&iter, NULL, &value)) {
-		func(PURPLE_ATTACHMENT(value), data);
-	}
-}
-
-void
-purple_message_clear_attachments(PurpleMessage *message) {
-	g_return_if_fail(PURPLE_IS_MESSAGE(message));
-
-	g_hash_table_remove_all(message->attachments);
-}
-
 int
 purple_message_compare_timestamp(PurpleMessage *message1,
                                  PurpleMessage *message2)
diff --git a/libpurple/purplemessage.h b/libpurple/purplemessage.h
--- a/libpurple/purplemessage.h
+++ b/libpurple/purplemessage.h
@@ -30,6 +30,7 @@
 #include <glib-object.h>
 
 #include "purpleattachment.h"
+#include "purpleattachments.h"
 #include "purpleconversationmember.h"
 #include "purpleversion.h"
 
@@ -91,6 +92,18 @@
 void purple_message_set_action(PurpleMessage *message, gboolean action);
 
 /**
+ * purple_message_get_attachments:
+ *
+ * Gets the attachments for the message.
+ *
+ * Returns: (transfer none): The attachments for the message.
+ *
+ * Since: 3.0
+ */
+PURPLE_AVAILABLE_IN_3_0
+PurpleAttachments *purple_message_get_attachments(PurpleMessage *message);
+
+/**
  * purple_message_get_author:
  * @message: The message.
  *
@@ -472,74 +485,6 @@
 char *purple_message_format_timestamp(PurpleMessage *message, const char *format);
 
 /**
- * purple_message_add_attachment:
- * @message: The #PurpleMessage instance.
- * @attachment: The #PurpleAttachment instance.
- *
- * Adds @attachment to @message.
- *
- * Returns: %TRUE if an attachment with the same ID did not already exist.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-gboolean purple_message_add_attachment(PurpleMessage *message, PurpleAttachment *attachment);
-
-/**
- * purple_message_remove_attachment:
- * @message: The #PurpleMessage instance.
- * @id: The id of the #PurpleAttachment
- *
- * Removes the #PurpleAttachment identified by @id if it exists.
- *
- * Returns: %TRUE if the #PurpleAttachment was found and removed, %FALSE
- *          otherwise.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-gboolean purple_message_remove_attachment(PurpleMessage *message, guint64 id);
-
-/**
- * purple_message_get_attachment:
- * @message: The #PurpleMessage instance.
- * @id: The id of the #PurpleAttachment to get.
- *
- * Retrieves the #PurpleAttachment identified by @id from @message.
- *
- * Returns: (transfer full): The #PurpleAttachment if it was found, otherwise
- *                           %NULL.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-PurpleAttachment *purple_message_get_attachment(PurpleMessage *message, guint64 id);
-
-/**
- * purple_message_foreach_attachment:
- * @message: The #PurpleMessage instance.
- * @func: (scope call): The #PurpleAttachmentForeachFunc to call.
- * @data: User data to pass to @func.
- *
- * Calls @func for each #PurpleAttachment that's attached to @message.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-void purple_message_foreach_attachment(PurpleMessage *message, PurpleAttachmentForeachFunc func, gpointer data);
-
-/**
- * purple_message_clear_attachments:
- * @message: The #PurpleMessage instance.
- *
- * Removes all attachments from @message.
- *
- * Since: 3.0
- */
-PURPLE_AVAILABLE_IN_3_0
-void purple_message_clear_attachments(PurpleMessage *message);
-
-/**
  * purple_message_compare_timestamp:
  * @message1: (transfer none) (nullable): The first instance.
  * @message2: (transfer none) (nullable): The second instance.
diff --git a/libpurple/tests/test_message.c b/libpurple/tests/test_message.c
--- a/libpurple/tests/test_message.c
+++ b/libpurple/tests/test_message.c
@@ -38,6 +38,7 @@
  *****************************************************************************/
 static void
 test_purple_message_properties(void) {
+	PurpleAttachments *attachments = NULL;
 	PurpleContactInfo *info = NULL;
 	PurpleConversation *conversation = NULL;
 	PurpleConversationMember *author = NULL;
@@ -95,6 +96,7 @@
 	g_object_get(
 		message,
 		"action", &action,
+		"attachments", &attachments,
 		"author", &author1,
 		"author-name-color", &author_name_color,
 		"contents", &contents,
@@ -112,6 +114,9 @@
 
 	g_assert_true(action);
 
+	g_assert_true(PURPLE_IS_ATTACHMENTS(attachments));
+	g_clear_object(&attachments);
+
 	g_assert_true(author1 == author);
 	g_clear_object(&author1);
 
