]> git.0d.be Git - empathy.git/blobdiff - libempathy/empathy-message.c
update gnome-contacts's desktop file
[empathy.git] / libempathy / empathy-message.c
index d020b72e4de23fdb2435edf0e44693d9bb81848c..ab683c717e2c753c70cb86f4e62e834f44369357 100644 (file)
  */
 
 #include "config.h"
+#include "empathy-message.h"
 
-#include <string.h>
-
-#include <telepathy-glib/util.h>
+#include <glib/gi18n-lib.h>
+#include <tp-account-widgets/tpaw-time.h>
 
-#include "empathy-message.h"
+#include "empathy-client-factory.h"
 #include "empathy-utils.h"
 #include "empathy-enum-types.h"
 
 #define GET_PRIV(obj) EMPATHY_GET_PRIV (obj, EmpathyMessage)
 typedef struct {
+       TpMessage *tp_message;
        TpChannelTextMessageType  type;
        EmpathyContact           *sender;
        EmpathyContact           *receiver;
+       gchar                    *token;
+       gchar                    *supersedes;
        gchar                    *body;
-       time_t                    timestamp;
+       gint64                    timestamp;
+       gint64                    original_timestamp;
+       gboolean                  is_backlog;
        guint                     id;
+       gboolean                  incoming;
 } EmpathyMessagePriv;
 
 static void empathy_message_finalize   (GObject            *object);
@@ -59,8 +65,14 @@ enum {
        PROP_TYPE,
        PROP_SENDER,
        PROP_RECEIVER,
+       PROP_TOKEN,
+       PROP_SUPERSEDES,
        PROP_BODY,
        PROP_TIMESTAMP,
+       PROP_ORIGINAL_TIMESTAMP,
+       PROP_IS_BACKLOG,
+       PROP_INCOMING,
+       PROP_TP_MESSAGE,
 };
 
 static void
@@ -81,38 +93,86 @@ empathy_message_class_init (EmpathyMessageClass *class)
                                                            TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
                                                            TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY,
                                                            TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL,
