1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /*
3 * SPDX-FileCopyrightText: (C) 2020 Red Hat (www.redhat.com)
4 * SPDX-License-Identifier: LGPL-2.1-or-later
5 */
6
7 #include "evolution-ews-config.h"
8
9 #include <stdio.h>
10
11 #include "camel/camel.h"
12
13 #include "camel-m365-message-info.h"
14
15 struct _CamelM365MessageInfoPrivate {
16 guint32 server_flags;
17 gint32 item_type;
18 gchar *change_key;
19 };
20
21 enum {
22 PROP_0,
23 PROP_SERVER_FLAGS,
24 PROP_ITEM_TYPE,
25 PROP_CHANGE_KEY,
26 };
27
G_DEFINE_TYPE_WITH_PRIVATE(CamelM365MessageInfo,camel_m365_message_info,CAMEL_TYPE_MESSAGE_INFO_BASE)28 G_DEFINE_TYPE_WITH_PRIVATE (CamelM365MessageInfo, camel_m365_message_info, CAMEL_TYPE_MESSAGE_INFO_BASE)
29
30 static CamelMessageInfo *
31 m365_message_info_clone (const CamelMessageInfo *mi,
32 CamelFolderSummary *assign_summary)
33 {
34 CamelMessageInfo *result;
35
36 g_return_val_if_fail (CAMEL_IS_M365_MESSAGE_INFO (mi), NULL);
37
38 result = CAMEL_MESSAGE_INFO_CLASS (camel_m365_message_info_parent_class)->clone (mi, assign_summary);
39 if (!result)
40 return NULL;
41
42 if (CAMEL_IS_M365_MESSAGE_INFO (result)) {
43 CamelM365MessageInfo *omi, *omi_result;
44
45 omi = CAMEL_M365_MESSAGE_INFO (mi);
46 omi_result = CAMEL_M365_MESSAGE_INFO (result);
47
48 camel_m365_message_info_set_server_flags (omi_result, camel_m365_message_info_get_server_flags (omi));
49 camel_m365_message_info_set_item_type (omi_result, camel_m365_message_info_get_item_type (omi));
50 camel_m365_message_info_take_change_key (omi_result, camel_m365_message_info_dup_change_key (omi));
51 }
52
53 return result;
54 }
55
56 static gboolean
m365_message_info_load(CamelMessageInfo * mi,const CamelMIRecord * record,gchar ** bdata_ptr)57 m365_message_info_load (CamelMessageInfo *mi,
58 const CamelMIRecord *record,
59 /* const */ gchar **bdata_ptr)
60 {
61 CamelM365MessageInfo *omi;
62
63 g_return_val_if_fail (CAMEL_IS_M365_MESSAGE_INFO (mi), FALSE);
64 g_return_val_if_fail (record != NULL, FALSE);
65 g_return_val_if_fail (bdata_ptr != NULL, FALSE);
66
67 if (!CAMEL_MESSAGE_INFO_CLASS (camel_m365_message_info_parent_class)->load ||
68 !CAMEL_MESSAGE_INFO_CLASS (camel_m365_message_info_parent_class)->load (mi, record, bdata_ptr))
69 return FALSE;
70
71 omi = CAMEL_M365_MESSAGE_INFO (mi);
72
73 if (*bdata_ptr) {
74 gchar **values;
75
76 values = g_strsplit (*bdata_ptr, " ", -1);
77
78 if (values && values[0] && values[1] && values[2]) {
79 camel_m365_message_info_set_server_flags (omi, g_ascii_strtoll (values[0], NULL, 10));
80 camel_m365_message_info_set_item_type (omi, g_ascii_strtoll (values[1], NULL, 10));
81 camel_m365_message_info_set_change_key (omi, values[2]);
82 }
83
84 g_strfreev (values);
85 }
86
87 return TRUE;
88 }
89
90 static gboolean
m365_message_info_save(const CamelMessageInfo * mi,CamelMIRecord * record,GString * bdata_str)91 m365_message_info_save (const CamelMessageInfo *mi,
92 CamelMIRecord *record,
93 GString *bdata_str)
94 {
95 CamelM365MessageInfo *omi;
96
97 g_return_val_if_fail (CAMEL_IS_M365_MESSAGE_INFO (mi), FALSE);
98 g_return_val_if_fail (record != NULL, FALSE);
99 g_return_val_if_fail (bdata_str != NULL, FALSE);
100
101 if (!CAMEL_MESSAGE_INFO_CLASS (camel_m365_message_info_parent_class)->save ||
102 !CAMEL_MESSAGE_INFO_CLASS (camel_m365_message_info_parent_class)->save (mi, record, bdata_str))
103 return FALSE;
104
105 omi = CAMEL_M365_MESSAGE_INFO (mi);
106
107 g_string_append_printf (bdata_str, "%u %d %s",
108 camel_m365_message_info_get_server_flags (omi),
109 camel_m365_message_info_get_item_type (omi),
110 camel_m365_message_info_get_change_key (omi));
111
112 return TRUE;
113 }
114
115 static void
m365_message_info_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)116 m365_message_info_set_property (GObject *object,
117 guint property_id,
118 const GValue *value,
119 GParamSpec *pspec)
120 {
121 CamelM365MessageInfo *omi = CAMEL_M365_MESSAGE_INFO (object);
122
123 switch (property_id) {
124 case PROP_SERVER_FLAGS:
125 camel_m365_message_info_set_server_flags (omi, g_value_get_uint (value));
126 return;
127
128 case PROP_ITEM_TYPE:
129 camel_m365_message_info_set_item_type (omi, g_value_get_int (value));
130 return;
131
132 case PROP_CHANGE_KEY:
133 camel_m365_message_info_set_change_key (omi, g_value_get_string (value));
134 return;
135 }
136
137 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
138 }
139
140 static void
m365_message_info_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)141 m365_message_info_get_property (GObject *object,
142 guint property_id,
143 GValue *value,
144 GParamSpec *pspec)
145 {
146 CamelM365MessageInfo *omi = CAMEL_M365_MESSAGE_INFO (object);
147
148 switch (property_id) {
149
150 case PROP_SERVER_FLAGS:
151 g_value_set_uint (value, camel_m365_message_info_get_server_flags (omi));
152 return;
153
154 case PROP_ITEM_TYPE:
155 g_value_set_int (value, camel_m365_message_info_get_item_type (omi));
156 return;
157
158 case PROP_CHANGE_KEY:
159 g_value_take_string (value, camel_m365_message_info_dup_change_key (omi));
160 return;
161 }
162
163 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
164 }
165
166 static void
m365_message_info_dispose(GObject * object)167 m365_message_info_dispose (GObject *object)
168 {
169 CamelM365MessageInfo *omi = CAMEL_M365_MESSAGE_INFO (object);
170
171 g_free (omi->priv->change_key);
172 omi->priv->change_key = NULL;
173
174 /* Chain up to parent's method. */
175 G_OBJECT_CLASS (camel_m365_message_info_parent_class)->dispose (object);
176 }
177
178 static void
camel_m365_message_info_class_init(CamelM365MessageInfoClass * class)179 camel_m365_message_info_class_init (CamelM365MessageInfoClass *class)
180 {
181 CamelMessageInfoClass *mi_class;
182 GObjectClass *object_class;
183
184 mi_class = CAMEL_MESSAGE_INFO_CLASS (class);
185 mi_class->clone = m365_message_info_clone;
186 mi_class->load = m365_message_info_load;
187 mi_class->save = m365_message_info_save;
188
189 object_class = G_OBJECT_CLASS (class);
190 object_class->set_property = m365_message_info_set_property;
191 object_class->get_property = m365_message_info_get_property;
192 object_class->dispose = m365_message_info_dispose;
193
194 /*
195 * CamelM365MessageInfo:server-flags
196 *
197 * Last known server flags of the message.
198 */
199 g_object_class_install_property (
200 object_class,
201 PROP_SERVER_FLAGS,
202 g_param_spec_uint (
203 "server-flags",
204 "Server Flags",
205 NULL,
206 0, G_MAXUINT32, 0,
207 G_PARAM_READWRITE));
208
209 /*
210 * CamelM365MessageInfo:item-type
211 *
212 * Item type of the message.
213 */
214 g_object_class_install_property (
215 object_class,
216 PROP_ITEM_TYPE,
217 g_param_spec_int (
218 "item-type",
219 "Item Type",
220 NULL,
221 0, G_MAXINT32, 0,
222 G_PARAM_READWRITE));
223
224 /*
225 * CamelM365MessageInfo:change-key
226 *
227 * Change key of the message on the server.
228 */
229 g_object_class_install_property (
230 object_class,
231 PROP_CHANGE_KEY,
232 g_param_spec_string (
233 "change-key",
234 "Change Key",
235 NULL,
236 NULL,
237 G_PARAM_READWRITE));
238 }
239
240 static void
camel_m365_message_info_init(CamelM365MessageInfo * omi)241 camel_m365_message_info_init (CamelM365MessageInfo *omi)
242 {
243 omi->priv = camel_m365_message_info_get_instance_private (omi);
244 }
245
246 guint32
camel_m365_message_info_get_server_flags(const CamelM365MessageInfo * omi)247 camel_m365_message_info_get_server_flags (const CamelM365MessageInfo *omi)
248 {
249 CamelMessageInfo *mi;
250 guint32 result;
251
252 g_return_val_if_fail (CAMEL_IS_M365_MESSAGE_INFO (omi), 0);
253
254 mi = CAMEL_MESSAGE_INFO (omi);
255
256 camel_message_info_property_lock (mi);
257 result = omi->priv->server_flags;
258 camel_message_info_property_unlock (mi);
259
260 return result;
261 }
262
263 gboolean
camel_m365_message_info_set_server_flags(CamelM365MessageInfo * omi,guint32 server_flags)264 camel_m365_message_info_set_server_flags (CamelM365MessageInfo *omi,
265 guint32 server_flags)
266 {
267 CamelMessageInfo *mi;
268 gboolean changed;
269
270 g_return_val_if_fail (CAMEL_IS_M365_MESSAGE_INFO (omi), FALSE);
271
272 mi = CAMEL_MESSAGE_INFO (omi);
273
274 camel_message_info_property_lock (mi);
275
276 changed = omi->priv->server_flags != server_flags;
277
278 if (changed)
279 omi->priv->server_flags = server_flags;
280
281 camel_message_info_property_unlock (mi);
282
283 if (changed && !camel_message_info_get_abort_notifications (mi)) {
284 g_object_notify (G_OBJECT (omi), "server-flags");
285 camel_message_info_set_dirty (mi, TRUE);
286 }
287
288 return changed;
289 }
290
291 gint32
camel_m365_message_info_get_item_type(const CamelM365MessageInfo * omi)292 camel_m365_message_info_get_item_type (const CamelM365MessageInfo *omi)
293 {
294 CamelMessageInfo *mi;
295 gint32 result;
296
297 g_return_val_if_fail (CAMEL_IS_M365_MESSAGE_INFO (omi), 0);
298
299 mi = CAMEL_MESSAGE_INFO (omi);
300
301 camel_message_info_property_lock (mi);
302 result = omi->priv->item_type;
303 camel_message_info_property_unlock (mi);
304
305 return result;
306 }
307
308 gboolean
camel_m365_message_info_set_item_type(CamelM365MessageInfo * omi,gint32 item_type)309 camel_m365_message_info_set_item_type (CamelM365MessageInfo *omi,
310 gint32 item_type)
311 {
312 CamelMessageInfo *mi;
313 gboolean changed;
314
315 g_return_val_if_fail (CAMEL_IS_M365_MESSAGE_INFO (omi), FALSE);
316
317 mi = CAMEL_MESSAGE_INFO (omi);
318
319 camel_message_info_property_lock (mi);
320
321 changed = omi->priv->item_type != item_type;
322
323 if (changed)
324 omi->priv->item_type = item_type;
325
326 camel_message_info_property_unlock (mi);
327
328 if (changed && !camel_message_info_get_abort_notifications (mi)) {
329 g_object_notify (G_OBJECT (omi), "item-type");
330 camel_message_info_set_dirty (mi, TRUE);
331 }
332
333 return changed;
334 }
335
336 const gchar *
camel_m365_message_info_get_change_key(const CamelM365MessageInfo * omi)337 camel_m365_message_info_get_change_key (const CamelM365MessageInfo *omi)
338 {
339 CamelMessageInfo *mi;
340 const gchar *result;
341
342 g_return_val_if_fail (CAMEL_IS_M365_MESSAGE_INFO (omi), NULL);
343
344 mi = CAMEL_MESSAGE_INFO (omi);
345
346 camel_message_info_property_lock (mi);
347 result = omi->priv->change_key;
348 camel_message_info_property_unlock (mi);
349
350 return result;
351 }
352
353 gchar *
camel_m365_message_info_dup_change_key(const CamelM365MessageInfo * omi)354 camel_m365_message_info_dup_change_key (const CamelM365MessageInfo *omi)
355 {
356 CamelMessageInfo *mi;
357 gchar *result;
358
359 g_return_val_if_fail (CAMEL_IS_M365_MESSAGE_INFO (omi), NULL);
360
361 mi = CAMEL_MESSAGE_INFO (omi);
362
363 camel_message_info_property_lock (mi);
364 result = g_strdup (omi->priv->change_key);
365 camel_message_info_property_unlock (mi);
366
367 return result;
368 }
369
370 gboolean
camel_m365_message_info_set_change_key(CamelM365MessageInfo * omi,const gchar * change_key)371 camel_m365_message_info_set_change_key (CamelM365MessageInfo *omi,
372 const gchar *change_key)
373 {
374 g_return_val_if_fail (CAMEL_IS_M365_MESSAGE_INFO (omi), FALSE);
375
376 return camel_m365_message_info_take_change_key (omi, g_strdup (change_key));
377 }
378
379 gboolean
camel_m365_message_info_take_change_key(CamelM365MessageInfo * omi,gchar * change_key)380 camel_m365_message_info_take_change_key (CamelM365MessageInfo *omi,
381 gchar *change_key)
382 {
383 CamelMessageInfo *mi;
384 gboolean changed;
385
386 g_return_val_if_fail (CAMEL_IS_M365_MESSAGE_INFO (omi), FALSE);
387
388 mi = CAMEL_MESSAGE_INFO (omi);
389
390 camel_message_info_property_lock (mi);
391
392 changed = g_strcmp0 (omi->priv->change_key, change_key) != 0;
393
394 if (changed) {
395 g_free (omi->priv->change_key);
396 omi->priv->change_key = change_key;
397 } else if (change_key != omi->priv->change_key) {
398 g_free (change_key);
399 }
400
401 camel_message_info_property_unlock (mi);
402
403 if (changed && !camel_message_info_get_abort_notifications (mi)) {
404 g_object_notify (G_OBJECT (omi), "change-key");
405 camel_message_info_set_dirty (mi, TRUE);
406 }
407
408 return changed;
409 }
410