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