-                                                           G_PARAM_READWRITE));
+                                                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+                                                           G_PARAM_CONSTRUCT_ONLY));
        g_object_class_install_property (object_class,
                                         PROP_SENDER,
                                         g_param_spec_object ("sender",
                                                              "Message Sender",
                                                              "The sender of the message",
                                                              EMPATHY_TYPE_CONTACT,
-                                                             G_PARAM_READWRITE));
+                                                             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
        g_object_class_install_property (object_class,
                                         PROP_RECEIVER,
                                         g_param_spec_object ("receiver",
                                                              "Message Receiver",
                                                              "The receiver of the message",
                                                              EMPATHY_TYPE_CONTACT,
-                                                             G_PARAM_READWRITE));
+                                                             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+       g_object_class_install_property (object_class,
+                                        PROP_TOKEN,
+                                        g_param_spec_string ("token",
+                                                             "Message Token",
+                                                             "The message-token",
+                                                             NULL,
+                                                             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
+       g_object_class_install_property (object_class,
+                                        PROP_SUPERSEDES,
+                                        g_param_spec_string ("supersedes",
+                                                             "Supersedes Token",
+                                                             "The message-token this message supersedes",
+                                                             NULL,
+                                                             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
        g_object_class_install_property (object_class,
                                         PROP_BODY,
                                         g_param_spec_string ("body",
                                                              "Message Body",
                                                              "The content of the message",
                                                              NULL,
-                                                             G_PARAM_READWRITE));
+                                                             G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+                                                             G_PARAM_CONSTRUCT_ONLY));
        g_object_class_install_property (object_class,
                                         PROP_TIMESTAMP,
-                                        g_param_spec_long ("timestamp",
+                                        g_param_spec_int64 ("timestamp",
                                                            "timestamp",
                                                            "timestamp",
-                                                           -1,
-                                                           G_MAXLONG,
-                                                           -1,
-                                                           G_PARAM_READWRITE));
+                                                           G_MININT64, G_MAXINT64, 0,
+                                                           G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+                                                           G_PARAM_CONSTRUCT_ONLY));
+       g_object_class_install_property (object_class,
+                                        PROP_ORIGINAL_TIMESTAMP,
+                                        g_param_spec_int64 ("original-timestamp",
+                                                            "Original Timestamp",
+                                                            "Timestamp of the original message",
+                                                            G_MININT64, G_MAXINT64, 0,
+                                                            G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS | G_PARAM_CONSTRUCT_ONLY));
+       g_object_class_install_property (object_class,
+                                        PROP_IS_BACKLOG,
+                                        g_param_spec_boolean ("is-backlog",
+                                                              "History message",
+                                                              "If the message belongs to history",
+                                                              FALSE,
+                                                              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+                                                              G_PARAM_CONSTRUCT_ONLY));
+
+
+       g_object_class_install_property (object_class,
+                                        PROP_INCOMING,
+                                        g_param_spec_boolean ("incoming",
+                                                              "Incoming",
+                                                              "If this is an incoming (as opposed to sent) message",
+                                                              FALSE,
+                                                              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+                                                              G_PARAM_CONSTRUCT_ONLY));
 
+       g_object_class_install_property (object_class,
+                                        PROP_TP_MESSAGE,
+                                        g_param_spec_object ("tp-message",
+                                                              "TpMessage",
+                                                              "The TpMessage of this message",
+                                                              TP_TYPE_MESSAGE,
+                                                              G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+                                                              G_PARAM_CONSTRUCT_ONLY));
 
        g_type_class_add_private (object_class, sizeof (EmpathyMessagePriv));
 
@@ -125,7 +185,7 @@ empathy_message_init (EmpathyMessage *message)
                EMPATHY_TYPE_MESSAGE, EmpathyMessagePriv);
 
        message->priv = priv;
-       priv->timestamp = empathy_time_get_current ();
+       priv->timestamp = tpaw_time_get_current ();
 }
 
 static void
@@ -142,6 +202,12 @@ empathy_message_finalize (GObject *object)
                g_object_unref (priv->receiver);
        }
 
+       if (priv->tp_message) {
+               g_object_unref (priv->tp_message);
+       }
+
+       g_free (priv->token);
+       g_free (priv->supersedes);
        g_free (priv->body);
 
        G_OBJECT_CLASS (empathy_message_parent_class)->finalize (object);
