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); }
static void cal_backend_create_object (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *calobj) { GError *error = NULL; gchar *uid = NULL; ECalComponent *new_component = NULL; e_cal_backend_sync_create_object (E_CAL_BACKEND_SYNC (backend), cal, cancellable, calobj, &uid, &new_component, &error); if (!new_component) new_component = e_cal_component_new_from_string (calobj); e_data_cal_respond_create_object (cal, opid, error, uid, new_component); g_free (uid); if (new_component) g_object_unref (new_component); }
static void cal_backend_modify_object (ECalBackend *backend, EDataCal *cal, guint32 opid, GCancellable *cancellable, const gchar *calobj, CalObjModType mod) { GError *error = NULL; ECalComponent *old_component = NULL, *new_component = NULL; e_cal_backend_sync_modify_object (E_CAL_BACKEND_SYNC (backend), cal, cancellable, calobj, mod, &old_component, &new_component, &error); if (!old_component) old_component = e_cal_component_new_from_string (calobj); e_data_cal_respond_modify_object (cal, opid, error, old_component, new_component); if (old_component) g_object_unref (old_component); if (new_component) g_object_unref (new_component); }
static void test_time_zones_sync (gconstpointer user_data) { gboolean retval = FALSE; gint i; GError *error = NULL; UhmServer *local_server; EwsTestData *etd = (gpointer) user_data; EwsCalendarConvertData convert_data; EwsFolderId *calendar_fid = NULL; gboolean includes_last_folder = FALSE; gchar *old_sync_state = NULL; gchar **tokens; GSList *zone_location_errors = NULL; local_server = ews_test_get_mock_server (); ews_test_server_set_trace_directory (local_server, etd->version, "calendar/timezones"); ews_test_server_start_trace (local_server, etd, "get_server_time_zones_sync", &error); if (error != NULL) { g_printerr ("\n%s\n", error->message); goto exit; } while (!includes_last_folder) { GSList *folders_created = NULL; GSList *folders_updated = NULL; GSList *folders_deleted = NULL; GSList *l; gchar *new_sync_state = NULL; gboolean found = FALSE; old_sync_state = new_sync_state; e_ews_connection_sync_folder_hierarchy_sync ( etd->connection, EWS_PRIORITY_MEDIUM, old_sync_state, &new_sync_state, &includes_last_folder, &folders_created, &folders_updated, &folders_deleted, NULL, &error); if (error != NULL) { g_free (old_sync_state); g_printerr ("\n%s\n", error->message); goto exit; } for (l = folders_created; l != NULL; l = l->next) { EEwsFolder *folder = l->data; if (e_ews_folder_get_folder_type (folder) == E_EWS_FOLDER_TYPE_CALENDAR) { const EwsFolderId *fid; fid = e_ews_folder_get_id (folder); calendar_fid = g_new0 (EwsFolderId, 1); calendar_fid->id = g_strdup (fid->id); calendar_fid->change_key = g_strdup (fid->change_key); found = TRUE; break; } } g_slist_free_full (folders_created, g_object_unref); g_slist_free_full (folders_updated, g_object_unref); g_slist_free_full (folders_deleted, g_free); g_free (old_sync_state); old_sync_state = NULL; if (found) { g_free (new_sync_state); break; } } if (!calendar_fid) { g_printerr ("No calendar folder found\n"); goto exit; } convert_data.connection = etd->connection; convert_data.default_zone = icaltimezone_get_utc_timezone (); tokens = g_strsplit (str_comp, "ICAL_TIMEZONE", 0); for (i = 0; i < builtin_timezones->num_elements; i++) { GSList *ll; GSList *ids = NULL; icaltimezone *zone; ECalComponent *comp; const gchar *zone_location; gchar *str; zone = icalarray_element_at (builtin_timezones, i); zone_location = icaltimezone_get_location (zone); if (is_a_known_unknown_timezone (zone_location)) continue; str = g_strdup_printf ("%s%s%s%s%s", tokens[0], zone_location, tokens[1], zone_location, tokens[2]); comp = e_cal_component_new_from_string (str); g_free (str); convert_data.icalcomp = e_cal_component_get_icalcomponent (comp); e_ews_connection_create_items_sync ( etd->connection, EWS_PRIORITY_MEDIUM, "SaveOnly", "SendToNone", calendar_fid, convert_calcomp_to_xml, &convert_data, &ids, NULL, &error); g_object_unref (comp); if (error != NULL) { g_printerr ("\n%s\n", error->message); g_clear_error (&error); zone_location_errors = g_slist_append (zone_location_errors, g_strdup (zone_location)); continue; } for (ll = ids; ll != NULL; ll = ll->next) { EEwsItem *item = ll->data; if (e_ews_item_get_item_type (item) == E_EWS_ITEM_TYPE_ERROR) { const GError *item_error = e_ews_item_get_error (item); g_printerr ("\n%s\n", item_error->message); g_clear_error (&error); zone_location_errors = g_slist_append (zone_location_errors, g_strdup (zone_location)); continue; } } g_slist_free_full (ids, g_object_unref); } retval = zone_location_errors == NULL; exit: if (zone_location_errors != NULL) { GSList *l; g_printerr ("Errors found in: \n"); for (l = zone_location_errors; l != NULL; l = l->next) g_printerr (" - %s\n", (gchar *) l->data); g_slist_free_full (zone_location_errors, g_free); } uhm_server_end_trace (local_server); g_clear_error (&error); g_assert (retval == TRUE); }
static gboolean cal_backend_http_load (ECalBackendHttp *backend, const gchar *uri, gchar **out_certificate_pem, GTlsCertificateFlags *out_certificate_errors, GCancellable *cancellable, GError **error) { ECalBackendHttpPrivate *priv = backend->priv; ETimezoneCache *timezone_cache; SoupMessage *soup_message; SoupSession *soup_session; icalcomponent *icalcomp, *subcomp; icalcomponent_kind kind; const gchar *newuri; SoupURI *uri_parsed; GHashTable *old_cache; GSList *comps_in_cache; ESource *source; guint status_code; gulong cancel_id = 0; struct { SoupSession *soup_session; SoupMessage *soup_message; } cancel_data; timezone_cache = E_TIMEZONE_CACHE (backend); soup_session = backend->priv->soup_session; soup_message = cal_backend_http_new_message (backend, uri); if (soup_message == NULL) { g_set_error ( error, SOUP_HTTP_ERROR, SOUP_STATUS_MALFORMED, _("Malformed URI: %s"), uri); return FALSE; } if (G_IS_CANCELLABLE (cancellable)) { cancel_data.soup_session = soup_session; cancel_data.soup_message = soup_message; cancel_id = g_cancellable_connect ( cancellable, G_CALLBACK (cal_backend_http_cancelled), &cancel_data, (GDestroyNotify) NULL); } source = e_backend_get_source (E_BACKEND (backend)); e_soup_ssl_trust_connect (soup_message, source); e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTING); status_code = soup_session_send_message (soup_session, soup_message); if (G_IS_CANCELLABLE (cancellable)) g_cancellable_disconnect (cancellable, cancel_id); if (status_code == SOUP_STATUS_NOT_MODIFIED) { e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTED); /* attempts with ETag can result in 304 status code */ g_object_unref (soup_message); priv->opened = TRUE; return TRUE; } /* Handle redirection ourselves */ if (SOUP_STATUS_IS_REDIRECTION (status_code)) { gboolean success; newuri = soup_message_headers_get_list ( soup_message->response_headers, "Location"); d (g_message ("Redirected from %s to %s\n", async_context->uri, newuri)); if (newuri != NULL) { gchar *redirected_uri; if (newuri[0]=='/') { g_warning ("Hey! Relative URI returned! Working around...\n"); uri_parsed = soup_uri_new (uri); soup_uri_set_path (uri_parsed, newuri); soup_uri_set_query (uri_parsed, NULL); /* g_free (newuri); */ newuri = soup_uri_to_string (uri_parsed, FALSE); g_message ("Translated URI: %s\n", newuri); soup_uri_free (uri_parsed); } redirected_uri = webcal_to_http_method (newuri, FALSE); success = cal_backend_http_load ( backend, redirected_uri, out_certificate_pem, out_certificate_errors, cancellable, error); g_free (redirected_uri); } else { g_set_error ( error, SOUP_HTTP_ERROR, SOUP_STATUS_BAD_REQUEST, _("Redirected to Invalid URI")); success = FALSE; } if (success) { e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTED); } else { e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED); } g_object_unref (soup_message); return success; } /* check status code */ if (!SOUP_STATUS_IS_SUCCESSFUL (status_code)) { /* because evolution knows only G_IO_ERROR_CANCELLED */ if (status_code == SOUP_STATUS_CANCELLED) g_set_error ( error, G_IO_ERROR, G_IO_ERROR_CANCELLED, "%s", soup_message->reason_phrase); else g_set_error ( error, SOUP_HTTP_ERROR, status_code, "%s", soup_message->reason_phrase); if (status_code == SOUP_STATUS_SSL_FAILED) { e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_SSL_FAILED); cal_backend_http_extract_ssl_failed_data (soup_message, out_certificate_pem, out_certificate_errors); } else { e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED); } g_object_unref (soup_message); empty_cache (backend); return FALSE; } e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTED); if (priv->store) { const gchar *etag; etag = soup_message_headers_get_one ( soup_message->response_headers, "ETag"); if (etag != NULL && *etag == '\0') etag = NULL; e_cal_backend_store_put_key_value (priv->store, "ETag", etag); } /* get the calendar from the response */ icalcomp = icalparser_parse_string (soup_message->response_body->data); if (!icalcomp) { g_set_error ( error, SOUP_HTTP_ERROR, SOUP_STATUS_MALFORMED, _("Bad file format.")); g_object_unref (soup_message); empty_cache (backend); return FALSE; } if (icalcomponent_isa (icalcomp) != ICAL_VCALENDAR_COMPONENT) { g_set_error ( error, SOUP_HTTP_ERROR, SOUP_STATUS_MALFORMED, _("Not a calendar.")); icalcomponent_free (icalcomp); g_object_unref (soup_message); empty_cache (backend); return FALSE; } g_object_unref (soup_message); soup_message = NULL; /* Update cache */ old_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free); comps_in_cache = e_cal_backend_store_get_components (priv->store); while (comps_in_cache != NULL) { const gchar *uid; ECalComponent *comp = comps_in_cache->data; e_cal_component_get_uid (comp, &uid); g_hash_table_insert (old_cache, g_strdup (uid), e_cal_component_get_as_string (comp)); comps_in_cache = g_slist_remove (comps_in_cache, comps_in_cache->data); g_object_unref (comp); } kind = e_cal_backend_get_kind (E_CAL_BACKEND (backend)); subcomp = icalcomponent_get_first_component (icalcomp, ICAL_ANY_COMPONENT); e_cal_backend_store_freeze_changes (priv->store); while (subcomp) { ECalComponent *comp; icalcomponent_kind subcomp_kind; icalproperty *prop = NULL; subcomp_kind = icalcomponent_isa (subcomp); prop = icalcomponent_get_first_property (subcomp, ICAL_UID_PROPERTY); if (!prop && subcomp_kind == kind) { gchar *new_uid = e_cal_component_gen_uid (); icalcomponent_set_uid (subcomp, new_uid); g_free (new_uid); } if (subcomp_kind == kind) { comp = e_cal_component_new (); if (e_cal_component_set_icalcomponent (comp, icalcomponent_new_clone (subcomp))) { const gchar *uid; gpointer orig_key, orig_value; e_cal_component_get_uid (comp, &uid); if (!put_component_to_store (backend, comp)) { g_hash_table_remove (old_cache, uid); } else if (g_hash_table_lookup_extended (old_cache, uid, &orig_key, &orig_value)) { ECalComponent *orig_comp = e_cal_component_new_from_string (orig_value); e_cal_backend_notify_component_modified (E_CAL_BACKEND (backend), orig_comp, comp); g_hash_table_remove (old_cache, uid); if (orig_comp) g_object_unref (orig_comp); } else { e_cal_backend_notify_component_created (E_CAL_BACKEND (backend), comp); } } g_object_unref (comp); } else if (subcomp_kind == ICAL_VTIMEZONE_COMPONENT) { icaltimezone *zone; zone = icaltimezone_new (); icaltimezone_set_component (zone, icalcomponent_new_clone (subcomp)); e_timezone_cache_add_timezone (timezone_cache, zone); icaltimezone_free (zone, 1); } subcomp = icalcomponent_get_next_component (icalcomp, ICAL_ANY_COMPONENT); } e_cal_backend_store_thaw_changes (priv->store); /* notify the removals */ g_hash_table_foreach_remove (old_cache, (GHRFunc) notify_and_remove_from_cache, backend); g_hash_table_destroy (old_cache); /* free memory */ icalcomponent_free (icalcomp); priv->opened = TRUE; return TRUE; }