~ubuntu-branches/ubuntu/breezy/evolution-data-server/breezy

« back to all changes in this revision

Viewing changes to calendar/backends/groupwise/e-cal-backend-groupwise.c

  • Committer: Bazaar Package Importer
  • Author(s): Daniel Holbach
  • Date: 2005-10-10 11:30:56 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20051010113056-rb4vj4kbs8yxft85
Tags: 1.4.1-0ubuntu3
* debian/patches/camel-imap-store.c.patch:
  - Ubuntu 17465: apply patch from
  http://bugzilla.gnome.org/attachment.cgi?id=53234&action=view
  (additional NULL pointer check)

Show diffs side-by-side

added added

removed removed

Lines of Context:
7
7
 * Copyright 2003, Novell, Inc.
8
8
 *
9
9
 * This program is free software; you can redistribute it and/or 
10
 
 * modify it under the terms of version 2 of the GNU General Public 
 
10
 * modify it under the terms of version 2 of the GNU Lesser General Public 
11
11
 * License as published by the Free Software Foundation.
12
12
 *
13
13
 * This program is distributed in the hope that it will be useful,
14
14
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15
15
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
16
 
 * GNU General Public License for more details.
 
16
 * GNU Lesser General Public License for more details.
17
17
 *
18
 
 * You should have received a copy of the GNU General Public License
 
18
 * You should have received a copy of the GNU Lesser General Public License
19
19
 * along with this program; if not, write to the Free Software
20
20
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
21
21
 * USA
61
61
        GHashTable *categories_by_id;
62
62
        GHashTable *categories_by_name;
63
63
 
 
64
        /* number of calendar items in the folder */
 
65
        guint32 total_count;
 
66
        
64
67
        /* fields for storing info while offline */
65
68
        char *user_email;
66
69
        char *local_attachments_store;
68
71
 
69
72
static void e_cal_backend_groupwise_dispose (GObject *object);
70
73
static void e_cal_backend_groupwise_finalize (GObject *object);
 
74
static void sanitize_component (ECalBackendSync *backend, ECalComponent *comp, char *server_uid);
71
75
 
72
76
#define PARENT_TYPE E_TYPE_CAL_BACKEND_SYNC
73
77
static ECalBackendClass *parent_class = NULL;
75
79
/* Time interval in milliseconds for obtaining changes from server and refresh the cache. */
76
80
#define CACHE_REFRESH_INTERVAL 600000
77
81
#define CURSOR_ITEM_LIMIT 100
 
82
#define CURSOR_ICALID_LIMIT 500
78
83
 
79
84
EGwConnection *
80
85
e_cal_backend_groupwise_get_connection (ECalBackendGroupwise *cbgw) {
120
125
        GList *list = NULL, *l;
121
126
        gboolean done = FALSE;
122
127
        int cursor = 0;
 
128
        guint32 total, num = 0;
 
129
        int percent = 0;
123
130
        const char *position = E_GW_CURSOR_POSITION_END; 
124
131
        icalcomponent_kind kind;
125
 
        
 
132
        const char *type;
 
133
 
126
134
        priv = cbgw->priv;
127
135
        kind = e_cal_backend_get_kind (E_CAL_BACKEND (cbgw));
 
136
        total = priv->total_count;
128
137
        
129
138
        if (!mutex) {
130
139
                mutex = g_mutex_new ();
132
141
 
133
142
        g_mutex_lock (mutex);
134
143
 
 
144
        if (kind == ICAL_VEVENT_COMPONENT)
 
145
                type = "Calendar";
 
146
        else
 
147
                type = "Task";
135
148
        
136
149
        status = e_gw_connection_create_cursor (priv->cnc,
137
150
                        priv->container_id, 
138
 
                        "recipients message recipientStatus attachments default", NULL, &cursor);
 
151
                        "recipients message recipientStatus attachments default peek", NULL, &cursor);
139
152
        if (status != E_GW_CONNECTION_STATUS_OK) {
140
153
                e_cal_backend_groupwise_notify_error_code (cbgw, status);
141
154
                g_mutex_unlock (mutex);
152
165
                }
153
166
                for (l = list; l != NULL; l = g_list_next(l)) {
154
167
                        EGwItem *item;
 
168
                        char *progress_string = NULL;
155
169
                        
156
170
                        item = E_GW_ITEM (l->data);
157
171
                        comp = e_gw_item_to_cal_component (item, cbgw);
158
172
                        g_object_unref (item);
 
173
                        
 
174
                        /* Show the progress information */
 
175
                        num++;
 
176
                        percent = ((float) num/total) * 100;
 
177
                
 
178
                        /* FIXME The total obtained from the server is wrong. Sometimes the num can 
 
179
                        be greater than the total. The following makes sure that the percentage is not >= 100 */
 
180
 
 
181
                        if (percent > 100)
 
182
                                percent = 99; 
 
183
 
 
184
                        progress_string = g_strdup_printf (_("Loading %s items"), type);
 
185
                        e_cal_backend_notify_view_progress (E_CAL_BACKEND (cbgw), progress_string, percent);
 
186
                        
159
187
                        if (E_IS_CAL_COMPONENT (comp)) {
160
188
                                char *comp_str;
161
189
                                
168
196
                                e_cal_backend_cache_put_component (priv->cache, comp);
169
197
                                g_object_unref (comp);
170
198
                        }
 
199
                        g_free (progress_string);
171
200
                }
172
201
                
173
202
                if (!list  || g_list_length (list) == 0)
177
206
                position = E_GW_CURSOR_POSITION_CURRENT;
178
207
        }
179
208
        e_gw_connection_destroy_cursor (priv->cnc, priv->container_id, cursor);
 
209
        e_cal_backend_notify_view_done (E_CAL_BACKEND (cbgw), GNOME_Evolution_Calendar_Success);
180
210
 
181
211
        g_mutex_unlock (mutex);
182
212
 
183
213
        return E_GW_CONNECTION_STATUS_OK;
184
214
}
 
215
static gboolean
 
216
compare_prefix (gconstpointer a, gconstpointer b)
 
217
{
 
218
        return !(g_str_has_prefix ((const char *)a, (const char *)b));
 
219
}
185
220
 