@@ -167,9 +233,30 @@ message_get_property (GObject    *object,
        case PROP_RECEIVER:
                g_value_set_object (value, priv->receiver);
                break;
+       case PROP_TOKEN:
+               g_value_set_string (value, priv->token);
+               break;
+       case PROP_SUPERSEDES:
+               g_value_set_string (value, priv->supersedes);
+               break;
        case PROP_BODY:
                g_value_set_string (value, priv->body);
                break;
+       case PROP_TIMESTAMP:
+               g_value_set_int64 (value, priv->timestamp);
+               break;
+       case PROP_ORIGINAL_TIMESTAMP:
+               g_value_set_int64 (value, priv->original_timestamp);
+               break;
+       case PROP_IS_BACKLOG:
+               g_value_set_boolean (value, priv->is_backlog);
+               break;
+       case PROP_INCOMING:
+               g_value_set_boolean (value, priv->incoming);
+               break;
+       case PROP_TP_MESSAGE:
+               g_value_set_object (value, priv->tp_message);
+               break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
                break;
@@ -188,8 +275,7 @@ message_set_property (GObject      *object,
 
        switch (param_id) {
        case PROP_TYPE:
-               empathy_message_set_tptype (EMPATHY_MESSAGE (object),
-                                           g_value_get_uint (value));
+               priv->type = g_value_get_uint (value);
                break;
        case PROP_SENDER:
                empathy_message_set_sender (EMPATHY_MESSAGE (object),
@@ -199,9 +285,34 @@ message_set_property (GObject      *object,
                empathy_message_set_receiver (EMPATHY_MESSAGE (object),
                                             EMPATHY_CONTACT (g_value_get_object (value)));
                break;
+       case PROP_TOKEN:
+               g_assert (priv->token == NULL); /* construct only */
+               priv->token = g_value_dup_string (value);
+               break;
+       case PROP_SUPERSEDES:
+               g_assert (priv->supersedes == NULL); /* construct only */
+               priv->supersedes = g_value_dup_string (value);
+               break;
        case PROP_BODY:
-               empathy_message_set_body (EMPATHY_MESSAGE (object),
-                                        g_value_get_string (value));
+               g_assert (priv->body == NULL); /* construct only */
+               priv->body = g_value_dup_string (value);
+               break;
+       case PROP_TIMESTAMP:
+               priv->timestamp = g_value_get_int64 (value);
+               if (priv->timestamp <= 0)
+                       priv->timestamp = tpaw_time_get_current ();
+               break;
+       case PROP_ORIGINAL_TIMESTAMP:
+               priv->original_timestamp = g_value_get_int64 (value);
+               break;
+       case PROP_IS_BACKLOG:
+               priv->is_backlog = g_value_get_boolean (value);
+               break;
+       case PROP_INCOMING:
+               priv->incoming = g_value_get_boolean (value);
+               break;
+       case PROP_TP_MESSAGE:
+               priv->tp_message = g_value_dup_object (value);
                break;
        default:
                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, param_id, pspec);
@@ -210,39 +321,135 @@ message_set_property (GObject      *object,
 }
 
 EmpathyMessage *
-empathy_message_new (const gchar *body)
+empathy_message_from_tpl_log_event (TplEvent *logevent)
 {
-       return g_object_new (EMPATHY_TYPE_MESSAGE,
-                            "body", body,
-                            NULL);
+       EmpathyMessage *retval = NULL;
+       EmpathyClientFactory *factory;
+       TpAccount *account = NULL;
+       TplEntity *receiver = NULL;
+       TplEntity *sender = NULL;
+       gchar *body = NULL;
+       const gchar *token = NULL, *supersedes = NULL;
+       EmpathyContact *contact;
+       TpChannelTextMessageType type = TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
+       gint64 timestamp, original_timestamp = 0;
+
+       g_return_val_if_fail (TPL_IS_EVENT (logevent), NULL);
+
+       factory = empathy_client_factory_dup ();
+       /* FIXME Currently Empathy shows in the log viewer only valid accounts, so it
+        * won't be selected any non-existing (ie removed) account.
+        * When #610455 will be fixed, calling tp_account_manager_ensure_account ()
+        * might add a not existing account to the AM. tp_account_new () probably
+        * will be the best way to handle it.
+        * Note: When creating an EmpathyContact from a TplEntity instance, the
+        * TpAccount is passed *only* to let EmpathyContact be able to retrieve the
+        * avatar (contact_get_avatar_filename () need a TpAccount).
+        * If the way EmpathyContact stores the avatar is changes, it might not be
+        * needed anymore any TpAccount passing and the following call will be
+        * useless */
+       account = tp_simple_client_factory_ensure_account (
+                       TP_SIMPLE_CLIENT_FACTORY (factory),
+                       tpl_event_get_account_path (logevent), NULL, NULL);
+       g_object_unref (factory);
+
+       if (TPL_IS_TEXT_EVENT (logevent)) {
+               TplTextEvent *textevent = TPL_TEXT_EVENT (logevent);
+
+               supersedes = tpl_text_event_get_supersedes_token (textevent);
+
+               /* tp-logger is kind of messy in that instead of having
+                * timestamp and original-timestamp like Telepathy it has
+                * timestamp (which is the original) and edited-timestamp,
+                * (which is when the message was edited) */
+               if (tp_str_empty (supersedes)) {
+                       /* not an edited message */
+                       timestamp = tpl_event_get_timestamp (logevent);
+               } else {
+                       /* this is an edited event */
+                       original_timestamp = tpl_event_get_timestamp (logevent);
+                       timestamp = tpl_text_event_get_edit_timestamp (textevent);
+               }
+
+               body = g_strdup (tpl_text_event_get_message (textevent));
+
+               type = tpl_text_event_get_message_type (TPL_TEXT_EVENT (logevent));
+               token = tpl_text_event_get_message_token (textevent);
+       }
+       else if (TPL_IS_CALL_EVENT (logevent)) {
+               TplCallEvent *call = TPL_CALL_EVENT (logevent);
+
+               timestamp = tpl_event_get_timestamp (logevent);
+
+               if (tpl_call_event_get_end_reason (call) == TP_CALL_STATE_CHANGE_REASON_NO_ANSWER)
+                       body = g_strdup_printf (_("Missed call from %s"),
+                               tpl_entity_get_alias (tpl_event_get_sender (logevent)));
+               else if (tpl_entity_get_entity_type (tpl_event_get_sender (logevent)) == TPL_ENTITY_SELF)
+                       /* Translators: this is an outgoing call, e.g. 'Called Alice' */
+                       body = g_strdup_printf (_("Called %s"),
+                               tpl_entity_get_alias (tpl_event_get_receiver (logevent)));
+               else
+                       body = g_strdup_printf (_("Call from %s"),
+                               tpl_entity_get_alias (tpl_event_get_sender (logevent)));
+       }
+       else {
+               /* Unknown event type */
+               return NULL;
+       }
+
+       receiver = tpl_event_get_receiver (logevent);
+       sender = tpl_event_get_sender (logevent);
+
+       retval = g_object_new (EMPATHY_TYPE_MESSAGE,
+               "type", type,
+               "token", token,
+               "supersedes", supersedes,
+               "body", body,
+               "is-backlog", TRUE,
+               "timestamp", timestamp,
+               "original-timestamp", original_timestamp,
+               NULL);
+
+       if (receiver != NULL) {
+               contact = empathy_contact_from_tpl_contact (account, receiver);
+               empathy_message_set_receiver (retval, contact);
+               g_object_unref (contact);
+       }
+
+       if (sender != NULL) {
+               contact = empathy_contact_from_tpl_contact (account, sender);
+               empathy_message_set_sender (retval, contact);
+               g_object_unref (contact);
+       }
+
+       g_free (body);
+
+       return retval;
 }
 
-TpChannelTextMessageType
-empathy_message_get_tptype (EmpathyMessage *message)
+TpMessage *
+empathy_message_get_tp_message (EmpathyMessage *message)
 {
        EmpathyMessagePriv *priv;
 
-       g_return_val_if_fail (EMPATHY_IS_MESSAGE (message),
-                             TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL);
+       g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
 
        priv = GET_PRIV (message);
 
-       return priv->type;
+       return priv->tp_message;
 }
 
-void
-empathy_message_set_tptype (EmpathyMessage           *message,
-                           TpChannelTextMessageType  type)
+TpChannelTextMessageType
+empathy_message_get_tptype (EmpathyMessage *message)
 {
        EmpathyMessagePriv *priv;
 
-       g_return_if_fail (EMPATHY_IS_MESSAGE (message));
+       g_return_val_if_fail (EMPATHY_IS_MESSAGE (message),
+                             TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL);
 
        priv = GET_PRIV (message);
 
-       priv->type = type;
-
-       g_object_notify (G_OBJECT (message), "type");
+       return priv->type;
 }
 
 EmpathyContact *
@@ -312,7 +519,7 @@ empathy_message_set_receiver (EmpathyMessage *message, EmpathyContact *contact)
 }
 
 const gchar *
-empathy_message_get_body (EmpathyMessage *message)
+empathy_message_get_token (EmpathyMessage *message)
 {
        EmpathyMessagePriv *priv;
 
@@ -320,132 +527,79 @@ empathy_message_get_body (EmpathyMessage *message)
 
        priv = GET_PRIV (message);
 
-       return priv->body;
+       return priv->token;
 }
 
-void
-empathy_message_set_body (EmpathyMessage *message,
-                         const gchar    *body)
+const gchar *
+empathy_message_get_supersedes (EmpathyMessage *message)
 {
-       EmpathyMessagePriv       *priv = GET_PRIV (message);
-       TpChannelTextMessageType  type;
-
-       g_return_if_fail (EMPATHY_IS_MESSAGE (message));
-
-       g_free (priv->body);
-       priv->body = NULL;
-
-       type = TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL;
-       if (g_str_has_prefix (body, "/me")) {
-               type = TP_CHANNEL_TEXT_MESSAGE_TYPE_ACTION;
-               body += 4;
-       }
-       else if (g_str_has_prefix (body, "/say")) {
-               body += 5;
-       }
+       EmpathyMessagePriv *priv;
 
-       if (body) {
-               priv->body = g_strdup (body);
-       }
+       g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
 
-       if (type != priv->type) {
-               empathy_message_set_tptype (message, type);
-       }
+       priv = GET_PRIV (message);
 
-       g_object_notify (G_OBJECT (message), "body");
+       return priv->supersedes;
 }
 
-time_t
-empathy_message_get_timestamp (EmpathyMessage *message)
+gboolean
+empathy_message_is_edit (EmpathyMessage *message)
 {
        EmpathyMessagePriv *priv;
 
-       g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), -1);
+       g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
 
        priv = GET_PRIV (message);
 
-       return priv->timestamp;
+       return !tp_str_empty (priv->supersedes);
 }
 
-void
-empathy_message_set_timestamp (EmpathyMessage *message,
-                              time_t          timestamp)
+const gchar *
+empathy_message_get_body (EmpathyMessage *message)
 {
        EmpathyMessagePriv *priv;
 
-       g_return_if_fail (EMPATHY_IS_MESSAGE (message));
-       g_return_if_fail (timestamp >= -1);
+       g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), NULL);
 
        priv = GET_PRIV (message);
 
