/** * get_uuid_from_component: * @source: an {@link ESource} * @component: an {@link ECalComponent} * * Obtains the uuid from a component in the form * "source_uid:event_uid:event_rid" or "source:uid:event_uid" if the * component doesn't hold a recurrence event * * Returns: (Transfer full) a new allocated string with the description **/ gchar* get_uuid_from_component (ESource *source, ECalComponent *component) { gchar *uuid; ECalComponentId *id; id = e_cal_component_get_id (component); if (id->rid != NULL) { uuid = g_strdup_printf ("%s:%s:%s", e_source_get_uid (source), id->uid, id->rid); } else { uuid = g_strdup_printf ("%s:%s", e_source_get_uid (source), id->uid); } e_cal_component_free_id (id); return uuid; }
/** Wrapper for e_cal_backend_cache_put_component(). * * Keeps track of cache state of the component by using * e_cal_component_set_cache_state(). If component already existed in cache and * did not have cache state E_CAL_COMPONENT_CACHE_STATE_CREATED, its cache state will * be set to E_CAL_COMPONENT_CACHE_STATE_MODIFIED, in all other cases it will be * set to will be set to E_CAL_COMPONENT_CACHE_STATE_CREATED. * * @param cb 3E calendar backend. * @param cache Calendar backend cache object. * @param comp ECalComponent object. * * @return TRUE if successfully stored. */ gboolean e_cal_backend_3e_cache_put_component(ECalBackend3e *cb, ECalBackendCache *cache, ECalComponent *comp) { ECalComponentId *id; ECalComponentCacheState cache_state = E_CAL_COMPONENT_CACHE_STATE_CREATED; gboolean retval; id = e_cal_component_get_id(comp); if (id) { g_static_rw_lock_writer_lock(&cb->priv->cache_lock); ECalComponent *existing = e_cal_backend_cache_get_component(cache, id->uid, id->rid); if (existing) { if (e_cal_component_get_cache_state(existing) != E_CAL_COMPONENT_CACHE_STATE_CREATED) { cache_state = E_CAL_COMPONENT_CACHE_STATE_MODIFIED; } g_object_unref(existing); } e_cal_component_set_cache_state(comp, cache_state); retval = e_cal_backend_cache_put_component(cache, comp); g_static_rw_lock_writer_unlock(&cb->priv->cache_lock); e_cal_component_free_id(id); return retval; } return FALSE; }
static void empty_cache (ECalBackendHttp *cbhttp) { ECalBackendHttpPrivate *priv; GSList *comps, *l; priv = cbhttp->priv; if (!priv->store) return; comps = e_cal_backend_store_get_components (priv->store); for (l = comps; l != NULL; l = g_slist_next (l)) { ECalComponentId *id; ECalComponent *comp = l->data; id = e_cal_component_get_id (comp); e_cal_backend_notify_component_removed ((ECalBackend *) cbhttp, id, comp, NULL); e_cal_component_free_id (id); g_object_unref (comp); } g_slist_free (comps); e_cal_backend_store_put_key_value (priv->store, "ETag", NULL); e_cal_backend_store_clean (priv->store); }
/** Check if component's ID matches given ID. * * @param comp ECalComponent object. * @param id ECalComponentId object. * * @return TRUE if ID (both UID and RID) matches. */ gboolean e_cal_component_match_id(ECalComponent *comp, ECalComponentId *id) { ECalComponentId *comp_id = e_cal_component_get_id(comp); gboolean retval = e_cal_component_id_compare(comp_id, id); e_cal_component_free_id(comp_id); return retval; }
static gboolean notify_and_remove_from_cache (gpointer key, gpointer value, gpointer user_data) { const gchar *calobj = value; ECalBackendHttp *cbhttp = E_CAL_BACKEND_HTTP (user_data); ECalComponent *comp = e_cal_component_new_from_string (calobj); ECalComponentId *id = e_cal_component_get_id (comp); if (id) { e_cal_backend_store_remove_component (cbhttp->priv->store, id->uid, id->rid); e_cal_backend_notify_component_removed (E_CAL_BACKEND (cbhttp), id, comp, NULL); e_cal_component_free_id (id); } g_object_unref (comp); return TRUE; }
static void notify_add (EDataCalView *view, gchar *obj) { EDataCalViewPrivate *priv = view->priv; ECalComponent *comp; send_pending_changes (view); send_pending_removes (view); if (priv->adds->len == THRESHOLD_ITEMS) { send_pending_adds (view); } g_array_append_val (priv->adds, obj); comp = e_cal_component_new_from_string (obj); g_hash_table_insert (priv->ids, e_cal_component_get_id (comp), GUINT_TO_POINTER (1)); g_object_unref (comp); ensure_pending_flush_timeout (view); }
/** Sync changes from the server to the cache. * * @param cb 3E calendar backend. * * @return TRUE on success. * * @todo Handle UID/RID. * @todo Better server error handling. * @todo Conflict resolution. */ gboolean e_cal_backend_3e_sync_server_to_cache(ECalBackend3e *cb) { GError *local_err = NULL; gboolean update_sync = TRUE; icalcomponent *ical; icalcomponent *icomp; char filter[128]; struct tm tm; time_t stamp = MAX(e_cal_backend_3e_get_sync_timestamp(cb) - 60 * 60 * 24, 0); /*XXX: always add 1 day padding to prevent timezone problems */ /* prepare query filter string */ gmtime_r(&stamp, &tm); strftime(filter, sizeof(filter), "modified_since('%F %T')", &tm); ical = get_server_objects(cb, filter); if (ical == NULL) { return FALSE; } for (icomp = icalcomponent_get_first_component(ical, ICAL_ANY_COMPONENT); icomp; icomp = icalcomponent_get_next_component(ical, ICAL_ANY_COMPONENT)) { icalcomponent_kind kind = icalcomponent_isa(icomp); icalcomponent_set_cache_state(icomp, E_CAL_COMPONENT_CACHE_STATE_NONE); if (kind == ICAL_VEVENT_COMPONENT) { ECalComponent *comp; const char *uid = icalcomponent_get_uid(icomp); gboolean server_deleted = icalcomponent_3e_status_is_deleted(icomp); ECalComponentCacheState comp_state = E_CAL_COMPONENT_CACHE_STATE_NONE; g_static_rw_lock_reader_lock(&cb->priv->cache_lock); comp = e_cal_backend_cache_get_component(cb->priv->cache, uid, NULL); g_static_rw_lock_reader_unlock(&cb->priv->cache_lock); if (comp) { comp_state = e_cal_component_get_cache_state(comp); } if (server_deleted) { /* deleted by the server */ if (comp && e_cal_component_get_cache_state(comp) != E_CAL_COMPONENT_CACHE_STATE_CREATED && e_cal_component_get_cache_state(comp) != E_CAL_COMPONENT_CACHE_STATE_MODIFIED) { char *object = e_cal_component_get_as_string(comp); ECalComponentId *id = e_cal_component_get_id(comp); g_static_rw_lock_writer_lock(&cb->priv->cache_lock); e_cal_backend_cache_remove_component(cb->priv->cache, uid, NULL); g_static_rw_lock_writer_unlock(&cb->priv->cache_lock); e_cal_backend_notify_object_removed(E_CAL_BACKEND(cb), id, object, NULL); e_cal_component_free_id(id); g_free(object); } } else { char *old_object = NULL; char *object; ECalComponent *new_comp = e_cal_component_new(); e_cal_component_set_icalcomponent(new_comp, icalcomponent_new_clone(icomp)); e_cal_component_set_cache_state(new_comp, E_CAL_COMPONENT_CACHE_STATE_NONE); e_cal_backend_3e_convert_attachment_uris_to_local(cb, new_comp); if (comp) { old_object = e_cal_component_get_as_string(comp); } object = e_cal_component_get_as_string(new_comp); if (old_object == NULL) { if (e_cal_backend_3e_download_attachments(cb, new_comp, &local_err)) { /* not in cache yet */ g_static_rw_lock_writer_lock(&cb->priv->cache_lock); e_cal_backend_cache_put_component(cb->priv->cache, new_comp); g_static_rw_lock_writer_unlock(&cb->priv->cache_lock); e_cal_backend_notify_object_created(E_CAL_BACKEND(cb), object); } else { e_cal_backend_notify_gerror_error(E_CAL_BACKEND(cb), "Can't download attachment.", local_err); g_clear_error(&local_err); update_sync = FALSE; } } else if (strcmp(old_object, object)) { /* what is in cache and what is on server differs */ if (comp_state != E_CAL_COMPONENT_CACHE_STATE_NONE) { /* modified in cache, don't do anything */ } else { if (e_cal_backend_3e_download_attachments(cb, new_comp, &local_err)) { /* sync with server */ g_static_rw_lock_writer_lock(&cb->priv->cache_lock); e_cal_backend_cache_put_component(cb->priv->cache, new_comp); g_static_rw_lock_writer_unlock(&cb->priv->cache_lock); e_cal_backend_notify_object_modified(E_CAL_BACKEND(cb), old_object, object); } else { e_cal_backend_notify_gerror_error(E_CAL_BACKEND(cb), "Can't download attachment.", local_err); g_clear_error(&local_err); update_sync = FALSE; } } } g_free(old_object); g_free(object); g_object_unref(new_comp); } if (comp) { g_object_unref(comp); } } else if (kind == ICAL_VTIMEZONE_COMPONENT) { const char *tzid = icalcomponent_get_tzid(icomp); /* import non-existing timezones from the server */ if (!e_cal_backend_cache_get_timezone(cb->priv->cache, tzid)) { icaltimezone *zone = icaltimezone_new(); icalcomponent *zone_comp = icalcomponent_new_clone(icomp); if (icaltimezone_set_component(zone, zone_comp)) { g_static_rw_lock_writer_lock(&cb->priv->cache_lock); e_cal_backend_cache_put_timezone(cb->priv->cache, zone); g_static_rw_lock_writer_unlock(&cb->priv->cache_lock); } else { icalcomponent_free(zone_comp); } icaltimezone_free(zone, 1); } } else { g_warning("Unsupported component kind (%d) found on the 3e server.", kind); } } if (update_sync) { e_cal_backend_3e_set_sync_timestamp(cb, time(NULL)); } icalcomponent_free(ical); return TRUE; }
/** Sync cache changes to the server and unmark them. * * @param cb 3E calendar backend. * * @return TRUE on success. * * @todo Conflict resolution. */ gboolean e_cal_backend_3e_sync_cache_to_server(ECalBackend3e *cb) { GError *local_err = NULL; GList *components, *iter; if (!e_cal_backend_3e_open_connection(cb, &local_err)) { g_warning("Sync failed. Can't open connection to the 3e server. (%s)", local_err ? local_err->message : "Unknown error"); g_clear_error(&local_err); return FALSE; } sync_timezones_to_server(cb); g_static_rw_lock_reader_lock(&cb->priv->cache_lock); components = e_cal_backend_cache_get_components(cb->priv->cache); g_static_rw_lock_reader_unlock(&cb->priv->cache_lock); for (iter = components; iter && !e_cal_backend_3e_sync_should_stop(cb); iter = iter->next) { ECalComponent *comp = E_CAL_COMPONENT(iter->data); ECalComponent *remote_comp; ECalComponentId *id = e_cal_component_get_id(comp); ECalComponentCacheState state = e_cal_component_get_cache_state(comp); /* remove client properties before sending component to the server */ e_cal_component_set_x_property(comp, "X-EVOLUTION-STATUS", NULL); e_cal_component_set_cache_state(comp, E_CAL_COMPONENT_CACHE_STATE_NONE); e_cal_component_set_x_property(comp, "X-3E-DELETED", NULL); remote_comp = e_cal_component_clone(comp); gboolean attachments_converted = e_cal_backend_3e_convert_attachment_uris_to_remote(cb, remote_comp); char *remote_object = e_cal_component_get_as_string(remote_comp); char *object = e_cal_component_get_as_string(comp); if (!attachments_converted) { goto next; } if (state == E_CAL_COMPONENT_CACHE_STATE_CREATED || state == E_CAL_COMPONENT_CACHE_STATE_MODIFIED) { if (!e_cal_backend_3e_upload_attachments(cb, remote_comp, &local_err)) { e_cal_backend_notify_gerror_error(E_CAL_BACKEND(cb), "3e attachemnts sync failure", local_err); g_clear_error(&local_err); goto next; } } switch (state) { case E_CAL_COMPONENT_CACHE_STATE_CREATED: { ESClient_addObject(cb->priv->conn, cb->priv->calspec, remote_object, &local_err); if (local_err) { e_cal_backend_notify_gerror_error(E_CAL_BACKEND(cb), "3e sync failure", local_err); g_clear_error(&local_err); break; } char *new_object = e_cal_component_get_as_string(comp); e_cal_backend_notify_object_modified(E_CAL_BACKEND(cb), object, new_object); g_free(new_object); g_static_rw_lock_writer_lock(&cb->priv->cache_lock); e_cal_backend_cache_put_component(cb->priv->cache, comp); g_static_rw_lock_writer_unlock(&cb->priv->cache_lock); break; } case E_CAL_COMPONENT_CACHE_STATE_MODIFIED: { ESClient_updateObject(cb->priv->conn, cb->priv->calspec, remote_object, &local_err); if (local_err) { e_cal_backend_notify_gerror_error(E_CAL_BACKEND(cb), "3e sync failure", local_err); g_clear_error(&local_err); break; } char *new_object = e_cal_component_get_as_string(comp); e_cal_backend_notify_object_modified(E_CAL_BACKEND(cb), object, new_object); g_free(new_object); g_static_rw_lock_writer_lock(&cb->priv->cache_lock); e_cal_backend_cache_put_component(cb->priv->cache, comp); g_static_rw_lock_writer_unlock(&cb->priv->cache_lock); break; } case E_CAL_COMPONENT_CACHE_STATE_REMOVED: { char *oid = id->rid ? g_strdup_printf("%s@%s", id->uid, id->rid) : g_strdup(id->uid); ESClient_deleteObject(cb->priv->conn, cb->priv->calspec, oid, &local_err); g_free(oid); if (local_err) { // ignore the error if component doesn't exist anymore if (local_err->code == ES_XMLRPC_ERROR_UNKNOWN_COMPONENT) { g_clear_error(&local_err); local_err = NULL; } else { e_cal_backend_notify_gerror_error(E_CAL_BACKEND(cb), "3e sync failure", local_err); g_clear_error(&local_err); break; } } g_static_rw_lock_writer_lock(&cb->priv->cache_lock); e_cal_backend_cache_remove_component(cb->priv->cache, id->uid, id->rid); g_static_rw_lock_writer_unlock(&cb->priv->cache_lock); break; } case E_CAL_COMPONENT_CACHE_STATE_NONE: default: break; } next: g_object_unref(comp); g_object_unref(remote_comp); e_cal_component_free_id(id); g_free(object); g_free(remote_object); } g_list_free(components); e_cal_backend_3e_close_connection(cb); return TRUE; }
static CompEditor * get_component_editor (EShell *shell, ECalClient *client, ECalComponent *comp, gboolean is_new, GError **error) { ECalComponentId *id; CompEditorFlags flags = 0; CompEditor *editor = NULL; ESourceRegistry *registry; g_return_val_if_fail (E_IS_SHELL (shell), NULL); g_return_val_if_fail (E_IS_CAL_CLIENT (client), NULL); g_return_val_if_fail (E_IS_CAL_COMPONENT (comp), NULL); registry = e_shell_get_registry (shell); id = e_cal_component_get_id (comp); g_return_val_if_fail (id != NULL, NULL); g_return_val_if_fail (id->uid != NULL, NULL); if (is_new) { flags |= COMP_EDITOR_NEW_ITEM; } else { editor = comp_editor_find_instance (id->uid); } if (!editor) { if (itip_organizer_is_user (registry, comp, client)) flags |= COMP_EDITOR_USER_ORG; switch (e_cal_component_get_vtype (comp)) { case E_CAL_COMPONENT_EVENT: if (e_cal_component_has_attendees (comp)) flags |= COMP_EDITOR_MEETING; editor = event_editor_new (client, shell, flags); if (flags & COMP_EDITOR_MEETING) event_editor_show_meeting (EVENT_EDITOR (editor)); break; case E_CAL_COMPONENT_TODO: if (e_cal_component_has_attendees (comp)) flags |= COMP_EDITOR_IS_ASSIGNED; editor = task_editor_new (client, shell, flags); if (flags & COMP_EDITOR_IS_ASSIGNED) task_editor_show_assignment (TASK_EDITOR (editor)); break; case E_CAL_COMPONENT_JOURNAL: if (e_cal_component_has_organizer (comp)) flags |= COMP_EDITOR_IS_SHARED; editor = memo_editor_new (client, shell, flags); break; default: g_warn_if_reached (); break; } if (editor) { comp_editor_edit_comp (editor, comp); /* request save for new events */ comp_editor_set_changed (editor, is_new); } } e_cal_component_free_id (id); return editor; }