186
221
static gboolean
187
222
get_deltas (gpointer handle)
188
223
{
189
 
        ECalBackendGroupwise *cbgw;
 
224
        ECalBackendGroupwise *cbgw;
190
225
        ECalBackendGroupwisePrivate *priv;
191
226
        EGwConnection *cnc; 
192
 
        ECalBackendCache *cache; 
193
 
        EGwConnectionStatus status; 
 
227
        ECalBackendCache *cache; 
 
228
        EGwConnectionStatus status; 
194
229
        icalcomponent_kind kind;
195
 
        GSList *item_list, *cache_keys, *l;
196
 
        char *comp_str;
 
230
        GList *item_list, *total_list = NULL, *l;
 
231
        GSList *cache_keys = NULL;
 
232
        GPtrArray *uid_array = g_ptr_array_new ();
197
233
        char *time_string = NULL;
198
234
        char t_str [100]; 
199
 
        struct stat buf;
200
 
        
 
235
        const char *serv_time;
 
236
        static GStaticMutex connecting = G_STATIC_MUTEX_INIT;
 
237
        const char *time_interval_string;
 
238
        const char *key = "attempts";
 
239
        const char *attempts;
 
240
        const char *position ;
 
241
        
 
242
 
 
243
        EGwFilter *filter;
 
244
        int time_interval;
 
245
        icaltimetype temp;
 
246
        gboolean done = FALSE;
 
247
        int cursor = 0;
 
248
        struct tm *tm;
 
249
        time_t current_time;
 
250
        gboolean needs_to_get = FALSE;
 
251
 
201
252
        if (!handle)
202
253
                return FALSE;
203
254
        cbgw = (ECalBackendGroupwise *) handle;
204
255
        priv= cbgw->priv;
205
256
        kind = e_cal_backend_get_kind (E_CAL_BACKEND (cbgw));
206
 
        cnc = priv->cnc; 
207
 
        cache = priv->cache; 
 
257
        cnc = priv->cnc; 
 
258
        cache = priv->cache; 
208
259
        item_list = NULL;
209
 
        
 
260
 
210
261
        if (priv->mode == CAL_MODE_LOCAL)
211
262
                return FALSE;
212
263
 
213
 
        g_strlcpy (t_str, e_cal_backend_cache_get_server_utc_time (cache), 100);
214
 
        if (!*t_str || !strcmp (t_str, "")) {
215
 
                icaltimetype temp;
216
 
                time_t current_time;
217
 
                const struct tm *tm;
218
 
 
219
 
                g_warning (" Could not get the correct time stamp for using in getQuick Messages\n");
 
264
        attempts = e_cal_backend_cache_get_key_value (cache, key);
 
265
 
 
266
        g_static_mutex_lock (&connecting);
 
267
 
 
268
        serv_time = e_cal_backend_cache_get_server_utc_time (cache);
 
269
        if (serv_time) {
 
270
                g_strlcpy (t_str, e_cal_backend_cache_get_server_utc_time (cache), 100);
 
271
                if (!*t_str || !strcmp (t_str, "")) {
 
272
                        /* FIXME: When time-stamp is crashed, getting changes from current time */
 
273
                        g_warning ("\n\a Could not get the correct time stamp. \n\a");
 
274
                        temp = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
 
275
                        current_time = icaltime_as_timet_with_zone (temp, icaltimezone_get_utc_timezone ());
 
276
                        tm = gmtime (&current_time);
 
277
                        strftime (t_str, 100, "%Y-%m-%dT%H:%M:%SZ", tm);
 
278
                }
 
279
        } else {
 
280
                /* FIXME: When time-stamp is crashed, getting changes from current time */
 
281
                g_warning ("\n\a Could not get the correct time stamp. \n\a");
220
282
                temp = icaltime_current_time_with_zone (icaltimezone_get_utc_timezone ());
221
283
                current_time = icaltime_as_timet_with_zone (temp, icaltimezone_get_utc_timezone ());
222
284
                tm = gmtime (&current_time);
223
285
                strftime (t_str, 100, "%Y-%m-%dT%H:%M:%SZ", tm);
224
286
        }
225
 
 
226
 
        time_string = g_strdup (t_str);
227
 
        status = e_gw_connection_get_quick_messages (cnc, cbgw->priv->container_id, "attachments recipients message recipientStatus default peek", &time_string, "New", "CalendarItem", NULL,  -1,  &item_list);
228
 
        
229
 
        if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
230
 
                status = e_gw_connection_get_quick_messages (cnc, cbgw->priv->container_id, "attachments recipients message recipientStatus default peek", &time_string, "New", "CalendarItem", NULL,  -1,  &item_list);
231
 
        
232
 
        if (status != E_GW_CONNECTION_STATUS_OK) {
233
 
                                
234
 
                if (status == E_GW_CONNECTION_STATUS_NO_RESPONSE) 
235
 
                        return TRUE;
236
 
 
237
 
                e_cal_backend_groupwise_notify_error_code (cbgw, status);
238
 
                return TRUE;
239
 
        }
240
 
        /* store the timestamp in the cache */  
241
 
        e_cal_backend_cache_put_server_utc_time (cache, time_string);
242
 
        g_free (time_string), time_string = NULL;
243
 
 
244
 
        e_file_cache_freeze_changes (E_FILE_CACHE (cache));
245
 
        for (; item_list != NULL; item_list = g_slist_next(item_list)) {
246
 
                EGwItem *item = E_GW_ITEM(item_list->data);
247
 
                ECalComponent *comp = e_gw_item_to_cal_component (item, cbgw);
248
 
                
249
 
                e_cal_component_commit_sequence (comp);
250
 
 
251
 
                if (comp) {
252
 
                        if (!e_cal_backend_cache_put_component (cache, comp)) 
253
 
                                g_message ("Could not add the component");
254
 
                        else  {
255
 
                                if (kind == icalcomponent_isa (e_cal_component_get_icalcomponent (comp))) {
256
 
                                        comp_str = e_cal_component_get_as_string (comp);        
257
 
                                        e_cal_backend_notify_object_created (E_CAL_BACKEND (cbgw), comp_str);
258
 
                                        g_free (comp_str);
259
 
                                }
260
 
                        }
261
 
                }
262
 
                else 
263
 
                        g_message ("Invalid component returned");
264
 
 
265
 
                g_object_unref (comp);
266
 
                g_object_unref (item);
267
 
        }
268
 
        if (item_list) {
269
 
                g_slist_free (item_list);
270
 
                item_list = NULL;
271
 
        }
272
 
        e_file_cache_thaw_changes (E_FILE_CACHE (cache));
273
 
        
274
 
        /* We must use the same timestamp used for getQm call with message list New */ 
275
 
        time_string = g_strdup (t_str);
276
 
 
277
 
        status = e_gw_connection_get_quick_messages (cnc, cbgw->priv->container_id,"attachments recipients message recipientStatus  default", &time_string, "Modified", "CalendarItem", NULL,  -1,  &item_list);
278
 
        
279
 
        if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
280
 
                status = e_gw_connection_get_quick_messages (cnc, cbgw->priv->container_id,"recipients message recipientStatus  default", &time_string, "Modified", "CalendarItem", NULL,  -1,  &item_list);
281
 
 
282
 
                
283
 
        g_free (time_string);
284
 
        if (status != E_GW_CONNECTION_STATUS_OK) {
285
 
                if (status == E_GW_CONNECTION_STATUS_NO_RESPONSE) 
286
 
                        return TRUE;
287
 
 
288
 
                e_cal_backend_groupwise_notify_error_code (cbgw, status);
289
 
                return TRUE;
290
 
        }
291
 
 
292
 
 
293
 
        e_file_cache_freeze_changes (E_FILE_CACHE (cache));
294
 
        
295
 
        for (; item_list != NULL; item_list = g_slist_next(item_list)) {
296
 
                EGwItem *item = E_GW_ITEM(item_list->data);
297
 
                ECalComponent *modified_comp, *cache_comp;
298
 
                char *cache_comp_str;
299
 
                
 
287
        time_string = g_strdup (t_str);
 
288
 
 
289
        filter = e_gw_filter_new ();
 
290
        /* Items modified after the time-stamp */
 
291
        e_gw_filter_add_filter_component (filter, E_GW_FILTER_OP_GREATERTHAN, "modified", time_string);
 
292
 
 
293
        status = e_gw_connection_get_items (cnc, cbgw->priv->container_id, "attachments recipients message recipientStatus default peek", filter, &item_list);
 
294
        if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
 
295
                status = e_gw_connection_get_items (cnc, cbgw->priv->container_id, "attachments recipients message recipientStatus default peek", filter, &item_list);
 
296
        g_object_unref (filter);
 
297
 
 
298
        if (status != E_GW_CONNECTION_STATUS_OK) {
 
299
 
 
300
                const char *msg = NULL;
 
301
 
 
302
                if (!attempts) {
 
303
                        e_cal_backend_cache_put_key_value (cache, key, "2");
 
304
                } else {
 
305
                        int failures;
 
306
                        failures = g_ascii_strtod(attempts, NULL) + 1;
 
307
                        e_cal_backend_cache_put_key_value (cache, key, GINT_TO_POINTER (failures));
 
308
                }
 
309
 
 
310
                if (status == E_GW_CONNECTION_STATUS_NO_RESPONSE) { 
 
311
                        g_static_mutex_unlock (&connecting);
 
312
                        return TRUE;
 
313
                }
 
314
 
 
315
                msg = e_gw_connection_get_error_message (status);
 
316
 
 
317
                g_static_mutex_unlock (&connecting);
 
318
                return TRUE;
 
319
        }
 
320
 
 
321
        e_file_cache_freeze_changes (E_FILE_CACHE (cache));
 
322
 
 
323
        for (; item_list != NULL; item_list = g_list_next(item_list)) {
 
324
                EGwItem *item = NULL;
 
325
                item = E_GW_ITEM(item_list->data);
 
326
                ECalComponent *modified_comp = NULL, *cache_comp = NULL;
 
327
                char *cache_comp_str = NULL;
 
328
                const char *uid, *rid = NULL;
 
329
                int r_key;
 
330
 
300
331
                modified_comp = e_gw_item_to_cal_component (item, cbgw);
301
332
                if (!modified_comp) {
302
333
                        g_message ("Invalid component returned in update");
303
334
                        continue;
304
335
                }
305
 
                cache_comp = e_cal_backend_cache_get_component (cache, e_gw_item_get_icalid (item), NULL);
 
336
                if ((r_key = e_gw_item_get_recurrence_key (item)) != 0)
 
337
                        rid = e_cal_component_get_recurid_as_string (modified_comp);
 
338
                
 
339
                e_cal_component_get_uid (modified_comp, &uid);          
 
340
                cache_comp = e_cal_backend_cache_get_component (cache, uid, rid);
306
341
                e_cal_component_commit_sequence (modified_comp);
307
342
                e_cal_component_commit_sequence (cache_comp);
308
343
 
310
345
                        cache_comp_str = e_cal_component_get_as_string (cache_comp);
311
346
                        e_cal_backend_notify_object_modified (E_CAL_BACKEND (cbgw), cache_comp_str, e_cal_component_get_as_string (modified_comp));
312
347
                        g_free (cache_comp_str);
 
348
                        cache_comp_str = NULL;
313
349
                }
314
350
                e_cal_backend_cache_put_component (cache, modified_comp);
 
351
 
315
352
                g_object_unref (item);
316
353
                g_object_unref (modified_comp);
317
354
        }
318
355
        e_file_cache_thaw_changes (E_FILE_CACHE (cache));
319
356
 
 
357
        temp = icaltime_from_string (time_string);
 
358
        current_time = icaltime_as_timet_with_zone (temp, icaltimezone_get_utc_timezone ());
 
359
        tm = gmtime (&current_time);
 
360
 
 
361
        time_interval = (CACHE_REFRESH_INTERVAL / 60000);
 
362
        time_interval_string = g_getenv ("GETQM_TIME_INTERVAL");
 
363
        if (time_interval_string) {
 
364
                time_interval = g_ascii_strtod (time_interval_string, NULL);
 
365
        } 
 
366
        if (attempts) {
 
367
                tm->tm_min += (time_interval * g_ascii_strtod (attempts, NULL));
 
368
                e_cal_backend_cache_put_key_value (cache, key, NULL);
 
369
        } else {
 
370
                tm->tm_min += time_interval;
 
371
        }
 
372
        strftime (t_str, 100, "%Y-%m-%dT%H:%M:%SZ", tm);
 
373
        time_string = g_strdup (t_str);
 
374
 
 
375
        e_cal_backend_cache_put_server_utc_time (cache, time_string);
 
376
 
 
377
        g_free (time_string);
 
378
        time_string = NULL;
 
379
 
320
380
        if (item_list) {
321
 
                g_slist_free (item_list);
 
381
                g_list_free (item_list);
322
382
                item_list = NULL;
323
383
        }
324
384
        
325
 
        status = e_gw_connection_get_quick_messages (cnc, cbgw->priv->container_id, "iCalId", NULL, "All", "CalendarItem", NULL,  -1,  &item_list);
326
 
 
327
 
        if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
328
 
                status = e_gw_connection_get_quick_messages (cnc, cbgw->priv->container_id, "iCalId", NULL, "All", "CalendarItem", NULL,  -1,  &item_list);
329
 
 
330
 
        if (status != E_GW_CONNECTION_STATUS_OK) {
331
 
                if (status == E_GW_CONNECTION_STATUS_NO_RESPONSE) 
332
 
                        return TRUE;
333
 
 
334
 
                e_cal_backend_groupwise_notify_error_code (cbgw, status);
335
 
                return TRUE;
336
 
        }
337
 
 
 
385
        /* TODO currently the read cursors response does not give us the recurrencKey, uncomment
 
386
           this once the  response gives the recurrenceKey */
338
387
        /* handle deleted items here by going over the entire cache and
339
388
         * checking for deleted items.*/
340
 
        
 
389
        position = E_GW_CURSOR_POSITION_END;
 
390
        cursor = 0;
 
391
        status = e_gw_connection_create_cursor (cnc, cbgw->priv->container_id, "id iCalId recurrenceKey", NULL, &cursor);
 
392
 
 
393
        if (status != E_GW_CONNECTION_STATUS_OK) {
 
394
                if (status == E_GW_CONNECTION_STATUS_NO_RESPONSE) {
 
395
                        g_static_mutex_unlock (&connecting);
 
396
                        return TRUE;
 
397
                }
 
398
 
 
399
                e_cal_backend_groupwise_notify_error_code (cbgw, status);
 
400
                g_static_mutex_unlock (&connecting);
 
401
                return TRUE;
 
402
        }
 
403
 
341
404
        cache_keys = e_cal_backend_cache_get_keys (cache);
342
 
        for (l = item_list; l; l = g_slist_next (l)) {
343
 
                /* this works assuming rid is null*/
344
 
                cache_keys = g_slist_delete_link (cache_keys, 
345
 
                                g_slist_find_custom (cache_keys, l->data, (GCompareFunc) strcmp));
346
 
                g_free (l->data);
 
405
        
 
406
        done = FALSE;
 
407
        while (!done) {
 
408
                status = e_gw_connection_read_cal_ids (cnc, cbgw->priv->container_id, cursor, FALSE, CURSOR_ICALID_LIMIT, position, &item_list);
 
409
                if (status != E_GW_CONNECTION_STATUS_OK) {
 
410
                        if (status == E_GW_CONNECTION_STATUS_NO_RESPONSE) {
 
411
                                g_static_mutex_unlock (&connecting);
 
412
                                return TRUE;
 
413
                        }
 
414
                        e_cal_backend_groupwise_notify_error_code (cbgw, status);
 
415
                        g_static_mutex_unlock (&connecting);
 
416
                        return TRUE;
 
417
                }
 
418
                
 
419
                /* FIXME handle deleted items here by going over the entire cache and
 
420
                 * checking for deleted items.*/
 
421
#if 0
 
422
                for (l1 = item_list; l1; l1 = g_list_next (l1)) {
 
423
                        char *icalid;
 
424
                        icalid = (char *)(l1->data);
 
425
                        cache_keys = g_slist_delete_link (cache_keys, 
 
426
                                        g_slist_find_custom (cache_keys, icalid, (GCompareFunc) strcmp));
 
427
                        if (l1->data)
 
428
                                g_free (l1->data);
 
429
                }       
 
430
#endif
 
431
                if (!item_list  || g_list_length (item_list) == 0)
 
432
                        done = TRUE;
 
433
                else {
 
434
                        if (!total_list)
 
435
                                total_list = item_list;
 
436
                        else
 
437
                                total_list = g_list_concat (total_list, item_list);
 
438
                }
 
439
 
 
440
                item_list = NULL;
 
441
 
 
442
                position = E_GW_CURSOR_POSITION_CURRENT;
 
443
 
347
444
        }
348
 
 
 
445
        e_gw_connection_destroy_cursor (cnc, cbgw->priv->container_id, cursor);
349
446
        e_file_cache_freeze_changes (E_FILE_CACHE (cache));
 
447
 
 
448
#if 0
350
449
        for (l = cache_keys; l ; l = g_slist_next (l)) {
351
450
                /* assumes rid is null - which works for now */
352
451
                ECalComponent *comp = NULL;
 
452
                GSList *comp_list = NULL;
353
453
                ECalComponentVType vtype;
354
454
 
355
455
                comp = e_cal_backend_cache_get_component (cache, (const char *) l->data, NULL); 
356
 
                
 
456
 
357
457
                if (!comp)
358
458
                        continue;
359
459
 
362
462
                                (vtype == E_CAL_COMPONENT_TODO)) {
363
463
                        comp_str = e_cal_component_get_as_string (comp);
364
464
                        e_cal_backend_notify_object_removed (E_CAL_BACKEND (cbgw), 
365
 
                                                             (char *) l->data, comp_str, NULL);
 
465
                                        (char *) l->data, comp_str, NULL);
366
466
                        e_cal_backend_cache_remove_component (cache, (const char *) l->data, NULL);
367
467
                        g_free (comp_str);
368
468
                }
369
469
                g_object_unref (comp);
370
470
        }
 
471
#endif
 
472
 
 
473
        for (l = total_list; l != NULL; l = l->next) {
 
474
                EGwItemCalId *calid = (EGwItemCalId *)  l->data;
 
475
                GCompareFunc func = NULL;
 
476
                GSList *remove = NULL;
 
477
 
 
478
                if (calid->ical_id) 
 
479
                        func = (GCompareFunc) strcmp;
 
480
                else
 
481
                        func = (GCompareFunc) compare_prefix;
 
482
 
 
483
                if (!(remove = g_slist_find_custom (cache_keys, calid->ical_id ? calid->ical_id :
 
484
                                                calid->recur_key,  func))) {
 
485
                        g_ptr_array_add (uid_array, g_strdup (calid->item_id));
 
486
                        needs_to_get = TRUE;
 
487
                } else  {
 
488
                        cache_keys = g_slist_delete_link (cache_keys, remove);
 
489
                        continue;
 
490
                }
 
491
 
 
492
        }
 
493
 
 
494
        if (needs_to_get) {
 
495
                e_gw_connection_get_items_from_ids (priv->cnc,
 
496
                                priv->container_id, 
 
497
                                "attachments recipients message recipientStatus default peek",
 
498
                                uid_array, &item_list);
 
499
 
 
500
                for (l = item_list; l != NULL; l = l->next) {
 
501
                        ECalComponent *comp = NULL;
 
502
                        EGwItem *item = NULL;
 
503
                        char *temp = NULL;
 
504
 
 
505
                        item = (EGwItem *) l->data;
 
506
                        comp = e_gw_item_to_cal_component (item, cbgw); 
 
507
                        if (comp) {
 
508
                                e_cal_component_commit_sequence (comp);
 
509
                                sanitize_component (E_CAL_BACKEND_SYNC (cbgw), comp, (char *) e_gw_item_get_id (item));
 
510
                                e_cal_backend_cache_put_component (priv->cache, comp);
 
511
 
 
512
 
 
513
                                if (kind == icalcomponent_isa (e_cal_component_get_icalcomponent (comp))) {
 
514
                                        temp = e_cal_component_get_as_string (comp);
 
515
                                        e_cal_backend_notify_object_created (E_CAL_BACKEND (cbgw), temp);
 
516
                                        g_free (temp);
 
517
                                }
 
518
                                g_object_unref (comp);
 
519
                        }
 
520
 
 
521
                        g_object_unref (item);
 
522
                }
 
523
        }
 
524
 
371
525
        e_file_cache_thaw_changes (E_FILE_CACHE (cache));
372
526
 
 
527
        g_ptr_array_free (uid_array, TRUE);
 
528
        
373
529
        if (item_list) {
374
 
                g_slist_free (item_list);
 
530
                g_list_free (item_list);
375
531
                item_list = NULL;
376
532
        }
 
533
 
 
534
        if (total_list) {
 
535
                g_list_foreach (total_list, (GFunc) e_gw_item_free_cal_id, NULL);
 
536
                g_list_free (total_list);
 
537
        }
 
538
        
377
539
        if (cache_keys) {
378
540
                g_slist_free (cache_keys);
379
 
                item_list = NULL;
380
 
        }
381
 
                
382
 
        return TRUE;        
383
 
}
 