-       if (timestamp <= 0) {
-               priv->timestamp = empathy_time_get_current ();
-       } else {
-               priv->timestamp = timestamp;
-       }
-
-       g_object_notify (G_OBJECT (message), "timestamp");
+       return priv->body;
 }
 
-#define IS_SEPARATOR(ch) (ch == ' ' || ch == ',' || ch == '.' || ch == ':')
-gboolean
-empathy_message_should_highlight (EmpathyMessage *message)
+gint64
+empathy_message_get_timestamp (EmpathyMessage *message)
 {
-       EmpathyContact *contact;
-       const gchar   *msg, *to;
-       gchar         *cf_msg, *cf_to;
-       gchar         *ch;
-       gboolean       ret_val;
+       EmpathyMessagePriv *priv;
 
-       g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
+       g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), -1);
 
-       ret_val = FALSE;
+       priv = GET_PRIV (message);
 
-       msg = empathy_message_get_body (message);
-       if (!msg) {
-               return FALSE;
-       }
+       return priv->timestamp;
+}
 
-       contact = empathy_message_get_receiver (message);
-       if (!contact || !empathy_contact_is_user (contact)) {
-               return FALSE;
-       }
+gint64
+empathy_message_get_original_timestamp (EmpathyMessage *message)
+{
+       EmpathyMessagePriv *priv;
 
-       to = empathy_contact_get_name (contact);
-       if (!to) {
-               return FALSE;
-       }
+       g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), -1);
 
