pidgin/pidgin

PurpleMessage cleanups from hell

2020-10-03, Gary Kramlich
9ceb8d25d4d9
Parents 168407b6f9fd
Children 8079731c8ef9
PurpleMessage cleanups from hell

Clean up libpurple/message.[ch] and remove the messages hash table as its current implementation will not fit our future needs

add a content-type property to PurpleMessage

Convert message timestamps from time_t to GDateTime and set default values

Make purple_message_new_outgoing take a parameter for the author.

Testing Done:
messages sent on bonjour, irc privmsg, irc chat, `/me` is broken i think unrelated.

Reviewed at https://reviews.imfreedom.org/r/124/
--- a/finch/gntconv.c Sun Sep 27 21:13:04 2020 -0500
+++ b/finch/gntconv.c Sat Oct 03 05:58:21 2020 -0500
@@ -902,11 +902,14 @@
/* Unnecessary to print the timestamp for delayed message */
if (purple_prefs_get_bool("/finch/conversations/timestamps")) {
- time_t mtime = purple_message_get_time(msg);
- if (!mtime)
- time(&mtime);
+ gchar *timestamp = NULL;
+
+ timestamp = purple_message_format_timestamp(msg, "(%H:%M:%S)");
+
gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(ggconv->tv),
- purple_utf8_strftime("(%H:%M:%S)", localtime(&mtime)), gnt_color_pair(color_timestamp));
+ timestamp,
+ gnt_color_pair(color_timestamp));
+ g_free(timestamp);
}
gnt_text_view_append_text_with_flags(GNT_TEXT_VIEW(ggconv->tv), " ", GNT_TEXT_FLAG_NORMAL);
--- a/finch/gntpounce.c Sun Sep 27 21:13:04 2020 -0500
+++ b/finch/gntpounce.c Sat Oct 03 05:58:21 2020 -0500
@@ -843,15 +843,18 @@
if (message != NULL)
{
PurpleMessage *pmsg;
+ const gchar *me = purple_account_get_name_for_display(account);
im = purple_conversations_find_im_with_account(pouncee, account);
- if (im == NULL)
+ if (im == NULL) {
im = purple_im_conversation_new(account, pouncee);
+ }
- pmsg = purple_message_new_outgoing(pouncee, message, 0);
+ pmsg = purple_message_new_outgoing(me, pouncee, message, 0);
purple_serv_send_im(purple_account_get_connection(account), pmsg);
purple_conversation_write_message(PURPLE_CONVERSATION(im), pmsg);
+ g_object_unref(G_OBJECT(pmsg));
}
}
--- a/libpurple/conversation.c Sun Sep 27 21:13:04 2020 -0500
+++ b/libpurple/conversation.c Sat Oct 03 05:58:21 2020 -0500
@@ -87,9 +87,8 @@
PurpleConnection *gc;
PurpleConversationPrivate *priv =
purple_conversation_get_instance_private(conv);
- PurpleMessage *msg;
char *displayed = NULL;
- const char *sent;
+ const char *sent, *me;
int err = 0;
if (*message == '\0')
@@ -101,6 +100,8 @@
gc = purple_account_get_connection(account);
g_return_if_fail(PURPLE_IS_CONNECTION(gc));
+ me = purple_account_get_name_for_display(account);
+
/* Always linkfy the text for display, unless we're
* explicitly asked to do otheriwse*/
if (!(msgflags & PURPLE_MESSAGE_INVISIBLE)) {
@@ -119,7 +120,7 @@
msgflags |= PURPLE_MESSAGE_SEND;
if (PURPLE_IS_IM_CONVERSATION(conv)) {
- msg = purple_message_new_outgoing(
+ PurpleMessage *msg = purple_message_new_outgoing(me,
purple_conversation_get_name(conv), sent, msgflags);
purple_signal_emit(purple_conversations_get_handle(), "sending-im-msg",
@@ -138,11 +139,14 @@
purple_signal_emit(purple_conversations_get_handle(),
"sent-im-msg", account, msg);
}
+
+ g_object_unref(G_OBJECT(msg));
}
else if (PURPLE_IS_CHAT_CONVERSATION(conv)) {
+ PurpleMessage *msg;
int id = purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(conv));
- msg = purple_message_new_outgoing(NULL, sent, msgflags);
+ msg = purple_message_new_outgoing(me, NULL, sent, msgflags);
purple_signal_emit(purple_conversations_get_handle(),
"sending-chat-msg", account, msg, id);
@@ -153,6 +157,8 @@
purple_signal_emit(purple_conversations_get_handle(),
"sent-chat-msg", account, msg, id);
}
+
+ g_object_unref(G_OBJECT(msg));
}
if (err < 0) {
@@ -558,7 +564,7 @@
GList *log;
GDateTime *dt;
- dt = g_date_time_new_from_unix_local(purple_message_get_time(pmsg));
+ dt = g_date_time_ref(purple_message_get_timestamp(pmsg));
log = priv->logs;
while (log != NULL) {
purple_log_write((PurpleLog *)log->data,
--- a/libpurple/core.c Sun Sep 27 21:13:04 2020 -0500
+++ b/libpurple/core.c Sat Oct 03 05:58:21 2020 -0500
@@ -171,7 +171,6 @@
purple_accounts_init();
purple_savedstatuses_init();
purple_notify_init();
- _purple_message_init();
purple_conversations_init();
purple_blist_init();
purple_log_init();
@@ -251,7 +250,6 @@
purple_cmds_uninit();
purple_log_uninit();
- _purple_message_uninit();
/* Everything after util_uninit cannot try to write things to the
* confdir.
*/
--- a/libpurple/example/nullclient.c Sun Sep 27 21:13:04 2020 -0500
+++ b/libpurple/example/nullclient.c Sat Oct 03 05:58:21 2020 -0500
@@ -40,13 +40,15 @@
static void
null_write_conv(PurpleConversation *conv, PurpleMessage *msg)
{
- time_t mtime = purple_message_get_time(msg);
+ gchar *timestamp = purple_message_format_timestamp(msg, "(%H:%M:%S)");
printf("(%s) %s %s: %s\n",
purple_conversation_get_name(conv),
- purple_utf8_strftime("(%H:%M:%S)", localtime(&mtime)),
+ timestamp,
purple_message_get_author_alias(msg),
purple_message_get_contents(msg));
+
+ g_free(timestamp);
}
static PurpleConversationUiOps null_conv_uiops =
--- a/libpurple/message.c Sun Sep 27 21:13:04 2020 -0500
+++ b/libpurple/message.c Sat Oct 03 05:58:21 2020 -0500
@@ -33,259 +33,513 @@
*
* A message data container.
*/
-struct _PurpleMessage
-{
+struct _PurpleMessage {
GObject parent;
-};
-typedef struct {
guint id;
gchar *author;
gchar *author_alias;
gchar *recipient;
+
gchar *contents;
- guint64 msgtime;
+ PurpleMessageContentType content_type;
+
+ GDateTime *timestamp;
PurpleMessageFlags flags;
GHashTable *attachments;
-} PurpleMessagePrivate;
+};
-enum
-{
+enum {
PROP_0,
PROP_ID,
PROP_AUTHOR,
PROP_AUTHOR_ALIAS,
PROP_RECIPIENT,
PROP_CONTENTS,
- PROP_TIME,
+ PROP_CONTENT_TYPE,
+ PROP_TIMESTAMP,
PROP_FLAGS,
- PROP_LAST
+ N_PROPERTIES
};
+static GParamSpec *properties[N_PROPERTIES];
+
+G_DEFINE_TYPE(PurpleMessage, purple_message, G_TYPE_OBJECT)
-static GParamSpec *properties[PROP_LAST];
+/******************************************************************************
+ * Helpers
+ *****************************************************************************/
+static void
+purple_message_set_id(PurpleMessage *message, guint id) {
+ message->id = id;
-static GHashTable *messages = NULL;
+ g_object_notify_by_pspec(G_OBJECT(message), properties[PROP_ID]);
+}
-G_DEFINE_TYPE_WITH_PRIVATE(PurpleMessage, purple_message, G_TYPE_OBJECT)
+static void
+purple_message_set_author(PurpleMessage *message, const gchar *author) {
+ g_free(message->author);
+ message->author = g_strdup(author);
+
+ g_object_notify_by_pspec(G_OBJECT(message), properties[PROP_AUTHOR]);
+}
/******************************************************************************
- * API implementation
- ******************************************************************************/
+ * GObject Implementation
+ *****************************************************************************/
+static void
+purple_message_get_property(GObject *object, guint param_id, GValue *value,
+ GParamSpec *pspec)
+{
+ PurpleMessage *message = PURPLE_MESSAGE(object);
+
+ switch(param_id) {
+ case PROP_ID:
+ g_value_set_uint(value, purple_message_get_id(message));
+ break;
+ case PROP_AUTHOR:
+ g_value_set_string(value, purple_message_get_author(message));
+ break;
+ case PROP_AUTHOR_ALIAS:
+ g_value_set_string(value, purple_message_get_author_alias(message));
+ break;
+ case PROP_RECIPIENT:
+ g_value_set_string(value, purple_message_get_recipient(message));
+ break;
+ case PROP_CONTENTS:
+ g_value_set_string(value, purple_message_get_contents(message));
+ break;
+ case PROP_CONTENT_TYPE:
+ g_value_set_enum(value, purple_message_get_content_type(message));
+ break;
+ case PROP_TIMESTAMP:
+ g_value_set_boxed(value, purple_message_get_timestamp(message));
+ break;
+ case PROP_FLAGS:
+ g_value_set_flags(value, purple_message_get_flags(message));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+purple_message_set_property(GObject *object, guint param_id,
+ const GValue *value, GParamSpec *pspec)
+{
+ PurpleMessage *message = PURPLE_MESSAGE(object);
+
+ switch(param_id) {
+ case PROP_ID:
+ purple_message_set_id(message, g_value_get_uint(value));
+ break;
+ case PROP_AUTHOR:
+ purple_message_set_author(message, g_value_get_string(value));
+ break;
+ case PROP_AUTHOR_ALIAS:
+ purple_message_set_author_alias(message, g_value_get_string(value));
+ break;
+ case PROP_RECIPIENT:
+ purple_message_set_recipient(message, g_value_get_string(value));
+ break;
+ case PROP_CONTENTS:
+ purple_message_set_contents(message, g_value_get_string(value));
+ break;
+ case PROP_CONTENT_TYPE:
+ purple_message_set_content_type(message, g_value_get_enum(value));
+ break;
+ case PROP_TIMESTAMP:
+ purple_message_set_timestamp(message, g_value_get_boxed(value));
+ break;
+ case PROP_FLAGS:
+ purple_message_set_flags(message, g_value_get_flags(value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID(object, param_id, pspec);
+ break;
+ }
+}
+
+static void
+purple_message_finalize(GObject *obj) {
+ PurpleMessage *message = PURPLE_MESSAGE(obj);
+
+ g_free(message->author);
+ g_free(message->author_alias);
+ g_free(message->recipient);
+ g_free(message->contents);
+
+ if(message->timestamp != NULL) {
+ g_date_time_unref(message->timestamp);
+ }
+
+ g_hash_table_destroy(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);
+}
+static void
+purple_message_class_init(PurpleMessageClass *klass) {
+ GObjectClass *obj_class = G_OBJECT_CLASS(klass);
+
+ obj_class->get_property = purple_message_get_property;
+ obj_class->set_property = purple_message_set_property;
+ obj_class->finalize = purple_message_finalize;
+
+ /**
+ * PurpleMessage::id:
+ *
+ * The account specific identifier of the message.
+ */
+ properties[PROP_ID] = g_param_spec_uint(
+ "id", "ID",
+ "The session-unique message id",
+ 0, G_MAXUINT, 0,
+ G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * PurpleMessage::author:
+ *
+ * The author of the message.
+ */
+ properties[PROP_AUTHOR] = g_param_spec_string(
+ "author", "Author",
+ "The username of the person, who sent the message.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * PurpleMessage::author-alias:
+ *
+ * The alias of the author.
+ */
+ properties[PROP_AUTHOR_ALIAS] = g_param_spec_string(
+ "author-alias", "Author's alias",
+ "The alias of the sender",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * PurpleMessage::recipient:
+ *
+ * The recipient of the message.
+ */
+ properties[PROP_RECIPIENT] = g_param_spec_string(
+ "recipient", "Recipient",
+ "The username of the recipient.",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * PurpleMessage::content:
+ *
+ * The contents of the message.
+ */
+ properties[PROP_CONTENTS] = g_param_spec_string(
+ "contents", "Contents",
+ "The message text",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * PurpleMessage::content-type:
+ *
+ * The content-type of the message.
+ */
+ properties[PROP_CONTENT_TYPE] = g_param_spec_enum(
+ "content-type", "content-type",
+ "The content-type of the message.",
+ PURPLE_TYPE_MESSAGE_CONTENT_TYPE, PURPLE_MESSAGE_CONTENT_TYPE_PLAIN,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * PurpleMessage::timestamp:
+ *
+ * The timestamp of the message.
+ */
+ properties[PROP_TIMESTAMP] = g_param_spec_boxed(
+ "timestamp", "timestamp",
+ "The timestamp of the message",
+ G_TYPE_DATE_TIME,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ /**
+ * PurpleMessage::flags:
+ *
+ * The #PurpleMessageFlags for the message.
+ */
+ properties[PROP_FLAGS] = g_param_spec_flags(
+ "flags", "Flags",
+ "Bitwise set of #PurpleMessageFlags flags",
+ PURPLE_TYPE_MESSAGE_FLAGS, 0,
+ G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
+
+ g_object_class_install_properties(obj_class, N_PROPERTIES, properties);
+}
+
+/******************************************************************************
+ * Public API
+ *****************************************************************************/
PurpleMessage *
-purple_message_new_outgoing(const gchar *who, const gchar *contents,
- PurpleMessageFlags flags)
+purple_message_new_outgoing(const gchar *author, const gchar *recipient,
+ const gchar *contents, PurpleMessageFlags flags)
{
+ PurpleMessage *message = NULL;
+ GDateTime *dt = NULL;
+
g_warn_if_fail(!(flags & PURPLE_MESSAGE_RECV));
g_warn_if_fail(!(flags & PURPLE_MESSAGE_SYSTEM));
flags |= PURPLE_MESSAGE_SEND;
+ dt = g_date_time_new_now_local();
/* who may be NULL for outgoing MUC messages */
- return g_object_new(PURPLE_TYPE_MESSAGE,
- "author-alias", _("Me"),
- "recipient", who,
+ message = PURPLE_MESSAGE(g_object_new(PURPLE_TYPE_MESSAGE,
+ "author", author,
+ "recipient", recipient,
"contents", contents,
- "time", (guint64)time(NULL),
+ "timestamp", dt,
"flags", flags,
- NULL);
+ NULL));
+
+ g_date_time_unref(dt);
+
+ return message;
}
PurpleMessage *
purple_message_new_incoming(const gchar *who, const gchar *contents,
- PurpleMessageFlags flags, guint64 timestamp)
+ PurpleMessageFlags flags, guint64 timestamp)
{
+ PurpleMessage *message = NULL;
+ GDateTime *dt = NULL;
+
g_warn_if_fail(!(flags & PURPLE_MESSAGE_SEND));
g_warn_if_fail(!(flags & PURPLE_MESSAGE_SYSTEM));
flags |= PURPLE_MESSAGE_RECV;
- if (timestamp == 0)
- timestamp = time(NULL);
+ if(timestamp == 0) {
+ dt = g_date_time_new_now_local();
+ } else {
+ dt = g_date_time_new_from_unix_local((gint64)timestamp);
+ }
- return g_object_new(PURPLE_TYPE_MESSAGE,
+ message = PURPLE_MESSAGE(g_object_new(PURPLE_TYPE_MESSAGE,
"author", who,
"author-alias", who,
"contents", contents,
- "time", timestamp,
+ "timestamp", dt,
"flags", flags,
- NULL);
+ NULL));
+
+ g_date_time_unref(dt);
+
+ return message;
}
PurpleMessage *
-purple_message_new_system(const gchar *contents, PurpleMessageFlags flags)
-{
+purple_message_new_system(const gchar *contents, PurpleMessageFlags flags) {
+ PurpleMessage *message = NULL;
+ GDateTime *dt = NULL;
+
g_warn_if_fail(!(flags & PURPLE_MESSAGE_SEND));
g_warn_if_fail(!(flags & PURPLE_MESSAGE_RECV));
flags |= PURPLE_MESSAGE_SYSTEM;
+ dt = g_date_time_new_now_local();
- return g_object_new(PURPLE_TYPE_MESSAGE,
+ message = PURPLE_MESSAGE(g_object_new(PURPLE_TYPE_MESSAGE,
"contents", contents,
- "time", (guint64)time(NULL),
+ "timestamp", dt,
"flags", flags,
- NULL);
+ NULL));
+
+ g_date_time_unref(dt);
+
+ return message;
}
guint
-purple_message_get_id(PurpleMessage *msg)
-{
- PurpleMessagePrivate *priv = NULL;
+purple_message_get_id(PurpleMessage *message) {
+ g_return_val_if_fail(PURPLE_IS_MESSAGE(message), 0);
- g_return_val_if_fail(PURPLE_IS_MESSAGE(msg), 0);
-
- priv = purple_message_get_instance_private(msg);
- return priv->id;
+ return message->id;
}
-PurpleMessage *
-purple_message_find_by_id(guint id)
-{
- g_return_val_if_fail(id > 0, NULL);
+const gchar *
+purple_message_get_author(PurpleMessage *message) {
+ g_return_val_if_fail(PURPLE_IS_MESSAGE(message), NULL);
+
+ return message->author;
+}
- return g_hash_table_lookup(messages, GINT_TO_POINTER(id));
+void
+purple_message_set_recipient(PurpleMessage *message, const gchar *recipient) {
+ g_return_if_fail(PURPLE_IS_MESSAGE(message));
+
+ g_free(message->recipient);
+ message->recipient = g_strdup(recipient);
+
+ g_object_notify_by_pspec(G_OBJECT(message), properties[PROP_RECIPIENT]);
}
const gchar *
-purple_message_get_author(PurpleMessage *msg)
-{
- PurpleMessagePrivate *priv = NULL;
+purple_message_get_recipient(PurpleMessage *message) {
+ g_return_val_if_fail(PURPLE_IS_MESSAGE(message), NULL);
+
+ return message->recipient;
+}
- g_return_val_if_fail(PURPLE_IS_MESSAGE(msg), NULL);
+void
+purple_message_set_author_alias(PurpleMessage *message,
+ const gchar *author_alias)
+{
+ g_return_if_fail(PURPLE_IS_MESSAGE(message));
- priv = purple_message_get_instance_private(msg);
- return priv->author;
+ g_free(message->author_alias);
+ message->author_alias = g_strdup(author_alias);
+
+ g_object_notify_by_pspec(G_OBJECT(message), properties[PROP_AUTHOR_ALIAS]);
}
const gchar *
-purple_message_get_recipient(PurpleMessage *msg)
-{
- PurpleMessagePrivate *priv = NULL;
+purple_message_get_author_alias(PurpleMessage *message) {
+ g_return_val_if_fail(PURPLE_IS_MESSAGE(message), NULL);
- g_return_val_if_fail(PURPLE_IS_MESSAGE(msg), NULL);
+ if (message->author_alias == NULL)
+ return purple_message_get_author(message);
- priv = purple_message_get_instance_private(msg);
- return priv->recipient;
+ return message->author_alias;
}
void
-purple_message_set_author_alias(PurpleMessage *msg, const gchar *alias)
-{
- g_object_set(msg, "author-alias", alias, NULL);
+purple_message_set_contents(PurpleMessage *message, const gchar *contents) {
+ g_return_if_fail(PURPLE_IS_MESSAGE(message));
+
+ g_free(message->contents);
+ message->contents = g_strdup(contents);
+
+ g_object_notify_by_pspec(G_OBJECT(message), properties[PROP_CONTENTS]);
}
const gchar *
-purple_message_get_author_alias(PurpleMessage *msg)
-{
- PurpleMessagePrivate *priv = NULL;
+purple_message_get_contents(PurpleMessage *message) {
+ g_return_val_if_fail(PURPLE_IS_MESSAGE(message), NULL);
- g_return_val_if_fail(PURPLE_IS_MESSAGE(msg), NULL);
- priv = purple_message_get_instance_private(msg);
-
- if (priv->author_alias == NULL)
- return purple_message_get_author(msg);
-
- return priv->author_alias;
+ return message->contents;
}
void
-purple_message_set_contents(PurpleMessage *msg, const gchar *cont)
+purple_message_set_content_type(PurpleMessage *message,
+ PurpleMessageContentType content_type)
{
- g_object_set(msg, "contents", cont, NULL);
+ g_return_if_fail(PURPLE_IS_MESSAGE(message));
+
+ message->content_type = content_type;
+
+ g_object_notify_by_pspec(G_OBJECT(message), properties[PROP_CONTENT_TYPE]);
}
-const gchar *
-purple_message_get_contents(PurpleMessage *msg)
-{
- PurpleMessagePrivate *priv = NULL;
+PurpleMessageContentType
+purple_message_get_content_type(PurpleMessage *message) {
+ g_return_val_if_fail(PURPLE_IS_MESSAGE(message),
+ PURPLE_MESSAGE_CONTENT_TYPE_PLAIN);
- g_return_val_if_fail(PURPLE_IS_MESSAGE(msg), NULL);
-
- priv = purple_message_get_instance_private(msg);
- return priv->contents;
+ return message->content_type;
}
gboolean
-purple_message_is_empty(PurpleMessage *msg)
-{
- const gchar *cont = purple_message_get_contents(msg);
-
- return (cont == NULL || cont[0] == '\0');
+purple_message_is_empty(PurpleMessage *message) {
+ return (message->contents == NULL || message->contents[0] == '\0');
}
void
-purple_message_set_time(PurpleMessage *msg, guint64 msgtime)
-{
- g_object_set(msg, "time", msgtime, NULL);
+purple_message_set_timestamp(PurpleMessage *message, GDateTime *timestamp) {
+ g_return_if_fail(PURPLE_IS_MESSAGE(message));
+
+ g_clear_pointer(&message->timestamp, g_date_time_unref);
+ if(timestamp != NULL) {
+ message->timestamp = g_date_time_ref(timestamp);
+ }
+
+ g_object_notify_by_pspec(G_OBJECT(message), properties[PROP_TIMESTAMP]);
}
-guint64
-purple_message_get_time(PurpleMessage *msg)
-{
- PurpleMessagePrivate *priv = NULL;
+GDateTime *
+purple_message_get_timestamp(PurpleMessage *message) {
+ g_return_val_if_fail(PURPLE_IS_MESSAGE(message), 0);
+
+ if(message->timestamp == NULL) {
+ GDateTime *dt = g_date_time_new_now_local();
+ purple_message_set_timestamp(message, dt);
+ g_date_time_unref(dt);
+ }
- g_return_val_if_fail(PURPLE_IS_MESSAGE(msg), 0);
+ return message->timestamp;
+}
+
+gchar *
+purple_message_format_timestamp(PurpleMessage *message, const gchar *format) {
+ GDateTime *dt = NULL;
- priv = purple_message_get_instance_private(msg);
- return priv->msgtime;
+ g_return_val_if_fail(PURPLE_IS_MESSAGE(message), NULL);
+ g_return_val_if_fail(format != NULL, NULL);
+
+ dt = purple_message_get_timestamp(message);
+
+ return g_date_time_format(dt, format);
}
void
-purple_message_set_flags(PurpleMessage *msg, PurpleMessageFlags flags)
-{
- g_object_set(msg, "flags", flags, NULL);
+purple_message_set_flags(PurpleMessage *message, PurpleMessageFlags flags) {
+ g_return_if_fail(PURPLE_IS_MESSAGE(message));
+
+ message->flags = flags;
+
+ g_object_notify_by_pspec(G_OBJECT(message), properties[PROP_FLAGS]);
}
PurpleMessageFlags
-purple_message_get_flags(PurpleMessage *msg)
-{
- PurpleMessagePrivate *priv = NULL;
+purple_message_get_flags(PurpleMessage *message) {
+ g_return_val_if_fail(PURPLE_IS_MESSAGE(message), 0);
- g_return_val_if_fail(PURPLE_IS_MESSAGE(msg), 0);
-
- priv = purple_message_get_instance_private(msg);
- return priv->flags;
+ return message->flags;
}
gboolean
purple_message_add_attachment(PurpleMessage *message,
PurpleAttachment *attachment)
{
- PurpleMessagePrivate *priv = NULL;
-
g_return_val_if_fail(PURPLE_IS_MESSAGE(message), FALSE);
g_return_val_if_fail(PURPLE_IS_ATTACHMENT(attachment), FALSE);
- priv = purple_message_get_instance_private(message);
-
- return g_hash_table_insert(priv->attachments,
+ return g_hash_table_insert(message->attachments,
purple_attachment_get_hash_key(attachment),
g_object_ref(G_OBJECT(attachment)));
}
gboolean
purple_message_remove_attachment(PurpleMessage *message, guint64 id) {
- PurpleMessagePrivate *priv = NULL;
-
g_return_val_if_fail(PURPLE_IS_MESSAGE(message), FALSE);
- priv = purple_message_get_instance_private(message);
-
- return g_hash_table_remove(priv->attachments, &id);
+ return g_hash_table_remove(message->attachments, &id);
}
PurpleAttachment *
purple_message_get_attachment(PurpleMessage *message, guint64 id) {
- PurpleMessagePrivate *priv = NULL;
PurpleAttachment *attachment = NULL;
g_return_val_if_fail(PURPLE_IS_MESSAGE(message), NULL);
- priv = purple_message_get_instance_private(message);
-
- attachment = g_hash_table_lookup(priv->attachments, &id);
-
+ attachment = g_hash_table_lookup(message->attachments, &id);
if(PURPLE_IS_ATTACHMENT(attachment)) {
return PURPLE_ATTACHMENT(g_object_ref(G_OBJECT(attachment)));
}
@@ -298,14 +552,13 @@
PurpleAttachmentForeachFunc func,
gpointer data)
{
- PurpleMessagePrivate *priv = NULL;
GHashTableIter iter;
gpointer value;
g_return_if_fail(PURPLE_IS_MESSAGE(message));
g_return_if_fail(func != NULL);
- g_hash_table_iter_init(&iter, priv->attachments);
+ g_hash_table_iter_init(&iter, message->attachments);
while(g_hash_table_iter_next(&iter, NULL, &value)) {
func(PURPLE_ATTACHMENT(value), data);
}
@@ -313,166 +566,7 @@
void
purple_message_clear_attachments(PurpleMessage *message) {
- PurpleMessagePrivate *priv = NULL;
-
g_return_if_fail(PURPLE_IS_MESSAGE(message));
- priv = purple_message_get_instance_private(message);
-
- g_hash_table_remove_all(priv->attachments);
-}
-
-/******************************************************************************
- * Object stuff
- ******************************************************************************/
-
-static void
-purple_message_init(PurpleMessage *msg)
-{
- static guint max_id = 0;
-
- PurpleMessagePrivate *priv = purple_message_get_instance_private(msg);
-
- priv->attachments = g_hash_table_new_full(g_int64_hash, g_int64_equal,
- NULL, g_object_unref);
-
- priv->id = ++max_id;
- g_hash_table_insert(messages, GINT_TO_POINTER(max_id), msg);
-}
-
-static void
-purple_message_finalize(GObject *obj)
-{
- PurpleMessage *message = PURPLE_MESSAGE(obj);
- PurpleMessagePrivate *priv = purple_message_get_instance_private(message);
-
- g_free(priv->author);
- g_free(priv->author_alias);
- g_free(priv->recipient);
- g_free(priv->contents);
-
- g_hash_table_destroy(priv->attachments);
-
- G_OBJECT_CLASS(purple_message_parent_class)->finalize(obj);
-}
-
-static void
-purple_message_get_property(GObject *object, guint par_id, GValue *value,
- GParamSpec *pspec)
-{
- PurpleMessage *message = PURPLE_MESSAGE(object);
- PurpleMessagePrivate *priv = purple_message_get_instance_private(message);
-
- switch (par_id) {
- case PROP_ID:
- g_value_set_uint(value, priv->id);
- break;
- case PROP_AUTHOR:
- g_value_set_string(value, priv->author);
- break;
- case PROP_AUTHOR_ALIAS:
- g_value_set_string(value, priv->author_alias);
- break;
- case PROP_RECIPIENT:
- g_value_set_string(value, priv->recipient);
- break;
- case PROP_CONTENTS:
- g_value_set_string(value, priv->contents);
- break;
- case PROP_TIME:
- g_value_set_uint64(value, priv->msgtime);
- break;
- case PROP_FLAGS:
- g_value_set_flags(value, priv->flags);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec);
- break;
- }
+ g_hash_table_remove_all(message->attachments);
}
-
-static void
-purple_message_set_property(GObject *object, guint par_id, const GValue *value,
- GParamSpec *pspec)
-{
- PurpleMessage *message = PURPLE_MESSAGE(object);
- PurpleMessagePrivate *priv = purple_message_get_instance_private(message);
-
- switch (par_id) {
- case PROP_AUTHOR:
- g_free(priv->author);
- priv->author = g_value_dup_string(value);
- break;
- case PROP_AUTHOR_ALIAS:
- g_free(priv->author_alias);
- priv->author_alias = g_value_dup_string(value);
- break;
- case PROP_RECIPIENT:
- g_free(priv->recipient);
- priv->recipient = g_value_dup_string(value);
- break;
- case PROP_CONTENTS:
- g_free(priv->contents);
- priv->contents = g_value_dup_string(value);
- break;
- case PROP_TIME:
- priv->msgtime = g_value_get_uint64(value);
- break;
- case PROP_FLAGS:
- priv->flags = g_value_get_flags(value);
- break;
- default:
- G_OBJECT_WARN_INVALID_PROPERTY_ID(object, par_id, pspec);
- break;
- }
-}
-
-static void
-purple_message_class_init(PurpleMessageClass *klass)
-{
- GObjectClass *gobj_class = G_OBJECT_CLASS(klass);
-
- gobj_class->finalize = purple_message_finalize;
- gobj_class->get_property = purple_message_get_property;
- gobj_class->set_property = purple_message_set_property;
-
- properties[PROP_ID] = g_param_spec_uint("id",
- "ID", "The session-unique message id",
- 0, G_MAXUINT, 0, G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
- properties[PROP_AUTHOR] = g_param_spec_string("author",
- "Author", "The username of the person, who sent the message.",
- NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- properties[PROP_AUTHOR_ALIAS] = g_param_spec_string("author-alias",
- "Author's alias", "The alias of the person, who sent the "
- "message. For outgoing messages, it's your alias.",
- NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- properties[PROP_RECIPIENT] = g_param_spec_string("recipient",
- "Recipient", "The username of the recipient.",
- NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- properties[PROP_CONTENTS] = g_param_spec_string("contents",
- "Contents", "The message text",
- NULL, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- properties[PROP_TIME] = g_param_spec_uint64("time",
- "Time", "Message timestamp",
- 0, G_MAXUINT64, 0, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
- properties[PROP_FLAGS] = g_param_spec_flags("flags",
- "Flags", "Bitwise set of #PurpleMessageFlags flags",
- PURPLE_TYPE_MESSAGE_FLAGS, 0,
- G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS);
-
- g_object_class_install_properties(gobj_class, PROP_LAST, properties);
-}
-
-void
-_purple_message_init(void)
-{
- messages = g_hash_table_new_full(g_direct_hash, g_direct_equal,
- NULL, g_object_unref);
-}
-
-void
-_purple_message_uninit(void)
-{
- g_hash_table_destroy(messages);
- messages = NULL;
-}
--- a/libpurple/message.h Sun Sep 27 21:13:04 2020 -0500
+++ b/libpurple/message.h Sat Oct 03 05:58:21 2020 -0500
@@ -48,6 +48,8 @@
* PURPLE_TYPE_MESSAGE:
*
* The standard _get_type macro for #PurpleMessage.
+ *
+ * Since: 3.0.0
*/
#define PURPLE_TYPE_MESSAGE purple_message_get_type()
@@ -96,27 +98,50 @@
} PurpleMessageFlags;
/**
+ * PurpleMessageContentType:
+ * @PURPLE_MESSAGE_CONTENT_TYPE_PLAIN: The message has no formatting.
+ * @PURPLE_MESSAGE_CONTENT_TYPE_HTML: The message is formatted in HTML.
+ * @PURPLE_MESSAGE_CONTENT_TYPE_XHTML: The mesage is formatted in XHTML.
+ * @PURPLE_MESSAGE_CONTENT_TYPE_MARKDOWN: The message is formatted in Markdown.
+ *
+ * The message formatting for the message.
+ *
+ * Since: 3.0.0
+ */
+typedef enum /*< prefix=PURPLE_MESSAGE_CONTENT_TYPE,underscore_name=PURPLE_MESSAGE_CONTENT_TYPE >*/
+{
+ PURPLE_MESSAGE_CONTENT_TYPE_PLAIN = 0,
+ PURPLE_MESSAGE_CONTENT_TYPE_HTML,
+ PURPLE_MESSAGE_CONTENT_TYPE_XHTML,
+ PURPLE_MESSAGE_CONTENT_TYPE_MARKDOWN,
+} PurpleMessageContentType;
+
+/**
* purple_message_get_type:
*
* Returns: the #GType for a message.
+ *
+ * Since: 3.0.0
*/
G_DECLARE_FINAL_TYPE(PurpleMessage, purple_message, PURPLE, MESSAGE, GObject)
/**
* purple_message_new_outgoing:
- * @who: Message's recipient.
- * @contents: The contents of a message.
- * @flags: The message flags.
+ * @author: The author.
+ * @recipient: The recipient.
+ * @contents: The contents.
+ * @flags: The #PurpleMessageFlags.
*
- * Creates new outgoing message (the user is the author).
+ * Creates new outgoing message to @recipient.
*
- * You don't need to set the #PURPLE_MESSAGE_SEND flag.
+ * You don't need to set the #PURPLE_MESSAGE_SEND flag. If the message is not
+ * plain text be sure to call purple_message_set_content_type().
*
- * Returns: the new #PurpleMessage.
+ * Returns: (transfer full): The new #PurpleMessage instance.
+ *
+ * Since: 3.0.0
*/
-PurpleMessage *
-purple_message_new_outgoing(const gchar *who, const gchar *contents,
- PurpleMessageFlags flags);
+PurpleMessage *purple_message_new_outgoing(const gchar *author, const gchar *recipient, const gchar *contents, PurpleMessageFlags flags);
/**
* purple_message_new_incoming:
@@ -130,10 +155,10 @@
* You don't need to set the #PURPLE_MESSAGE_RECV flag.
*
* Returns: the new #PurpleMessage.
+ *
+ * Since: 3.0.0
*/
-PurpleMessage *
-purple_message_new_incoming(const gchar *who, const gchar *contents,
- PurpleMessageFlags flags, guint64 timestamp);
+PurpleMessage *purple_message_new_incoming(const gchar *who, const gchar *contents, PurpleMessageFlags flags, guint64 timestamp);
/**
* purple_message_new_system:
@@ -145,151 +170,198 @@
* You don't need to set the #PURPLE_MESSAGE_SYSTEM flag.
*
* Returns: the new #PurpleMessage.
+ *
+ * Since: 3.0.0
*/
-PurpleMessage *
-purple_message_new_system(const gchar *contents, PurpleMessageFlags flags);
+PurpleMessage *purple_message_new_system(const gchar *contents, PurpleMessageFlags flags);
/**
* purple_message_get_id:
- * @msg: The message.
+ * @message: The message.
*
* Returns the unique identifier of the message. These identifiers are not
* serialized - it's a per-session id.
*
- * Returns: the global identifier of @msg.
+ * Returns: the global identifier of @message.
+ *
+ * Since: 3.0.0
*/
-guint
-purple_message_get_id(PurpleMessage *msg);
-
-/**
- * purple_message_find_by_id:
- * @id: The message identifier.
- *
- * Finds the message with a given @id.
- *
- * Returns: (transfer none): The #PurpleMessage, or %NULL if not found.
- */
-PurpleMessage *
-purple_message_find_by_id(guint id);
+guint purple_message_get_id(PurpleMessage *message);
/**
* purple_message_get_author:
- * @msg: The message.
+ * @message: The message.
*
- * Returns the author of the message - his screen name (not a local alias).
+ * Returns the author of the message, not a local alias.
+ *
+ * Returns: the author of @message.
*
- * Returns: the author of @msg.
+ * Since: 3.0.0
*/
-const gchar *
-purple_message_get_author(PurpleMessage *msg);
+const gchar *purple_message_get_author(PurpleMessage *message);
+
+/**
+ * purple_message_set_recipient:
+ * @message: The #PurpleMessage instance.
+ * @recipient: The name of the recipient.
+ *
+ * Sets the recipient of @message to @recipient.
+ *
+ * Since: 3.0.0
+ */
+void purple_message_set_recipient(PurpleMessage *message, const gchar *recipient);
/**
* purple_message_get_recipient:
- * @msg: The message.
+ * @message: The message.
*
- * Returns the recipient of the message - his screen name (not a local alias).
+ * Returns the recipient of the message, not a local alias.
*
- * Returns: the recipient of @msg.
+ * Returns: the recipient of @message.
+ *
+ * Since: 3.0.0
*/
-const gchar *
-purple_message_get_recipient(PurpleMessage *msg);
+const gchar *purple_message_get_recipient(PurpleMessage *message);
/**
* purple_message_set_author_alias:
- * @msg: The message.
+ * @message: The message.
* @alias: The alias.
*
- * Sets the alias of @msg's author. You don't normally need to call this.
+ * Sets the alias of @message's author. You don't normally need to call this.
+ *
+ * Since: 3.0.0
*/
-void
-purple_message_set_author_alias(PurpleMessage *msg, const gchar *alias);
+void purple_message_set_author_alias(PurpleMessage *message, const gchar *alias);
/**
* purple_message_get_author_alias:
- * @msg: The message.
+ * @message: The message.
*
- * Returns the alias of @msg author.
+ * Returns the alias of @message author.
*
- * Returns: the @msg author's alias.
+ * Returns: the @message author's alias.
+ *
+ * Since: 3.0.0
*/
-const gchar *
-purple_message_get_author_alias(PurpleMessage *msg);
+const gchar *purple_message_get_author_alias(PurpleMessage *message);
/**
* purple_message_set_contents:
- * @msg: The message.
+ * @message: The message.
* @cont: The contents.
*
- * Sets the contents of the @msg. It might be HTML.
+ * Sets the contents of the @message. It might be HTML.
+ *
+ * Since: 3.0.0
*/
-void
-purple_message_set_contents(PurpleMessage *msg, const gchar *cont);
+void purple_message_set_contents(PurpleMessage *message, const gchar *cont);
/**
* purple_message_get_contents:
- * @msg: The message.
+ * @message: The message.
*
* Returns the contents of the message.
*
- * Returns: the contents of @msg.
+ * Returns: the contents of @message.
+ *
+ * Since: 3.0.0
*/
-const gchar *
-purple_message_get_contents(PurpleMessage *msg);
+const gchar *purple_message_get_contents(PurpleMessage *message);
+
+/**
+ * purple_message_set_content_type:
+ * @message: The #PurpleMessage instance.
+ * @content_type: The #PurpleMessageContentType value.
+ *
+ * Sets the content-type of @message to @content_type.
+ *
+ * Since: 3.0.0
+ */
+void purple_message_set_content_type(PurpleMessage *message, PurpleMessageContentType content_type);
+
+/**
+ * purple_message_get_content_type:
+ * @message: The #PurpleMessage instance.
+ *
+ * Gets the content-type of @message.
+ *
+ * Returns: The #PurpleMessageContentType of @message.
+ *
+ * Since: 3.0.0
+ */
+PurpleMessageContentType purple_message_get_content_type(PurpleMessage *message);
/**
* purple_message_is_empty:
- * @msg: The message.
+ * @message: The message.
*
* Checks, if the message's body is empty.
*
- * Returns: %TRUE, if @msg is empty.
+ * Returns: %TRUE, if @message is empty.
+ *
+ * Since: 3.0.0
*/
-gboolean
-purple_message_is_empty(PurpleMessage *msg);
+gboolean purple_message_is_empty(PurpleMessage *message);
+
+/**
+ * purple_message_set_timestamp:
+ * @message: The #PurpleMessage instance.
+ * @timestamp: (nullable): The #GDateTime of the message.
+ *
+ * Sets the timestamp of @message.
+ *
+ * Since: 3.0.0
+ */
+void purple_message_set_timestamp(PurpleMessage *message, GDateTime *timestamp);
/**
- * purple_message_set_time:
- * @msg: The message.
- * @msgtime: The timestamp of a message.
+ * purple_message_get_timestamp:
+ * @message: The message.
+ *
+ * Returns a @message's timestamp. If @message does not currently have a
+ * timestamp, the current time will be set as the time stamp and returned.
*
- * Sets the @msg's timestamp. It should be a date of posting, but it can be
- * a date of receiving (if the former is not available).
+ * Returns: (transfer none): The #GDateTime timestamp from @message.
+ *
+ * Since: 3.0.0
*/
-void
-purple_message_set_time(PurpleMessage *msg, guint64 msgtime);
+GDateTime *purple_message_get_timestamp(PurpleMessage *message);
/**
- * purple_message_get_time:
- * @msg: The message.
- *
- * Returns a @msg's timestamp.
+ * purple_message_format_timestamp:
+ * @message: The #PurpleMessage instance.
+ * @format: The format to output the time stamp as.
*
- * Returns: @msg's timestamp.
+ * Formats the timestamp of @message and returns it.
+ *
+ * Returns: The formatted timestamp.
*/
-guint64
-purple_message_get_time(PurpleMessage *msg);
+gchar *purple_message_format_timestamp(PurpleMessage *message, const gchar *format);
/**
* purple_message_set_flags:
- * @msg: The message.
+ * @message: The message.
* @flags: The message flags.
*
- * Sets flags for @msg. It shouldn't be in a conflict with a message type,
+ * Sets flags for @message. It shouldn't be in a conflict with a message type,
* so use it carefully.
+ *
+ * Since: 3.0.0
*/
-void
-purple_message_set_flags(PurpleMessage *msg, PurpleMessageFlags flags);
+void purple_message_set_flags(PurpleMessage *message, PurpleMessageFlags flags);
/**
* purple_message_get_flags:
- * @msg: The message.
+ * @message: The message.
*
- * Returns the flags of a @msg.
+ * Returns the flags of a @message.
*
- * Returns: the flags of a @msg.
+ * Returns: the flags of a @message.
+ *
+ * Since: 3.0.0
*/
-PurpleMessageFlags
-purple_message_get_flags(PurpleMessage *msg);
+PurpleMessageFlags purple_message_get_flags(PurpleMessage *message);
/**
* purple_message_add_attachment:
@@ -299,6 +371,8 @@
* Adds @attachment to @message.
*
* Returns %TRUE if an attachment with the same ID did not already exist.
+ *
+ * Since: 3.0.0
*/
gboolean purple_message_add_attachment(PurpleMessage *message, PurpleAttachment *attachment);
@@ -311,6 +385,8 @@
*
* Returns: %TRUE if the #PurpleAttachment was found and removed, %FALSE
* otherwise.
+ *
+ * Since: 3.0.0
*/
gboolean purple_message_remove_attachment(PurpleMessage *message, guint64 id);
@@ -323,6 +399,8 @@
*
* Returns: (transfer full): The #PurpleAttachment if it was found, otherwise
* %NULL.
+ *
+ * Since: 3.0.0
*/
PurpleAttachment *purple_message_get_attachment(PurpleMessage *message, guint64 id);
@@ -333,6 +411,8 @@
* @data: User data to pass to @func.
*
* Calls @func for each #PurpleAttachment that's attached to @message.
+ *
+ * Since: 3.0.0
*/
void purple_message_foreach_attachment(PurpleMessage *message, PurpleAttachmentForeachFunc func, gpointer data);
@@ -341,6 +421,8 @@
* @message: The #PurpleMessage instance.
*
* Removes all attachments from @message.
+ *
+ * Since: 3.0.0
*/
void purple_message_clear_attachments(PurpleMessage *message);
--- a/libpurple/plugins/offlinemsg.c Sun Sep 27 21:13:04 2020 -0500
+++ b/libpurple/plugins/offlinemsg.c Sat Oct 03 05:58:21 2020 -0500
@@ -73,7 +73,11 @@
PurplePounceEvent event;
PurplePounceOption option;
PurpleConversation *conv;
+ PurpleMessage *message;
char *temp;
+ const gchar *me;
+
+ me = purple_account_get_name_for_display(offline->account);
event = PURPLE_POUNCE_SIGNON;
option = PURPLE_POUNCE_OPTION_NONE;
@@ -99,9 +103,9 @@
g_object_set_data(G_OBJECT(conv), "plugin_pack:offlinemsg",
GINT_TO_POINTER(OFFLINE_MSG_YES));
- /* TODO: use a reference to a PurpleMessage */
- purple_conversation_write_message(conv,
- purple_message_new_outgoing(offline->who, offline->message, 0));
+ message = purple_message_new_outgoing(me, offline->who, offline->message, 0);
+ purple_conversation_write_message(conv, message);
+ g_object_unref(G_OBJECT(message));
discard_data(offline);
}
--- a/libpurple/protocols/facebook/util.c Sun Sep 27 21:13:04 2020 -0500
+++ b/libpurple/protocols/facebook/util.c Sat Oct 03 05:58:21 2020 -0500
@@ -19,6 +19,7 @@
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
+#include <glib.h>
#include <glib/gi18n-lib.h>
#include <gio/gio.h>
@@ -432,7 +433,8 @@
fb_util_serv_got_im(PurpleConnection *gc, const gchar *who, const gchar *text,
PurpleMessageFlags flags, guint64 timestamp)
{
- const gchar *name;
+ GDateTime *dt = NULL;
+ const gchar *name, *me;
PurpleAccount *acct;
PurpleIMConversation *conv;
PurpleMessage *msg;
@@ -449,21 +451,30 @@
conv = purple_im_conversation_new(acct, who);
}
+ me = purple_account_get_name_for_display(acct);
name = purple_account_get_username(acct);
- msg = purple_message_new_outgoing(name, text, flags);
- purple_message_set_time(msg, timestamp);
+ msg = purple_message_new_outgoing(me, name, text, flags);
+
+ dt = g_date_time_new_from_unix_local((gint64)timestamp);
+ purple_message_set_timestamp(msg, dt);
+ g_date_time_unref(dt);
+
purple_conversation_write_message(PURPLE_CONVERSATION(conv), msg);
+
+ g_object_unref(G_OBJECT(msg));
}
void
fb_util_serv_got_chat_in(PurpleConnection *gc, gint id, const gchar *who,
const gchar *text, PurpleMessageFlags flags,
- guint64 timestamp)
+ guint64 timestamp)
{
+ GDateTime *dt = NULL;
const gchar *name;
PurpleAccount *acct;
PurpleChatConversation *conv;
PurpleMessage *msg;
+ const gchar *me;
if (!(flags & PURPLE_MESSAGE_SEND)) {
purple_serv_got_chat_in(gc, id, who, flags, text, timestamp);
@@ -473,10 +484,18 @@
acct = purple_connection_get_account(gc);
conv = purple_conversations_find_chat(gc, id);
+ me = purple_account_get_name_for_display(acct);
name = purple_account_get_username(acct);
- msg = purple_message_new_outgoing(name, text, flags);
- purple_message_set_time(msg, timestamp);
+
+ msg = purple_message_new_outgoing(me, name, text, flags);
+
+ dt = g_date_time_new_from_unix_local((gint64)timestamp);
+ purple_message_set_timestamp(msg, dt);
+ g_date_time_unref(dt);
+
purple_conversation_write_message(PURPLE_CONVERSATION(conv), msg);
+
+ g_object_unref(G_OBJECT(msg));
}
gboolean
--- a/libpurple/protocols/gg/chat.c Sun Sep 27 21:13:04 2020 -0500
+++ b/libpurple/protocols/gg/chat.c Sat Oct 03 05:58:21 2020 -0500
@@ -25,6 +25,8 @@
* along with this program; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1301 USA
*/
+
+#include <glib.h>
#include <glib/gi18n-lib.h>
#include "chat.h"
@@ -471,6 +473,7 @@
int ggp_chat_send(PurpleConnection *gc, int local_id, PurpleMessage *msg)
{
GGPInfo *info = purple_connection_get_protocol_data(gc);
+ GDateTime *dt = NULL;
PurpleChatConversation *conv;
ggp_chat_local_info *chat;
gboolean succ = TRUE;
@@ -496,10 +499,11 @@
g_free(gg_msg);
me = purple_account_get_username(purple_connection_get_account(gc));
+ dt = purple_message_get_timestamp(msg);
purple_serv_got_chat_in(gc, chat->local_id, me,
purple_message_get_flags(msg),
purple_message_get_contents(msg),
- purple_message_get_time(msg));
+ (time_t)g_date_time_to_unix(dt));
return succ ? 0 : -1;
}
@@ -507,11 +511,12 @@
void ggp_chat_got_message(PurpleConnection *gc, uint64_t chat_id,
const char *message, time_t time, uin_t who)
{
+ PurpleAccount *account = NULL;
ggp_chat_local_info *chat;
uin_t me;
- me = ggp_str_to_uin(purple_account_get_username(
- purple_connection_get_account(gc)));
+ account = purple_connection_get_account(gc);
+ me = ggp_str_to_uin(purple_account_get_username(account));
chat = ggp_chat_get(gc, chat_id);
if (!chat) {
@@ -522,11 +527,16 @@
ggp_chat_open_conv(chat);
if (who == me) {
+ GDateTime *dt = NULL;
PurpleMessage *pmsg;
pmsg = purple_message_new_outgoing(
+ purple_account_get_name_for_display(account),
ggp_uin_to_str(who), message, 0);
- purple_message_set_time(pmsg, time);
+
+ dt = g_date_time_new_from_unix_local((gint64)time);
+ purple_message_set_timestamp(pmsg, dt);
+ g_date_time_unref(dt);
purple_conversation_write_message(
PURPLE_CONVERSATION(chat->conv), pmsg);
--- a/libpurple/protocols/gg/message-prpl.c Sun Sep 27 21:13:04 2020 -0500
+++ b/libpurple/protocols/gg/message-prpl.c Sat Oct 03 05:58:21 2020 -0500
@@ -235,16 +235,28 @@
ggp_chat_got_message(gc, msg->chat_id, msg->text, msg->time,
msg->user);
} else if (msg->type == GGP_MESSAGE_GOT_TYPE_MULTILOGON) {
+ GDateTime *dt = NULL;
+ PurpleAccount *account = NULL;
PurpleIMConversation *im = ggp_message_get_conv(gc, msg->user);
PurpleMessage *pmsg;
+ const gchar *me = NULL;
- pmsg = purple_message_new_outgoing(NULL, msg->text, 0);
- purple_message_set_time(pmsg, msg->time);
+ account = purple_connection_get_account(gc);
+ me = purple_account_get_name_for_display(account);
+
+ pmsg = purple_message_new_outgoing(me, NULL, msg->text, 0);
+
+ dt = g_date_time_new_from_unix_local((gint64)msg->time);
+ purple_message_set_timestamp(pmsg, dt);
+ g_date_time_unref(dt);
purple_conversation_write_message(PURPLE_CONVERSATION(im), pmsg);
- } else
+
+ g_object_unref(G_OBJECT(pmsg));
+ } else {
purple_debug_error("gg", "ggp_message_got_display: "
"unexpected message type: %d\n", msg->type);
+ }
}
static gboolean ggp_message_format_from_gg_found_img(const GMatchInfo *info,
--- a/libpurple/protocols/irc/cmds.c Sun Sep 27 21:13:04 2020 -0500
+++ b/libpurple/protocols/irc/cmds.c Sat Oct 03 05:58:21 2020 -0500
@@ -88,9 +88,9 @@
int irc_cmd_ctcp_action(struct irc_conn *irc, const char *cmd, const char *target, const char **args)
{
PurpleConnection *gc = purple_account_get_connection(irc->account);
- char *action, *escaped, *dst, **newargs;
- const char *src;
- char *msg;
+ gchar *action, *escaped, *dst, **newargs;
+ const gchar *src, *me;
+ gchar *msg;
PurpleConversation *convo;
PurpleMessage *pmsg;
@@ -98,28 +98,41 @@
return 0;
convo = purple_conversations_find_with_account(target, irc->account);
+ me = purple_account_get_name_for_display(irc->account);
msg = g_strdup_printf("/me %s", args[0]);
/* XXX: we'd prefer to keep this in conversation.c */
if (PURPLE_IS_IM_CONVERSATION(convo)) {
- pmsg = purple_message_new_outgoing(
- purple_conversation_get_name(convo), msg, 0);
+ const gchar *conv_name = purple_conversation_get_name(convo);
+ pmsg = purple_message_new_outgoing(me, conv_name, msg, 0);
purple_signal_emit(purple_conversations_get_handle(),
"sending-im-msg", irc->account, pmsg);
} else {
- pmsg = purple_message_new_outgoing(NULL, msg, 0);
+ pmsg = purple_message_new_outgoing(me, NULL, msg, 0);
purple_signal_emit(purple_conversations_get_handle(),
"sending-chat-msg", irc->account, pmsg,
purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(convo)));
}
+ /* We free the original message because it could have been changed by the
+ * sending-*-msg signals above.
+ */
g_free(msg);
- if (purple_message_is_empty(pmsg))
+
+ /* if the message was eaten by a signal we bail */
+ if(purple_message_is_empty(pmsg)) {
+ g_object_unref(G_OBJECT(pmsg));
+
return 0;
- msg = g_strdup(purple_message_get_contents(pmsg)); /* XXX: is it really necessary? */
+ }
+
+ /* create a copy of the updated message, which should not be null because
+ * we just tested if it was empty in the above conditional.
+ */
+ msg = g_strdup(purple_message_get_contents(pmsg));
if (strncmp(msg, "/me ", 4) != 0) {
newargs = g_new0(char *, 2);
@@ -177,18 +190,23 @@
escaped = g_markup_escape_text(args[0], -1);
action = g_strdup_printf("/me %s", escaped);
g_free(escaped);
- if (action[strlen(action) - 1] == '\n')
+ if (action[strlen(action) - 1] == '\n') {
action[strlen(action) - 1] = '\0';
- if (PURPLE_IS_CHAT_CONVERSATION(convo))
+ }
+ if (PURPLE_IS_CHAT_CONVERSATION(convo)) {
purple_serv_got_chat_in(gc, purple_chat_conversation_get_id(PURPLE_CHAT_CONVERSATION(convo)),
purple_connection_get_display_name(gc),
PURPLE_MESSAGE_SEND, action, time(NULL));
- else
- purple_conversation_write_message(convo, purple_message_new_outgoing(
- purple_connection_get_display_name(gc), action, 0));
+ } else {
+ purple_message_set_recipient(pmsg,
+ purple_connection_get_display_name(gc));
+ purple_conversation_write_message(convo, pmsg);
+ }
g_free(action);
}
+ g_object_unref(G_OBJECT(pmsg));
+
return 1;
}
@@ -512,11 +530,20 @@
purple_conversation_present(PURPLE_CONVERSATION(im));
if (args[1]) {
+ PurpleMessage *message = NULL;
+ const gchar *me = NULL;
+ const gchar *recipient = NULL;
+
gc = purple_account_get_connection(irc->account);
irc_cmd_privmsg(irc, cmd, target, args);
- purple_conversation_write_message(PURPLE_CONVERSATION(im),
- purple_message_new_outgoing(
- purple_connection_get_display_name(gc), args[1], 0));
+
+ me = purple_account_get_name_for_display(irc->account);
+ recipient = purple_connection_get_display_name(gc);
+ message = purple_message_new_outgoing(me, recipient, args[1], 0);
+
+ purple_conversation_write_message(PURPLE_CONVERSATION(im), message);
+
+ g_object_unref(G_OBJECT(message));
}
return 0;
--- a/libpurple/protocols/jabber/jabber.c Sun Sep 27 21:13:04 2020 -0500
+++ b/libpurple/protocols/jabber/jabber.c Sat Oct 03 05:58:21 2020 -0500
@@ -3059,20 +3059,25 @@
static PurpleCmdRet jabber_cmd_chat_msg(PurpleConversation *conv,
const char *cmd, char **args, char **error, void *data)
{
+ PurpleAccount *account = NULL;
PurpleConnection *pc = NULL;
PurpleProtocol *prpl = NULL;
PurpleMessage *msg = NULL;
JabberChat *chat = jabber_chat_find_by_conv(PURPLE_CHAT_CONVERSATION(conv));
char *who;
+ const gchar *me = NULL;
if (!chat)
return PURPLE_CMD_RET_FAILED;
+ account = purple_connection_get_account(pc);
+ me = purple_account_get_name_for_display(account);
+
who = g_strdup_printf("%s@%s/%s", chat->room, chat->server, args[0]);
pc = purple_conversation_get_connection(conv);
prpl = purple_connection_get_protocol(pc);
- msg = purple_message_new_outgoing(who, args[1], 0);
+ msg = purple_message_new_outgoing(me, who, args[1], 0);
jabber_message_send_im(PURPLE_PROTOCOL_IM(prpl), pc, msg);
--- a/libpurple/purpleprivate.h Sun Sep 27 21:13:04 2020 -0500
+++ b/libpurple/purpleprivate.h Sat Oct 03 05:58:21 2020 -0500
@@ -189,22 +189,6 @@
_purple_fstat(int fd, GStatBuf *st);
/**
- * _purple_message_init: (skip)
- *
- * Initializes the #PurpleMessage subsystem.
- */
-void
-_purple_message_init(void);
-
-/**
- * _purple_message_uninit: (skip)
- *
- * Uninitializes the #PurpleMessage subsystem.
- */
-void
-_purple_message_uninit(void);
-
-/**
* _purple_conversation_write_common:
* @conv: The conversation.
* @msg: The message.
--- a/libpurple/server.c Sun Sep 27 21:13:04 2020 -0500
+++ b/libpurple/server.c Sat Oct 03 05:58:21 2020 -0500
@@ -556,6 +556,7 @@
pmsg = purple_message_new_incoming(name, message, flags, mtime);
purple_conversation_write_message(PURPLE_CONVERSATION(im), pmsg);
g_free(message);
+ g_object_unref(G_OBJECT(pmsg));
/*
* Don't autorespond if:
@@ -622,12 +623,15 @@
if (!(flags & PURPLE_MESSAGE_AUTO_RESP))
{
PurpleMessage *msg;
+ const gchar *me = purple_account_get_name_for_display(account);
- msg = purple_message_new_outgoing(name,
+ msg = purple_message_new_outgoing(me, name,
away_msg, PURPLE_MESSAGE_AUTO_RESP);
purple_serv_send_im(gc, msg);
purple_conversation_write_message(PURPLE_CONVERSATION(im), msg);
+
+ g_object_unref(G_OBJECT(msg));
}
}
}
@@ -890,16 +894,23 @@
purple_signal_emit(purple_conversations_get_handle(), "received-chat-msg", purple_connection_get_account(g),
who, message, chat, flags);
- if (flags & PURPLE_MESSAGE_RECV)
+ if (flags & PURPLE_MESSAGE_RECV) {
pmsg = purple_message_new_incoming(who, message, flags, mtime);
- else {
- pmsg = purple_message_new_outgoing(who, message, flags);
- purple_message_set_time(pmsg, mtime);
+ } else {
+ PurpleAccount *account = purple_connection_get_account(g);
+ GDateTime *dt = g_date_time_new_from_unix_local((gint64)mtime);
+ const gchar *me = purple_account_get_name_for_display(account);
+
+ pmsg = purple_message_new_outgoing(me, who, message, flags);
+ purple_message_set_timestamp(pmsg, dt);
+ g_date_time_unref(dt);
}
purple_conversation_write_message(PURPLE_CONVERSATION(chat), pmsg);
g_free(angel);
g_free(buffy);
+
+ g_object_unref(G_OBJECT(pmsg));
}
void purple_serv_send_file(PurpleConnection *gc, const char *who, const char *file)
--- a/libpurple/tests/test_ui.c Sun Sep 27 21:13:04 2020 -0500
+++ b/libpurple/tests/test_ui.c Sat Oct 03 05:58:21 2020 -0500
@@ -40,13 +40,15 @@
static void
test_write_conv(PurpleConversation *conv, PurpleMessage *msg)
{
- time_t mtime = purple_message_get_time(msg);
+ gchar *timestamp = purple_message_format_timestamp(msg, "(%H:%M:%S)");
printf("(%s) %s %s: %s\n",
purple_conversation_get_name(conv),
- purple_utf8_strftime("(%H:%M:%S)", localtime(&mtime)),
+ timestamp,
purple_message_get_author_alias(msg),
purple_message_get_contents(msg));
+
+ g_free(timestamp);
}
static PurpleConversationUiOps test_conv_uiops = {
--- a/pidgin/gtkconv.c Sun Sep 27 21:13:04 2020 -0500
+++ b/pidgin/gtkconv.c Sat Oct 03 05:58:21 2020 -0500
@@ -4640,11 +4640,13 @@
purple_conversation_get_name(conv));
if (chat) {
GHashTable *comps = purple_chat_get_components(chat);
+ GDateTime *dt = NULL;
time_t now, history_since, prev_history_since = 0;
struct tm *history_since_tm;
const char *history_since_s, *prev_history_since_s;
- history_since = purple_message_get_time(pmsg) + 1;
+ dt = purple_message_get_timestamp(pmsg);
+ history_since = g_date_time_to_unix(dt) + 1;
prev_history_since_s = g_hash_table_lookup(comps,
"history_since");
@@ -6025,8 +6027,10 @@
static int
message_compare(PurpleMessage *m1, PurpleMessage *m2)
{
- guint64 t1 = purple_message_get_time(m1), t2 = purple_message_get_time(m2);
- return (t1 > t2) - (t1 < t2);
+ GDateTime *dt1 = purple_message_get_timestamp(m1);
+ GDateTime *dt2 = purple_message_get_timestamp(m2);
+
+ return g_date_time_compare(dt1, dt2);
}
/* Adds some message history to the gtkconv. This happens in a idle-callback. */
@@ -6036,13 +6040,14 @@
PidginConversation *gtkconv = data;
int count = 0;
int timer = gtkconv->attach_timer;
- time_t when = GPOINTER_TO_INT(g_object_get_data(G_OBJECT(gtkconv->editor), "attach-start-time"));
+ GDateTime *when = (GDateTime *)g_object_get_data(G_OBJECT(gtkconv->editor), "attach-start-time");
gboolean im = (PURPLE_IS_IM_CONVERSATION(gtkconv->active_conv));
gtkconv->attach_timer = 0;
while (gtkconv->attach_current && count < ADD_MESSAGE_HISTORY_AT_ONCE) {
PurpleMessage *msg = gtkconv->attach_current->data;
- if (!im && when && (guint64)when < purple_message_get_time(msg)) {
+ GDateTime *dt = purple_message_get_timestamp(msg);
+ if (!im && when && g_date_time_difference(dt, when) >= 0) {
g_object_set_data(G_OBJECT(gtkconv->editor), "attach-start-time", NULL);
}
/* XXX: should it be gtkconv->active_conv? */
@@ -6069,8 +6074,10 @@
GList *history = purple_conversation_get_message_history(conv);
for (; history; history = history->next) {
PurpleMessage *msg = history->data;
- if (purple_message_get_time(msg) > (guint64)when)
+ GDateTime *dt = purple_message_get_timestamp(msg);
+ if(g_date_time_difference(dt, when) > 0) {
msgs = g_list_prepend(msgs, msg);
+ }
}
}
msgs = g_list_sort(msgs, (GCompareFunc)message_compare);
@@ -6131,6 +6138,8 @@
list = purple_conversation_get_message_history(conv);
if (list) {
+ GDateTime *dt = NULL;
+
if (PURPLE_IS_IM_CONVERSATION(conv)) {
GList *convs;
list = g_list_copy(list);
@@ -6147,8 +6156,9 @@
gtkconv->attach_current = g_list_last(list);
}
- g_object_set_data(G_OBJECT(gtkconv->editor), "attach-start-time",
- GINT_TO_POINTER(purple_message_get_time(list->data)));
+ dt = purple_message_get_timestamp(PURPLE_MESSAGE(list->data));
+ g_object_set_data_full(G_OBJECT(gtkconv->editor), "attach-start-time",
+ g_date_time_ref(dt), (GDestroyNotify)g_date_time_unref);
gtkconv->attach_timer = g_idle_add(add_message_history_to_gtkconv, gtkconv);
} else {
purple_signal_emit(pidgin_conversations_get_handle(),
--- a/pidgin/gtkpounce.c Sun Sep 27 21:13:04 2020 -0500
+++ b/pidgin/gtkpounce.c Sat Oct 03 05:58:21 2020 -0500
@@ -1397,15 +1397,18 @@
if (message != NULL)
{
PurpleMessage *pmsg;
+ const gchar *me;
im = purple_conversations_find_im_with_account(pouncee, account);
+ me = purple_account_get_name_for_display(account);
if (im == NULL)
im = purple_im_conversation_new(account, pouncee);
- pmsg = purple_message_new_outgoing(pouncee, message, 0);
+ pmsg = purple_message_new_outgoing(me, pouncee, message, 0);
purple_serv_send_im(purple_account_get_connection(account), pmsg);
purple_conversation_write_message(PURPLE_CONVERSATION(im), pmsg);
+ g_object_unref(G_OBJECT(pmsg));
}
}
--- a/pidgin/pidginmessage.c Sun Sep 27 21:13:04 2020 -0500
+++ b/pidgin/pidginmessage.c Sat Oct 03 05:58:21 2020 -0500
@@ -27,7 +27,6 @@
GObject parent;
PurpleMessage *message;
- GDateTime *timestamp;
};
typedef struct {
@@ -55,13 +54,7 @@
static void
pidgin_message_set_message(PidginMessage *message, PurpleMessage *purple_msg) {
if(g_set_object(&message->message, purple_msg)) {
- g_clear_pointer(&message->timestamp, g_date_time_unref);
- message->timestamp = g_date_time_new_from_unix_local(purple_message_get_time(purple_msg));
-
- g_object_freeze_notify(G_OBJECT(message));
g_object_notify_by_pspec(G_OBJECT(message), properties[PROP_MESSAGE]);
- g_object_notify(G_OBJECT(message), "timestamp");
- g_object_thaw_notify(G_OBJECT(message));
}
}
@@ -199,7 +192,7 @@
g_value_set_string(value, purple_message_get_contents(message->message));
break;
case PROP_TIMESTAMP:
- g_value_set_pointer(value, message->timestamp);
+ g_value_set_boxed(value, purple_message_get_timestamp(message->message));
break;
case PROP_EDITED:
g_value_set_boolean(value, FALSE);
@@ -241,7 +234,6 @@
PidginMessage *message = PIDGIN_MESSAGE(obj);
g_clear_object(&message->message);
- g_clear_pointer(&message->timestamp, g_date_time_unref);
G_OBJECT_CLASS(pidgin_message_parent_class)->finalize(obj);
}