541
        }
 
542
        
 
543
        g_static_mutex_unlock (&connecting);
 
544
 
 
545
        return TRUE;        
 
546
}
 
547
 
 
548
static gboolean
 
549
get_deltas_timeout (gpointer cbgw)
 
550
{
 
551
        GThread *thread;
 
552
        GError *error = NULL;
 
553
 
 
554
        if (!cbgw)
 
555
                return FALSE;
 
556
 
 
557
        thread = g_thread_create ((GThreadFunc) get_deltas, cbgw, FALSE, &error);
 
558
        if (!thread) {
 
559
                g_warning (G_STRLOC ": %s", error->message);
 
560
                g_error_free (error);
 
561
        }
 
562
 
 
563
        return TRUE;
 
564
}
 
565
 
384
566
 
385
567
static char* 
386
568
form_uri (ESource *source)
468
650
 
469
651
                        /*  Set up deltas only if it is a Calendar backend */
470
652
                        if (kind == ICAL_VEVENT_COMPONENT)
471
 
                                priv->timeout_id = g_timeout_add (time_interval, (GSourceFunc) get_deltas, (gpointer) cbgw);
 
653
                                priv->timeout_id = g_timeout_add (time_interval, (GSourceFunc) get_deltas_timeout, (gpointer) cbgw);