-       cf_msg = g_utf8_casefold (msg, -1);
-       cf_to = g_utf8_casefold (to, -1);
+       priv = GET_PRIV (message);
 
-       ch = strstr (cf_msg, cf_to);
-       if (ch == NULL) {
-               goto finished;
-       }
-       if (ch != cf_msg) {
-               /* Not first in the message */
-               if (!IS_SEPARATOR (*(ch - 1))) {
-                       goto finished;
-               }
-       }
+       return priv->original_timestamp;
+}
 
-       ch = ch + strlen (cf_to);
-       if (ch >= cf_msg + strlen (cf_msg)) {
-               ret_val = TRUE;
-               goto finished;
-       }
+gboolean
+empathy_message_is_backlog (EmpathyMessage *message)
+{
+       EmpathyMessagePriv *priv;
 
-       if (IS_SEPARATOR (*ch)) {
-               ret_val = TRUE;
-               goto finished;
-       }
+       g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
 
-finished:
-       g_free (cf_msg);
-       g_free (cf_to);
+       priv = GET_PRIV (message);
 
-       return ret_val;
+       return priv->is_backlog;
 }
 
 TpChannelTextMessageType
@@ -477,27 +631,22 @@ empathy_message_type_to_str (TpChannelTextMessageType type)
                return "notice";
        case TP_CHANNEL_TEXT_MESSAGE_TYPE_AUTO_REPLY:
                return "auto-reply";
