1 /*
2 * signalled-message.c - Source for TpSignalledMessage
3 * Copyright (C) 2006-2010 Collabora Ltd.
4 * Copyright (C) 2006-2008 Nokia Corporation
5 *
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 /**
22 * SECTION:signalled-message
23 * @title: TpSignalledMessage
24 * @short_description: a message received using the Telepathy message interface
25 *
26 * #TpSignalledMessage is used within Telepathy clients to represent a message
27 * signalled by a connection manager. This can either be a message received from
28 * someone else, confirmation that a message has been sent by the local user,
29 * or a delivery report indicating that delivery of a message has
30 * succeeded or failed.
31 *
32 * Since: 0.13.9
33 */
34
35 #include "config.h"
36
37 #include "signalled-message.h"
38 #include "signalled-message-internal.h"
39 #include "message-internal.h"
40
41 #include <telepathy-glib/dbus.h>
42 #include <telepathy-glib/gtypes.h>
43 #include <telepathy-glib/util.h>
44
45 /**
46 * TpSignalledMessage:
47 *
48 * Opaque structure representing a received message using the Telepathy
49 * messages interface
50 *
51 * Since: 0.13.9
52 */
53
54 enum
55 {
56 PROP_SENDER = 1
57 };
58
59 G_DEFINE_TYPE (TpSignalledMessage, tp_signalled_message, TP_TYPE_MESSAGE)
60
61 struct _TpSignalledMessagePrivate
62 {
63 TpContact *sender;
64 };
65
66 static void
tp_signalled_message_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)67 tp_signalled_message_get_property (GObject *object,
68 guint property_id,
69 GValue *value,
70 GParamSpec *pspec)
71 {
72 TpSignalledMessage *self = (TpSignalledMessage *) object;
73
74 switch (property_id)
75 {
76 case PROP_SENDER:
77 g_value_set_object (value, self->priv->sender);
78 break;
79
80 default:
81 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
82 break;
83 }
84 }
85
86 static void
tp_signalled_message_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)87 tp_signalled_message_set_property (GObject *object,
88 guint property_id,
89 const GValue *value,
90 GParamSpec *pspec)
91 {
92 TpSignalledMessage *self = (TpSignalledMessage *) object;
93
94 switch (property_id)
95 {
96 case PROP_SENDER:
97 g_assert (self->priv->sender == NULL); /* construct only */
98 self->priv->sender = g_value_dup_object (value);
99 break;
100
101 default:
102 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
103 break;
104 }
105 }
106
107 static void
tp_signalled_message_dispose(GObject * object)108 tp_signalled_message_dispose (GObject *object)
109 {
110 TpSignalledMessage *self = TP_SIGNALLED_MESSAGE (object);
111 void (*dispose) (GObject *) =
112 G_OBJECT_CLASS (tp_signalled_message_parent_class)->dispose;
113
114 tp_clear_object (&self->priv->sender);
115
116 if (dispose != NULL)
117 dispose (object);
118 }
119
120 static void
tp_signalled_message_class_init(TpSignalledMessageClass * klass)121 tp_signalled_message_class_init (TpSignalledMessageClass *klass)
122 {
123 GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
124 GParamSpec *param_spec;
125
126 gobject_class->get_property = tp_signalled_message_get_property;
127 gobject_class->set_property = tp_signalled_message_set_property;
128 gobject_class->dispose = tp_signalled_message_dispose;
129
130 /**
131 * TpSignalledMessage:sender:
132 *
133 * A #TpContact representing the sender of the message, if known, or %NULL
134 * otherwise.
135 *
136 * Since: 0.13.9
137 */
138 param_spec = g_param_spec_object ("sender", "TpContact",
139 "The sender of the message",
140 TP_TYPE_CONTACT,
141 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY | G_PARAM_STATIC_STRINGS);
142 g_object_class_install_property (gobject_class, PROP_SENDER,
143 param_spec);
144
145 g_type_class_add_private (gobject_class, sizeof (TpSignalledMessagePrivate));
146 }
147
148 static void
tp_signalled_message_init(TpSignalledMessage * self)149 tp_signalled_message_init (TpSignalledMessage *self)
150 {
151 self->priv = G_TYPE_INSTANCE_GET_PRIVATE ((self), TP_TYPE_SIGNALLED_MESSAGE,
152 TpSignalledMessagePrivate);
153
154 self->priv->sender = NULL;
155 }
156
157 /*
158 * Create a new TpSignalledMessage.
159 *
160 * Any message-sender and message-sender-id in parts[0] will be ignored
161 * completely: the caller is responsible for interpreting those fields
162 * and providing a suitable @sender.
163 *
164 * The message-sender will be removed from the header, and the
165 * message-sender-id will be set to match the #TpContact:identifier of @sender.
166 *
167 * @sender may be %NULL, which means the message wasn't sent by a contact
168 * (this could be used for administrative messages from a chatroom or the
169 * server) or we have no idea who sent it.
170 */
171 TpMessage *
_tp_signalled_message_new(const GPtrArray * parts,TpContact * sender)172 _tp_signalled_message_new (const GPtrArray *parts,
173 TpContact *sender)
174 {
175 TpMessage *self;
176 guint i;
177
178 g_return_val_if_fail (parts != NULL, NULL);
179 g_return_val_if_fail (parts->len > 0, NULL);
180 g_return_val_if_fail (sender == NULL || TP_IS_CONTACT (sender), NULL);
181
182 self = g_object_new (TP_TYPE_SIGNALLED_MESSAGE,
183 "sender", sender,
184 NULL);
185
186 for (i = 0; i < parts->len; i++)
187 {
188 /* First part is automatically created */
189 if (i != 0)
190 tp_message_append_part (self);
191
192 tp_g_hash_table_update (g_ptr_array_index (self->parts, i),
193 g_ptr_array_index (parts, i),
194 (GBoxedCopyFunc) g_strdup,
195 (GBoxedCopyFunc) tp_g_value_slice_dup);
196 }
197
198 /* This handle may not be persistent, user should use the TpContact
199 * directly */
200 tp_message_delete_key (self, 0, "message-sender");
201
202 /* override any message-sender-id that the message might have had */
203 if (sender == NULL)
204 {
205 tp_message_delete_key (self, 0, "message-sender-id");
206 }
207 else
208 {
209 tp_message_set_string (self, 0, "message-sender-id",
210 tp_contact_get_identifier (sender));
211 }
212
213 _tp_message_set_immutable (self);
214
215 return self;
216 }
217
218 /**
219 * tp_signalled_message_get_sender:
220 * @message: a #TpSignalledMessage
221 *
222 * Returns a #TpContact representing the sender of @message if known, %NULL
223 * otherwise.
224 *
225 * Returns: (transfer none): the sender of the message
226 *
227 * Since: 0.13.9
228 */
229 TpContact *
tp_signalled_message_get_sender(TpMessage * message)230 tp_signalled_message_get_sender (TpMessage *message)
231 {
232 TpSignalledMessage *self;
233
234 g_return_val_if_fail (TP_IS_SIGNALLED_MESSAGE (message), NULL);
235
236 self = (TpSignalledMessage *) message;
237
238 return self->priv->sender;
239 }
240
241 guint
_tp_signalled_message_get_pending_message_id(TpMessage * message,gboolean * valid)242 _tp_signalled_message_get_pending_message_id (TpMessage *message,
243 gboolean *valid)
244 {
245 const GHashTable *part0;
246
247 g_return_val_if_fail (TP_IS_SIGNALLED_MESSAGE (message), 0);
248 g_return_val_if_fail (valid != NULL, 0);
249
250 part0 = tp_message_peek (message, 0);
251 if (part0 == NULL)
252 {
253 *valid = FALSE;
254 return 0;
255 }
256
257 return tp_asv_get_uint32 (part0, "pending-message-id", valid);
258 }
259