472
654
                        priv->mode = CAL_MODE_REMOTE;
473
655
                        return GNOME_Evolution_Calendar_Success;
474
656
                }
495
677
                /* get the deltas from the cache */
496
678
                if (get_deltas (cbgw)) {
497
679
                        if (kind == ICAL_VEVENT_COMPONENT)
498
 
                                priv->timeout_id = g_timeout_add (time_interval, (GSourceFunc) get_deltas, (gpointer) cbgw);
 
680
                                priv->timeout_id = g_timeout_add (time_interval, (GSourceFunc) get_deltas_timeout, (gpointer) cbgw);
499
681
                        priv->mode = CAL_MODE_REMOTE;
500
682
                        return GNOME_Evolution_Calendar_Success;
501
683
                } else {
508
690
}
509
691
 
510
692
static ECalBackendSyncStatus
 
693
set_container_id_with_count (ECalBackendGroupwise *cbgw) 
 
694
{
 
695
        ECalBackendGroupwisePrivate *priv;
 
696
        GList *container_list = NULL, *l;
 
697
        EGwConnectionStatus status;
 
698
        icalcomponent_kind kind;
 
699
        ECalBackendSyncStatus res;
 
700
 
 
701
        priv = cbgw->priv;
 
702
 
 
703
        kind = e_cal_backend_get_kind (E_CAL_BACKEND (cbgw));
 
704
        
 
705
        switch (kind) {
 
706
        case ICAL_VEVENT_COMPONENT:
 
707
        case ICAL_VTODO_COMPONENT:
 
708
                e_source_set_name (e_cal_backend_get_source (E_CAL_BACKEND (cbgw)), _("Calendar"));
 
709
                break;
 
710
        default:
 
711
                priv->container_id = NULL;
 
712
                return GNOME_Evolution_Calendar_UnsupportedMethod;
 
713
        }
 
714
        
 
715
        status = e_gw_connection_get_container_list (priv->cnc, "folders", &container_list);
 
716
        
 
717
        if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
 
718
                status = e_gw_connection_get_container_list (priv->cnc, "folders", &container_list);
 
719
        
 
720
        if (status != E_GW_CONNECTION_STATUS_OK)
 
721
                return GNOME_Evolution_Calendar_OtherError;
 
722
 
 
723
        res =  GNOME_Evolution_Calendar_ObjectNotFound;
 
724
        for (l = container_list; l != NULL; l = l->next) {
 
725
                EGwContainer *container = E_GW_CONTAINER (l->data);
 
726
                const char *name = e_gw_container_get_name (container);
 
727
                
 
728
                if (name && strcmp (name, "Calendar") == 0) {
 
729
                        priv->container_id = g_strdup (e_gw_container_get_id (container));
 
730
                        priv->total_count = e_gw_container_get_total_count (container);
 
731
                        res = GNOME_Evolution_Calendar_Success;
 
732
                        break;
 
733
                }
 
734
        }
 
735
 
 
736
        e_gw_connection_free_container_list (container_list);
 
737
 
 
738
        return res;
 
739
}
 