+       case TP_CHANNEL_TEXT_MESSAGE_TYPE_DELIVERY_REPORT:
+               return "delivery-report";
+       case TP_CHANNEL_TEXT_MESSAGE_TYPE_NORMAL:
        default:
                return "normal";
        }
 }
 
-guint
-empathy_message_get_id (EmpathyMessage *message)
+gboolean
+empathy_message_is_incoming (EmpathyMessage *message)
 {
        EmpathyMessagePriv *priv = GET_PRIV (message);
 
-       g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), 0);
-
-       return priv->id;
-}
-
-void
-empathy_message_set_id (EmpathyMessage *message, guint id)
-{
-       EmpathyMessagePriv *priv = GET_PRIV (message);
+       g_return_val_if_fail (EMPATHY_IS_MESSAGE (message), FALSE);
 
-       priv->id = id;
+       return priv->incoming;
 }
 
 gboolean
@@ -512,9 +661,47 @@ empathy_message_equal (EmpathyMessage *message1, EmpathyMessage *message2)
        priv1 = GET_PRIV (message1);
        priv2 = GET_PRIV (message2);
 
-       if (priv1->id == priv2->id && !tp_strdiff (priv1->body, priv2->body)) {
+       if (priv1->timestamp == priv2->timestamp &&
+                       !tp_strdiff (priv1->body, priv2->body)) {
                return TRUE;
        }
 
        return FALSE;
 }
+
+EmpathyMessage *
+empathy_message_new_from_tp_message (TpMessage *tp_msg,
+                                    gboolean incoming)
+{
+       EmpathyMessage *message;
+       gchar *body;
+       gint64 timestamp;
+       gint64 original_timestamp;
+       const GHashTable *part = tp_message_peek (tp_msg, 0);
+
+       g_return_val_if_fail (TP_IS_MESSAGE (tp_msg), NULL);
+
+       body = tp_message_to_text (tp_msg, NULL);
+
+       timestamp = tp_message_get_sent_timestamp (tp_msg);
+       if (timestamp == 0)
+               timestamp = tp_message_get_received_timestamp (tp_msg);
+
+       original_timestamp = tp_asv_get_int64 (part,
+               "original-message-received", NULL);
+
+       message = g_object_new (EMPATHY_TYPE_MESSAGE,
+               "body", body,
+               "token", tp_message_get_token (tp_msg),
+               "supersedes", tp_message_get_supersedes (tp_msg),
+               "type", tp_message_get_message_type (tp_msg),
+               "timestamp", timestamp,
+               "original-timestamp", original_timestamp,
+               "is-backlog", tp_message_is_scrollback (tp_msg),
+               "incoming", incoming,
+               "tp-message", tp_msg,
+               NULL);
+
+       g_free (body);
+       return message;
+}