740
        
 
741
static ECalBackendSyncStatus
511
742
connect_to_server (ECalBackendGroupwise *cbgw)
512
743
{
513
744
        char *real_uri;
515
746
        ESource *source;
516
747
        const char *use_ssl;
517
748
        char *http_uri;
 
749
        int permissions;
518
750
        GThread *thread;
519
751
        GError *error = NULL;
 
752
        char *parent_user = NULL;
 
753
        icalcomponent_kind kind;
 
754
        
520
755
        priv = cbgw->priv;
521
756
 
522
757
        source = e_cal_backend_get_source (E_CAL_BACKEND (cbgw));
524
759
        if (source)
525
760
                real_uri = form_uri (source);
526
761
        use_ssl = e_source_get_property (source, "use_ssl");
527
 
 
 
762
 
528
763
        if (!real_uri) {
529
764
                e_cal_backend_notify_error (E_CAL_BACKEND (cbgw), _("Invalid server URI"));
530
765
                return GNOME_Evolution_Calendar_NoSuchCal;
531
766
        } else {
 
767
                parent_user = (char *) e_source_get_property (source, "parent_id_name");
532
768
                /* create connection to server */
533
 
                priv->cnc = e_gw_connection_new (
534
 
                        real_uri,
535
 
                        priv->username,
536
 
                        priv->password);
537
 
 
538
 
                if (!E_IS_GW_CONNECTION(priv->cnc) && use_ssl && g_str_equal (use_ssl, "when-possible")) {
539
 
                        http_uri = g_strconcat ("http://", real_uri + 8, NULL);
540
 
                        priv->cnc = e_gw_connection_new (http_uri, priv->username, priv->password);
541
 
                        g_free (http_uri);
 
769
                if (parent_user) {
 
770
                        EGwConnection *cnc;
 
771
                        /* create connection to server */
 
772
                        cnc = e_gw_connection_new (real_uri, parent_user, priv->password);
 
773
                        if (!E_IS_GW_CONNECTION(cnc) && use_ssl && g_str_equal (use_ssl, "when-possible")) {
 
774
                                http_uri = g_strconcat ("http://", real_uri + 8, NULL);
 
775
                                cnc = e_gw_connection_new (http_uri, parent_user, priv->password);
 
776
                                g_free (http_uri);
 
777
                        }
 
778
 
 
779
                        if (!cnc) {
 
780
                                e_cal_backend_notify_error (E_CAL_BACKEND (cbgw), _("Authentication failed"));
 
781
                                return GNOME_Evolution_Calendar_AuthenticationFailed;
 
782
                        }
 
783
                                
 
784
                        priv->cnc = e_gw_connection_get_proxy_connection (cnc, parent_user, priv->password, priv->username, &permissions);
 
785
 
 
786
                        g_object_unref(cnc);
 
787
                
 
788
                        if (!priv->cnc) {
 
789
                                e_cal_backend_notify_error (E_CAL_BACKEND (cbgw), _("Authentication failed"));
 
790
                                return GNOME_Evolution_Calendar_AuthenticationFailed;
 
791
                        }
 
792
 
 
793
                        kind = e_cal_backend_get_kind (E_CAL_BACKEND (cbgw));
 
794
 
 
795
                        cbgw->priv->read_only = TRUE;
 
796
                
 
797
                        if (kind == ICAL_VEVENT_COMPONENT && (permissions & E_GW_PROXY_APPOINTMENT_WRITE) )
 
798
                                cbgw->priv->read_only = FALSE;
 
799
                        else if (kind == ICAL_VTODO_COMPONENT && (permissions & E_GW_PROXY_TASK_WRITE))
 
800
                                cbgw->priv->read_only = FALSE;
 
801
 
 
802
                } else {
 
803
 
 
804
                        priv->cnc = e_gw_connection_new (
 
805
                                        real_uri,
 
806
                                        priv->username,
 
807
                                        priv->password);
 
808
 
 
809
                        if (!E_IS_GW_CONNECTION(priv->cnc) && use_ssl && g_str_equal (use_ssl, "when-possible")) {
 
810
                                http_uri = g_strconcat ("http://", real_uri + 8, NULL);
 
811
                                priv->cnc = e_gw_connection_new (http_uri, priv->username, priv->password);
 
812
                                g_free (http_uri);
 
813
                        }
 
814
                        cbgw->priv->read_only = FALSE;
542
815
                }
543
816
                g_free (real_uri);
544
817
                        
545
 
                /* As of now we are assuming that logged in user has write rights to calender */
546
 
                /* we need to read actual rights from server when we implement proxy user access */
547
 
                cbgw->priv->read_only = FALSE;
548
 
 
549
 
                if (priv->cnc && priv->cache) {
 
818
                if (priv->cnc && priv->cache && priv->container_id) {
 
819
                        char *utc_str;
550
820
                        priv->mode = CAL_MODE_REMOTE;
551
821
                        if (priv->mode_changed && !priv->timeout_id && (e_cal_backend_get_kind (E_CAL_BACKEND (cbgw)) == ICAL_VEVENT_COMPONENT)) {
552
822
                                GThread *thread1;
560
830
                                        e_cal_backend_notify_error (E_CAL_BACKEND (cbgw), _("Could not create thread for getting deltas"));
561
831
                                        return GNOME_Evolution_Calendar_OtherError;
562
832
                                }
563
 
                                priv->timeout_id = g_timeout_add (CACHE_REFRESH_INTERVAL, (GSourceFunc) get_deltas, (gpointer) cbgw);
 
833
                                priv->timeout_id = g_timeout_add (CACHE_REFRESH_INTERVAL, (GSourceFunc) get_deltas_timeout, (gpointer)cbgw);
 
834
                        }
 
835
                        utc_str = (char *) e_gw_connection_get_server_time (priv->cnc);
 
836
                        e_cal_backend_cache_put_server_utc_time (priv->cache, utc_str);
564
837
 
565
 
                        }
566
 
        
567
838
                        return GNOME_Evolution_Calendar_Success;
568
839
                }
569
840
                priv->mode_changed = FALSE;
570
841
 
571
842
                if (E_IS_GW_CONNECTION (priv->cnc)) {
572
 
                        icalcomponent_kind kind;
573
 
 
 
843
                        ECalBackendSyncStatus status;
574
844
                        /* get the ID for the container */
575
845
                        if (priv->container_id)
576
846
                                g_free (priv->container_id);
577
847
                        
578
 
                        kind = e_cal_backend_get_kind (E_CAL_BACKEND (cbgw));
579
 
 
580
 
                        if (kind == ICAL_VEVENT_COMPONENT) {
581
 
                                priv->container_id = g_strdup (e_gw_connection_get_container_id (priv->cnc, "Calendar"));
582
 
                                e_source_set_name (e_cal_backend_get_source (E_CAL_BACKEND (cbgw)), _("Calendar"));
583
 
                        } else if (kind == ICAL_VTODO_COMPONENT) {
584
 
                                priv->container_id = g_strdup (e_gw_connection_get_container_id (priv->cnc, "Calendar"));
585
 
                                e_source_set_name (e_cal_backend_get_source (E_CAL_BACKEND (cbgw)), _("Calendar"));
586
 
                        } else
587
 
                                priv->container_id = NULL;
588
 
 
 
848
                        if ((status = set_container_id_with_count (cbgw)) != GNOME_Evolution_Calendar_Success) {
 
849
                                return status;
 
850
                        }
 
851
                
589
852
                        priv->cache = e_cal_backend_cache_new (e_cal_backend_get_uri (E_CAL_BACKEND (cbgw)));
590
853
                        if (!priv->cache) {
591
854
                                g_mutex_unlock (priv->mutex);
756
1019
static ECalBackendSyncStatus
757
1020
e_cal_backend_groupwise_get_static_capabilities (ECalBackendSync *backend, EDataCal *cal, char **capabilities)
758
1021
{
759
 
        *capabilities = g_strdup (CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS "," \
760
 
                                  CAL_STATIC_CAPABILITY_ONE_ALARM_ONLY "," \
761
 
                                  CAL_STATIC_CAPABILITY_REMOVE_ALARMS ","   \
762
 
                                  CAL_STATIC_CAPABILITY_NO_THISANDPRIOR "," \
763
 
                                  CAL_STATIC_CAPABILITY_NO_THISANDFUTURE "," \
764
 
                                  CAL_STATIC_CAPABILITY_NO_CONV_TO_ASSIGN_TASK "," \
765
 
                                  CAL_STATIC_CAPABILITY_NO_CONV_TO_RECUR "," \
766
 
                                  CAL_STATIC_CAPABILITY_REQ_SEND_OPTIONS "," \
 
1022
        *capabilities = g_strdup (CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS ","
 
1023
                                  CAL_STATIC_CAPABILITY_ONE_ALARM_ONLY ","
 
1024
                                  CAL_STATIC_CAPABILITY_REMOVE_ALARMS ","
 
1025
                                  CAL_STATIC_CAPABILITY_NO_THISANDPRIOR ","
 
1026
                                  CAL_STATIC_CAPABILITY_NO_THISANDFUTURE ","
 
1027
                                  CAL_STATIC_CAPABILITY_NO_CONV_TO_ASSIGN_TASK ","
 
1028
                                  CAL_STATIC_CAPABILITY_NO_CONV_TO_RECUR ","
 
1029
                                  CAL_STATIC_CAPABILITY_REQ_SEND_OPTIONS ","
 
1030
                                  CAL_STATIC_CAPABILITY_SAVE_SCHEDULES ","
 
1031
                                  CAL_STATIC_CAPABILITY_ORGANIZER_MUST_ACCEPT ","
 
1032
                                  CAL_STATIC_CAPABILITY_DELEGATE_SUPPORTED ","
 
1033
                                  CAL_STATIC_CAPABILITY_DELEGATE_TO_MANY ","
 
1034
                                  CAL_STATIC_CAPABILITY_NO_ORGANIZER ","
 
1035
                                  CAL_STATIC_CAPABILITY_RECURRENCES_NO_MASTER ","
 
1036
                                  CAL_STATIC_CAPABILITY_HAS_UNACCEPTED_MEETING ","
767
1037
                                  CAL_STATIC_CAPABILITY_SAVE_SCHEDULES);
768
1038
 
769
1039
        return GNOME_Evolution_Calendar_Success;
932
1202
                priv->read_only = FALSE;
933
1203
                e_cal_backend_notify_mode (backend, GNOME_Evolution_Calendar_CalListener_MODE_SET,
934
1204
                                                    GNOME_Evolution_Calendar_MODE_REMOTE);
 
1205
                e_cal_backend_notify_readonly (backend, priv->read_only);
935
1206
                if(e_cal_backend_groupwise_is_loaded (backend))
936
1207
                              e_cal_backend_notify_auth_required(backend);      
937
1208
                break;
940
1211
                /* FIXME: make sure we update the cache before closing the connection */
941
1212
                priv->mode = CAL_MODE_LOCAL;
942
1213
                in_offline (cbgw);
 
1214
                e_cal_backend_notify_readonly (backend, priv->read_only);
943
1215
                e_cal_backend_notify_mode (backend, GNOME_Evolution_Calendar_CalListener_MODE_SET,
944
1216
                                           GNOME_Evolution_Calendar_MODE_LOCAL);
945
1217
 
1095
1367
        return GNOME_Evolution_Calendar_Success;
1096
1368
}
1097
1369
 
 
1370
/* Gets the list of attachments */
 
1371
static ECalBackendSyncStatus
 
1372
e_cal_backend_groupwise_get_attachment_list (ECalBackendSync *backend, EDataCal *cal, const char *uid, const char *rid, GSList **list)
 
1373
{
 
1374
        /* TODO implement the function */
 
1375
        return GNOME_Evolution_Calendar_Success;
 
1376
}
 
1377
 
1098
1378
/* Get_objects_in_range handler for the groupwise backend */
1099
1379
static ECalBackendSyncStatus
1100
1380
e_cal_backend_groupwise_get_object_list (ECalBackendSync *backend, EDataCal *cal, const char *sexp, GList **objects)
1135
1415
                }
1136
1416
        }
1137
1417
 
 
1418
        g_object_unref (cbsexp);
1138
1419
        g_list_foreach (components, (GFunc) g_object_unref, NULL);
1139
1420
        g_list_free (components);
1140
1421
 
1211
1492
} ECalBackendGroupwiseComputeChangesData;
1212
1493
 
1213
1494
static void
1214
 
e_cal_backend_groupwise_compute_changes_foreach_key (const char *key, gpointer data)
 
1495
e_cal_backend_groupwise_compute_changes_foreach_key (const char *key, const char *value, gpointer data)
1215
1496
{
1216
1497
        ECalBackendGroupwiseComputeChangesData *be_data = data;
1217
1498
                
1437
1718
                        e_cal_backend_cache_put_component (priv->cache, comp);
1438
1719
                        *calobj = e_cal_component_get_as_string (comp);
1439
1720
                } else {
1440
 
                        
 
1721
                        EGwConnectionStatus status;     
1441
1722
                        GList *list = NULL, *tmp;
1442
1723
                        GPtrArray *uid_array = g_ptr_array_new ();
1443
1724
                        for (l = uid_list; l; l = g_slist_next (l)) {
1445
1726
                        }
1446
1727
                        
1447
1728
                        /* convert uid_list to GPtrArray and get the items in a list */
1448
 
                        e_gw_connection_get_items_from_ids (priv->cnc,
1449
 
                                        priv->container_id, "recipients message default",
 
1729
                        status = e_gw_connection_get_items_from_ids (priv->cnc,
 
1730
                                        priv->container_id, 
 
1731
                                        "attachments recipients message recipientStatus default peek",
1450
1732
                                        uid_array, &list);
1451
 
                        /* FIXME  check if list is null and status may have
1452
 
                         * failed. */
 
1733
 
 
1734
                        if (status != E_GW_CONNECTION_STATUS_OK || (list == NULL) || (g_list_length (list) == 0)) {
 
1735
                                g_ptr_array_free (uid_array, TRUE);
 
1736
                                return GNOME_Evolution_Calendar_OtherError;
 
1737
                        }
 
1738
                        
1453
1739
                        comp = g_object_ref ( (ECalComponent *) list->data );
1454
1740
                        /* convert items into components and add them to the cache */
1455
1741
                        for (i=0, tmp = list; tmp ; tmp = g_list_next (tmp), i++) {
1497
1783
        ECalComponent *comp, *cache_comp = NULL;
1498
1784
        EGwConnectionStatus status;
1499
1785
        EGwItem *item, *cache_item;
 
1786
        const char *uid = NULL;
1500
1787
 
1501
1788
        *old_object = NULL;
1502
1789
        cbgw = E_CAL_BACKEND_GROUPWISE (backend);
1517
1804
 
1518
1805
        comp = e_cal_component_new ();
1519
1806
        e_cal_component_set_icalcomponent (comp, icalcomp);
1520
 
        item = e_gw_item_new_from_cal_component (priv->container_id, cbgw, comp);
 
1807
        e_cal_component_get_uid (comp, &uid);
1521
1808
 
1522
1809
        /* check if the object exists */
1523
1810
        switch (priv->mode) {
1524
1811
        case CAL_MODE_ANY :
1525
1812
        case CAL_MODE_REMOTE :
1526
1813
                /* when online, send the item to the server */
1527
 
                cache_comp = e_cal_backend_cache_get_component (priv->cache, e_gw_item_get_icalid (item), NULL);
 
1814
                cache_comp = e_cal_backend_cache_get_component (priv->cache, uid, NULL);
1528
1815
                if (!cache_comp) {
1529
1816
                        g_message ("CRITICAL : Could not find the object in cache");
1530
1817
                        return GNOME_Evolution_Calendar_ObjectNotFound;
1531
1818
                }
1532
1819
 
 
1820
                if (e_cal_component_has_attendees (comp) && 
 
1821
                                e_cal_backend_groupwise_utils_check_delegate (comp, e_gw_connection_get_user_email (priv->cnc))) {
 
1822
                        const char *id = NULL, *recur_key = NULL;
 
1823
                        
 
1824
                        item = e_gw_item_new_for_delegate_from_cal (cbgw, comp);
 
1825
 
 
1826
                        if (mod == CALOBJ_MOD_ALL && e_cal_component_is_instance (comp)) {
 
1827
                                recur_key = uid;
 
1828
                        } else {
 
1829
                                id = e_gw_item_get_id (item);
 
1830
                        }
 
1831
 
 
1832
                        status = e_gw_connection_delegate_request (priv->cnc, item, id, NULL, NULL, recur_key); 
 
1833
                
 
1834
                        if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
 
1835
                                        status = e_gw_connection_delegate_request (priv->cnc, item, id, NULL, NULL, recur_key);
 
1836
                                
 
1837
                                if (status != E_GW_CONNECTION_STATUS_OK) {
 
1838
                                        g_object_unref (comp);
 
1839
                                        g_object_unref (cache_comp);
 
1840
                                        return GNOME_Evolution_Calendar_OtherError;
 
1841
                                }
 
1842
                        
 
1843
                        
 
1844
                        e_cal_backend_cache_put_component (priv->cache, comp);
 
1845
                        *new_object = e_cal_component_get_as_string (comp);
 
1846
                        break;
 
1847
                }
 
1848
 
 
1849
                item = e_gw_item_new_from_cal_component (priv->container_id, cbgw, comp);
1533
1850
                cache_item =  e_gw_item_new_from_cal_component (priv->container_id, cbgw, cache_comp);
1534
1851
                if ( e_gw_item_get_item_type (item) == E_GW_ITEM_TYPE_TASK) {
1535
1852
                        gboolean completed, cache_completed;
1552
1869
                                break;
1553
1870
                        }
1554
1871
                }
 
1872
                
1555
1873
                e_gw_item_set_changes (item, cache_item); 
1556
1874
 
1557
1875
                /* the second argument is redundant */
1582
1900
        return GNOME_Evolution_Calendar_Success;
1583
1901
}
1584
1902
 
 
1903
static const char *
 
1904
get_gw_item_id (icalcomponent *icalcomp) 
 
1905
{
 
1906
        icalproperty *icalprop; 
 
1907
 
 
1908
        /* search the component for the X-GWRECORDID property */
 
1909
        icalprop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY);
 
1910
        while (icalprop) {
 
1911
                const char *x_name, *x_val;
 
1912
 
 
1913
                x_name = icalproperty_get_x_name (icalprop);
 
1914
                x_val = icalproperty_get_x (icalprop);
 
1915
                if (!strcmp (x_name, "X-GWRECORDID")) {
 
1916
                        return x_val;
 
1917
                }
 
1918
 
 
1919
                icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY);
 
1920
        }
 
1921
        return NULL;
 
1922
}
 
1923
 
1585
1924
/* Remove_object handler for the file backend */
1586
1925
static ECalBackendSyncStatus
1587
1926
e_cal_backend_groupwise_remove_object (ECalBackendSync *backend, EDataCal *cal,
1602
1941
        if (priv->mode == CAL_MODE_REMOTE) {
1603
1942
                ECalBackendSyncStatus status;
1604
1943
                const char *id_to_remove = NULL;
1605
 
                icalproperty *icalprop;
1606
1944
                icalcomponent *icalcomp;
1607
1945
 
1608
 
                status = e_cal_backend_groupwise_get_object (backend, cal, uid, rid, &calobj);
1609
 
                if (status != GNOME_Evolution_Calendar_Success)
1610
 
                        return status;
1611
 
 
1612
 
                *old_object = strdup (calobj);
1613
 
 
1614
 
                icalcomp = icalparser_parse_string (calobj);
1615
 
                if (!icalcomp) {
1616
 
                        g_free (calobj);
1617
 
                        return GNOME_Evolution_Calendar_InvalidObject;
1618
 
                }
1619
 
 
1620
 
                /* search the component for the X-GWRECORDID property */
1621
 
                icalprop = icalcomponent_get_first_property (icalcomp, ICAL_X_PROPERTY);
1622
 
                while (icalprop) {
1623
 
                        const char *x_name, *x_val;
1624
 
 
1625
 
                        x_name = icalproperty_get_x_name (icalprop);
1626
 
                        x_val = icalproperty_get_x (icalprop);
1627
 
                        if (!strcmp (x_name, "X-GWRECORDID")) {
1628
 
                                id_to_remove = x_val;
1629
 
                                break;
1630
 
                        }
1631
 
 
1632
 
                        icalprop = icalcomponent_get_next_property (icalcomp, ICAL_X_PROPERTY);
1633
 
                }
1634
 
 
1635
 
                if (!id_to_remove) {
1636
 
                        /* use the iCalId to remove the object */
1637
 
                        id_to_remove = uid;
1638
 
                }
1639
 
 
1640
 
                /* remove the object */
1641
 
                status = e_gw_connection_remove_item (priv->cnc, priv->container_id, id_to_remove);
1642
 
 
1643
 
                if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
 
1946
                if (mod == CALOBJ_MOD_THIS) {
 
1947
 
 
1948
                        status = e_cal_backend_groupwise_get_object (backend, cal, uid, rid, &calobj);
 
1949
                        if (status != GNOME_Evolution_Calendar_Success)
 
1950
                                return status;
 
1951
 
 
1952
                        *old_object = strdup (calobj);
 
1953
 
 
1954
                        icalcomp = icalparser_parse_string (calobj);
 
1955
                        if (!icalcomp) {
 
1956
                                g_free (calobj);
 
1957
                                return GNOME_Evolution_Calendar_InvalidObject;
 
1958
                        }
 
1959
                
 
1960
                        id_to_remove = get_gw_item_id (icalcomp); 
 
1961
                        if (!id_to_remove) {
 
1962
                                /* use the iCalId to remove the object */
 
1963
                                id_to_remove = uid;
 
1964
                        }
 
1965
 
 
1966
                        /* remove the object */
1644
1967
                        status = e_gw_connection_remove_item (priv->cnc, priv->container_id, id_to_remove);
1645
1968
 
1646
 
                icalcomponent_free (icalcomp);
1647
 
                if (status == E_GW_CONNECTION_STATUS_OK) {
1648
 
                        /* remove the component from the cache */
1649
 
                        if (!e_cal_backend_cache_remove_component (priv->cache, uid, rid)) {
1650
 
                                g_free (calobj);
1651
 
                                return GNOME_Evolution_Calendar_ObjectNotFound;
1652
 
                        }
1653
 
                        *object = NULL;
1654
 
                        g_free (calobj);
1655
 
                        return GNOME_Evolution_Calendar_Success;
1656
 
                } else {
1657
 
                        g_free (calobj);
1658
 
                        return GNOME_Evolution_Calendar_OtherError;
1659
 
                }
 
1969
                        if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
 
1970
                                status = e_gw_connection_remove_item (priv->cnc, priv->container_id, id_to_remove);
 
1971
 
 
1972
                        icalcomponent_free (icalcomp);
 
1973
                        if (status == E_GW_CONNECTION_STATUS_OK) {
 
1974
                                /* remove the component from the cache */
 
1975
                                if (!e_cal_backend_cache_remove_component (priv->cache, uid, rid)) {
 
1976
                                        g_free (calobj);
 
1977
                                        return GNOME_Evolution_Calendar_ObjectNotFound;
 
1978
                                }
 
1979
                                *object = NULL;
 
1980
                                g_free (calobj);
 
1981
                                return GNOME_Evolution_Calendar_Success;
 
1982
                        } else {
 
1983
                                g_free (calobj);
 
1984
                                return GNOME_Evolution_Calendar_OtherError;
 
1985
                        }
 
1986
                } else if (mod == CALOBJ_MOD_ALL) {
 
1987
                        GSList *l, *comp_list = e_cal_backend_cache_get_components_by_uid (priv->cache, uid);
 
1988
 
 
1989
                        if (e_cal_component_has_attendees (E_CAL_COMPONENT (comp_list->data))) {
 
1990
                                /* get recurrence key and send it to
 
1991
                                 * e_gw_connection_remove_recurrence_item */
 
1992
                                
 
1993
                                id_to_remove = get_gw_item_id (e_cal_component_get_icalcomponent (comp_list->data)); 
 
1994
                                status = e_gw_connection_decline_request (priv->cnc, id_to_remove, NULL, uid);
 
1995
                                if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
 
1996
                                        status = e_gw_connection_decline_request (priv->cnc, id_to_remove, NULL, uid);
 
1997
                        } else {
 
1998
                                GList *item_ids = NULL; 
 
1999
                                for (l = comp_list; l; l = l->next) {
 
2000
                                        ECalComponent *comp = E_CAL_COMPONENT (l->data);
 
2001
 
 
2002
                                        id_to_remove = get_gw_item_id (e_cal_component_get_icalcomponent (comp)); 
 
2003
                                        item_ids = g_list_append (item_ids, (char *) id_to_remove);
 
2004
                                }
 
2005
                                status = e_gw_connection_remove_items (priv->cnc, priv->container_id, item_ids);
 
2006
                                
 
2007
                                if (status == E_GW_CONNECTION_STATUS_INVALID_CONNECTION)
 
2008
                                        status = e_gw_connection_remove_items (priv->cnc, priv->container_id, item_ids);
 
2009
                        }
 
2010
 
 
2011
                        if (status == E_GW_CONNECTION_STATUS_OK) {
 
2012
 
 
2013
                                for (l = comp_list; l; l = l->next) {
 
2014
                                        ECalComponent *comp = E_CAL_COMPONENT (l->data);
 
2015
                                        e_cal_backend_cache_remove_component (priv->cache, uid, 
 
2016
                                                        e_cal_component_get_recurid_as_string (comp));
 
2017
                                        e_cal_backend_notify_object_removed (E_CAL_BACKEND (cbgw), 
 
2018
                                                             uid, e_cal_component_get_as_string (comp), NULL);
 
2019
                                        g_object_unref (comp);
 
2020
                                
 
2021
                                }
 
2022
                                /* Setting NULL would trigger another signal.
 
2023
                                 * We do not set the *object to NULL  */
 
2024
                                g_slist_free (comp_list);
 
2025
                                return GNOME_Evolution_Calendar_Success;
 
2026
                        } else {
 
2027
                                return GNOME_Evolution_Calendar_OtherError;
 
2028
                        }
 
2029
                } else
 
2030
                        return GNOME_Evolution_Calendar_UnsupportedMethod;
1660
2031
        } else if (priv->mode == CAL_MODE_LOCAL) {
1661
2032
                in_offline (cbgw);
1662
2033
                return GNOME_Evolution_Calendar_RepositoryOffline;
1663
 
        }
1664
 
 
1665
 
        /* remove the component from the cache */
1666
 
        if (!e_cal_backend_cache_remove_component (priv->cache, uid, rid)) {
1667
 
                g_free (calobj);
1668
 
                return GNOME_Evolution_Calendar_ObjectNotFound;
1669
 
        }
1670
 
 
1671
 
        g_free (calobj);
1672
 
        return GNOME_Evolution_Calendar_Success;
 
2034
        } else
 
2035
                return GNOME_Evolution_Calendar_CalListener_MODE_NOT_SUPPORTED;
 
2036
        
1673
2037
}
1674
2038
 
1675
2039
static void
1785
2149
                                e_cal_backend_notify_object_removed (E_CAL_BACKEND (cbgw), uid, e_cal_component_get_as_string (comp), NULL);
1786
2150
                }
1787
2151
                else {
1788
 
                        char *cache_comp = NULL, *temp, *new_comp = NULL;
 
2152
                        char *cache_comp = NULL, *uid, *new_comp = NULL;
1789
2153
                        ECalComponent *cache_component;
1790
2154
                        
1791
 
                        e_cal_component_commit_sequence (modif_comp);
1792
 
                        e_cal_component_get_uid (modif_comp, (const char **) &temp);    
1793
 
                        cache_component = e_cal_backend_cache_get_component (priv->cache, temp, NULL);
 
2155
                        if (!modif_comp)
 
2156
                                modif_comp = g_object_ref (comp);
 
2157
                        else
 
2158
                                e_cal_component_commit_sequence (modif_comp);
 
2159
 
 
2160
                        e_cal_component_get_uid (modif_comp, (const char **) &uid);     
 
2161
                        cache_component = e_cal_backend_cache_get_component (priv->cache, uid, NULL);
1794
2162
                        
1795
2163
                        if (cache_component) {
1796
2164
                                e_cal_component_commit_sequence (cache_component);
1798
2166
                        }
1799
2167
 
1800
2168
                        e_cal_backend_cache_put_component (priv->cache, modif_comp);    
1801
 
                        e_cal_component_commit_sequence (modif_comp);
1802
2169
                        new_comp = e_cal_component_get_as_string (modif_comp);
1803
2170
 
1804
2171
                        if (cache_comp)
1808
2175
                                
1809
2176
                        g_free (cache_comp);
1810
2177
                        g_free (new_comp);
1811
 
                        g_free (temp);
 
2178
                        g_object_unref (modif_comp);
1812
2179
                }
1813
2180
                g_object_unref (comp);  
1814
2181
                return GNOME_Evolution_Calendar_Success;
2024
2391
        sync_class->get_default_object_sync = e_cal_backend_groupwise_get_default_object;
2025
2392
        sync_class->get_object_sync = e_cal_backend_groupwise_get_object;
2026
2393
        sync_class->get_object_list_sync = e_cal_backend_groupwise_get_object_list;
 
2394
        sync_class->get_attachment_list_sync = e_cal_backend_groupwise_get_attachment_list;
2027
2395
        sync_class->get_timezone_sync = e_cal_backend_groupwise_get_timezone;
2028
2396
        sync_class->add_timezone_sync = e_cal_backend_groupwise_add_timezone;
2029
2397
        sync_class->set_default_timezone_sync = e_cal_backend_groupwise_set_default_timezone;