[evolution-data-server/wip/offline-cache] Make ECalBackendHttp derive from ECalMetaBackend
- From: Milan Crha <mcrha src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [evolution-data-server/wip/offline-cache] Make ECalBackendHttp derive from ECalMetaBackend
- Date: Tue, 21 Mar 2017 17:33:45 +0000 (UTC)
commit 339974cb2fcdec74b5461bc0a92085fad88ba09b
Author: Milan Crha <mcrha redhat com>
Date: Thu Mar 16 15:31:49 2017 +0100
Make ECalBackendHttp derive from ECalMetaBackend
src/calendar/backends/http/e-cal-backend-http.c | 1754 ++++++-----------------
src/calendar/backends/http/e-cal-backend-http.h | 4 +-
2 files changed, 458 insertions(+), 1300 deletions(-)
---
diff --git a/src/calendar/backends/http/e-cal-backend-http.c b/src/calendar/backends/http/e-cal-backend-http.c
index 1cb7f13..6d806c5 100644
--- a/src/calendar/backends/http/e-cal-backend-http.c
+++ b/src/calendar/backends/http/e-cal-backend-http.c
@@ -28,225 +28,26 @@
#include <libedata-cal/libedata-cal.h>
#include "e-cal-backend-http.h"
-#define E_CAL_BACKEND_HTTP_GET_PRIVATE(obj) \
- (G_TYPE_INSTANCE_GET_PRIVATE \
- ((obj), E_TYPE_CAL_BACKEND_HTTP, ECalBackendHttpPrivate))
-
#define EDC_ERROR(_code) e_data_cal_create_error (_code, NULL)
#define EDC_ERROR_EX(_code, _msg) e_data_cal_create_error (_code, _msg)
-G_DEFINE_TYPE (ECalBackendHttp, e_cal_backend_http, E_TYPE_CAL_BACKEND_SYNC)
+G_DEFINE_TYPE (ECalBackendHttp, e_cal_backend_http, E_TYPE_CAL_META_BACKEND)
-/* Private part of the ECalBackendHttp structure */
struct _ECalBackendHttpPrivate {
- /* signal handler id for source's 'changed' signal */
- gulong source_changed_id;
- /* URI to get remote calendar data from */
- gchar *uri;
-
- /* The file cache */
- ECalBackendStore *store;
-
- /* Soup handles for remote file */
SoupSession *soup_session;
- /* Reload */
- guint reload_timeout_id;
- guint is_loading : 1;
+ SoupRequestHTTP *request;
+ GInputStream *input_stream;
+ GHashTable *components; /* gchar *uid ~> icalcomponent * */
- /* Flags */
- gboolean opened;
- gboolean requires_auth;
-
- gchar *username;
- gchar *password;
+ ENamedParameters *credentials;
};
#define d(x)
-static void e_cal_backend_http_add_timezone (ECalBackendSync *backend,
- EDataCal *cal,
- GCancellable *cancellable,
- const gchar *tzobj,
- GError **perror);
-
-static void
-soup_authenticate (SoupSession *session,
- SoupMessage *msg,
- SoupAuth *auth,
- gboolean retrying,
- gpointer data)
-{
- ECalBackendHttp *cbhttp;
- ESourceAuthentication *auth_extension;
- ESource *source;
- const gchar *extension_name;
- const gchar *username;
- gchar *auth_user;
-
- if (retrying)
- return;
-
- cbhttp = E_CAL_BACKEND_HTTP (data);
-
- source = e_backend_get_source (E_BACKEND (data));
- extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
- auth_extension = e_source_get_extension (source, extension_name);
-
- auth_user = e_source_authentication_dup_user (auth_extension);
-
- username = cbhttp->priv->username;
- if (!username || !*username)
- username = auth_user;
-
- if (!username || !*username || !cbhttp->priv->password)
- soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN);
- else
- soup_auth_authenticate (auth, username, cbhttp->priv->password);
-
- g_free (auth_user);
-}
-
-/* Dispose handler for the file backend */
-static void
-e_cal_backend_http_dispose (GObject *object)
-{
- ECalBackendHttp *cbhttp;
- ECalBackendHttpPrivate *priv;
-
- cbhttp = E_CAL_BACKEND_HTTP (object);
- priv = cbhttp->priv;
-
- if (priv->reload_timeout_id) {
- ESource *source = e_backend_get_source (E_BACKEND (cbhttp));
- e_source_refresh_remove_timeout (source, priv->reload_timeout_id);
- priv->reload_timeout_id = 0;
- }
-
- if (priv->soup_session) {
- soup_session_abort (priv->soup_session);
- g_object_unref (priv->soup_session);
- priv->soup_session = NULL;
- }
- if (priv->source_changed_id) {
- g_signal_handler_disconnect (
- e_backend_get_source (E_BACKEND (cbhttp)),
- priv->source_changed_id);
- priv->source_changed_id = 0;
- }
-
- /* Chain up to parent's dispose() method. */
- G_OBJECT_CLASS (e_cal_backend_http_parent_class)->dispose (object);
-}
-
-/* Finalize handler for the file backend */
-static void
-e_cal_backend_http_finalize (GObject *object)
-{
- ECalBackendHttpPrivate *priv;
-
- priv = E_CAL_BACKEND_HTTP_GET_PRIVATE (object);
-
- /* Clean up */
-
- if (priv->store) {
- g_object_unref (priv->store);
- priv->store = NULL;
- }
-
- g_free (priv->uri);
- g_free (priv->username);
- g_free (priv->password);
-
- /* Chain up to parent's finalize() method. */
- G_OBJECT_CLASS (e_cal_backend_http_parent_class)->finalize (object);
-}
-
-static void
-e_cal_backend_http_constructed (GObject *object)
-{
- ECalBackendHttp *backend;
- SoupSession *soup_session;
-
- /* Chain up to parent's constructed() method. */
- G_OBJECT_CLASS (e_cal_backend_http_parent_class)->constructed (object);
-
- soup_session = soup_session_sync_new ();
- g_object_set (
- soup_session,
- SOUP_SESSION_TIMEOUT, 90,
- SOUP_SESSION_SSL_STRICT, TRUE,
- SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE,
- SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE,
- NULL);
-
- backend = E_CAL_BACKEND_HTTP (object);
- backend->priv->soup_session = soup_session;
-
- e_binding_bind_property (
- backend, "proxy-resolver",
- backend->priv->soup_session, "proxy-resolver",
- G_BINDING_SYNC_CREATE);
-
- g_signal_connect (
- backend->priv->soup_session, "authenticate",
- G_CALLBACK (soup_authenticate), backend);
-
- if (g_getenv ("WEBCAL_DEBUG") != NULL) {
- SoupLogger *logger;
-
- logger = soup_logger_new (
- SOUP_LOGGER_LOG_BODY, 1024 * 1024);
- soup_session_add_feature (
- backend->priv->soup_session,
- SOUP_SESSION_FEATURE (logger));
- g_object_unref (logger);
- }
-}
-
-/* Calendar backend methods */
-
static gchar *
-e_cal_backend_http_get_backend_property (ECalBackend *backend,
- const gchar *prop_name)
-{
- g_return_val_if_fail (prop_name != NULL, NULL);
-
- if (g_str_equal (prop_name, CLIENT_BACKEND_PROPERTY_CAPABILITIES)) {
- return g_strjoin (
- ","
- CAL_STATIC_CAPABILITY_NO_EMAIL_ALARMS,
- CAL_STATIC_CAPABILITY_REFRESH_SUPPORTED,
- NULL);
-
- } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_CAL_EMAIL_ADDRESS) ||
- g_str_equal (prop_name, CAL_BACKEND_PROPERTY_ALARM_EMAIL_ADDRESS)) {
- /* A HTTP backend has no particular email address associated
- * with it (although that would be a useful feature some day).
- */
- return NULL;
-
- } else if (g_str_equal (prop_name, CAL_BACKEND_PROPERTY_DEFAULT_OBJECT)) {
- icalcomponent *icalcomp;
- icalcomponent_kind kind;
- gchar *prop_value;
-
- kind = e_cal_backend_get_kind (E_CAL_BACKEND (backend));
- icalcomp = e_cal_util_new_component (kind);
- prop_value = icalcomponent_as_ical_string_r (icalcomp);
- icalcomponent_free (icalcomp);
-
- return prop_value;
- }
-
- /* Chain up to parent's get_backend_property() method. */
- return E_CAL_BACKEND_CLASS (e_cal_backend_http_parent_class)->
- get_backend_property (backend, prop_name);
-}
-
-static gchar *
-webcal_to_http_method (const gchar *webcal_str,
- gboolean secure)
+ecb_http_webcal_to_http_method (const gchar *webcal_str,
+ gboolean secure)
{
if (secure && (strncmp ("http://", webcal_str, sizeof ("http://") - 1) == 0))
return g_strconcat ("https://", webcal_str + sizeof ("http://") - 1, NULL);
@@ -260,202 +61,44 @@ webcal_to_http_method (const gchar *webcal_str,
return g_strconcat ("http://", webcal_str + sizeof ("webcal://") - 1, NULL);
}
-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
-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);
-}
-
-/* TODO Do not replicate this in every backend */
-static icaltimezone *
-resolve_tzid (const gchar *tzid,
- gpointer user_data)
-{
- ETimezoneCache *timezone_cache;
-
- timezone_cache = E_TIMEZONE_CACHE (user_data);
-
- return e_timezone_cache_get_timezone (timezone_cache, tzid);
-}
-
-static gboolean
-put_component_to_store (ECalBackendHttp *cb,
- ECalComponent *comp)
+static gchar *
+ecb_http_dup_uri (ECalBackendHttp *cbhttp)
{
- time_t time_start, time_end;
- ECalBackendHttpPrivate *priv;
- ECalComponent *cache_comp;
- const gchar *uid;
- gchar *rid;
-
- priv = cb->priv;
-
- e_cal_component_get_uid (comp, &uid);
- rid = e_cal_component_get_recurid_as_string (comp);
- cache_comp = e_cal_backend_store_get_component (priv->store, uid, rid);
- g_free (rid);
-
- if (cache_comp) {
- gboolean changed = TRUE;
- struct icaltimetype stamp1, stamp2;
-
- stamp1 = icaltime_null_time ();
- stamp2 = icaltime_null_time ();
-
- e_cal_component_get_dtstamp (comp, &stamp1);
- e_cal_component_get_dtstamp (cache_comp, &stamp2);
-
- changed = (icaltime_is_null_time (stamp1) && !icaltime_is_null_time (stamp2)) ||
- (!icaltime_is_null_time (stamp1) && icaltime_is_null_time (stamp2)) ||
- (icaltime_compare (stamp1, stamp2) != 0);
-
- if (!changed) {
- struct icaltimetype *last_modified1 = NULL, *last_modified2 = NULL;
-
- e_cal_component_get_last_modified (comp, &last_modified1);
- e_cal_component_get_last_modified (cache_comp, &last_modified2);
-
- changed = (last_modified1 != NULL && last_modified2 == NULL) ||
- (last_modified1 == NULL && last_modified2 != NULL) ||
- (last_modified1 != NULL && last_modified2 != NULL && icaltime_compare
(*last_modified1, *last_modified2) != 0);
-
- if (last_modified1)
- e_cal_component_free_icaltimetype (last_modified1);
- if (last_modified2)
- e_cal_component_free_icaltimetype (last_modified2);
-
- if (!changed) {
- gint *sequence1 = NULL, *sequence2 = NULL;
-
- e_cal_component_get_sequence (comp, &sequence1);
- e_cal_component_get_sequence (cache_comp, &sequence2);
-
- changed = (sequence1 != NULL && sequence2 == NULL) ||
- (sequence1 == NULL && sequence2 != NULL) ||
- (sequence1 != NULL && sequence2 != NULL && *sequence1 !=
*sequence2);
+ ESource *source;
+ ESourceSecurity *security_extension;
+ ESourceWebdav *webdav_extension;
+ SoupURI *soup_uri;
+ gboolean secure_connection;
+ const gchar *extension_name;
+ gchar *uri_string, *uri;
- if (sequence1)
- e_cal_component_free_sequence (sequence1);
- if (sequence2)
- e_cal_component_free_sequence (sequence2);
- }
- }
+ g_return_val_if_fail (E_IS_CAL_BACKEND_HTTP (cbhttp), NULL);
- g_object_unref (cache_comp);
+ source = e_backend_get_source (E_BACKEND (cbhttp));
- if (!changed)
- return FALSE;
- }
+ extension_name = E_SOURCE_EXTENSION_SECURITY;
+ security_extension = e_source_get_extension (source, extension_name);
- e_cal_util_get_component_occur_times (
- comp, &time_start, &time_end,
- resolve_tzid, cb, icaltimezone_get_utc_timezone (),
- e_cal_backend_get_kind (E_CAL_BACKEND (cb)));
+ extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
+ webdav_extension = e_source_get_extension (source, extension_name);
- e_cal_backend_store_put_component_with_time_range (priv->store, comp, time_start, time_end);
+ secure_connection = e_source_security_get_secure (security_extension);
- return TRUE;
-}
+ soup_uri = e_source_webdav_dup_soup_uri (webdav_extension);
+ uri_string = soup_uri_to_string (soup_uri, FALSE);
+ soup_uri_free (soup_uri);
-static SoupMessage *
-cal_backend_http_new_message (ECalBackendHttp *backend,
- const gchar *uri)
-{
- SoupMessage *soup_message;
-
- /* create message to be sent to server */
- soup_message = soup_message_new (SOUP_METHOD_GET, uri);
- if (soup_message == NULL)
- return NULL;
-
- soup_message_headers_append (
- soup_message->request_headers,
- "User-Agent", "Evolution/" VERSION);
- soup_message_headers_append (
- soup_message->request_headers,
- "Connection", "close");
- soup_message_set_flags (
- soup_message, SOUP_MESSAGE_NO_REDIRECT);
- if (backend->priv->store != NULL) {
- const gchar *etag;
-
- etag = e_cal_backend_store_get_key_value (
- backend->priv->store, "ETag");
-
- if (etag != NULL && *etag != '\0')
- soup_message_headers_append (
- soup_message->request_headers,
- "If-None-Match", etag);
- }
+ uri = ecb_http_webcal_to_http_method (uri_string, secure_connection);
- return soup_message;
-}
+ g_free (uri_string);
-static void
-cal_backend_http_cancelled (GCancellable *cancellable,
- gpointer user_data)
-{
- struct {
- SoupSession *soup_session;
- SoupMessage *soup_message;
- } *cancel_data = user_data;
-
- soup_session_cancel_message (
- cancel_data->soup_session,
- cancel_data->soup_message,
- SOUP_STATUS_CANCELLED);
+ return uri;
}
static void
-cal_backend_http_extract_ssl_failed_data (SoupMessage *msg,
- gchar **out_certificate_pem,
- GTlsCertificateFlags *out_certificate_errors)
+ecb_http_extract_ssl_failed_data (SoupMessage *msg,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors)
{
GTlsCertificate *certificate = NULL;
@@ -475,1106 +118,621 @@ cal_backend_http_extract_ssl_failed_data (SoupMessage *msg,
}
}
-static gboolean
-cal_backend_http_load (ECalBackendHttp *backend,
- const gchar *uri,
- gchar **out_certificate_pem,
- GTlsCertificateFlags *out_certificate_errors,
- GCancellable *cancellable,
- GError **error)
+static void
+ecb_http_soup_authenticate (SoupSession *session,
+ SoupMessage *msg,
+ SoupAuth *auth,
+ gboolean retrying,
+ gpointer user_data)
{
- 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;
+ ECalBackendHttp *cbhttp;
+ const gchar *username;
+ gchar *auth_user = NULL;
- timezone_cache = E_TIMEZONE_CACHE (backend);
+ if (retrying)
+ return;
- soup_session = backend->priv->soup_session;
- soup_message = cal_backend_http_new_message (backend, uri);
+ cbhttp = E_CAL_BACKEND_HTTP (user_data);
- if (soup_message == NULL) {
- g_set_error (
- error, SOUP_HTTP_ERROR,
- SOUP_STATUS_MALFORMED,
- _("Malformed URI: %s"), uri);
- return FALSE;
- }
+ username = cbhttp->priv->credentials ? e_named_parameters_get (cbhttp->priv->credentials,
E_SOURCE_CREDENTIAL_USERNAME) : NULL;
+ if (!username || !*username) {
+ ESourceAuthentication *auth_extension;
+ ESource *source;
- if (G_IS_CANCELLABLE (cancellable)) {
- cancel_data.soup_session = soup_session;
- cancel_data.soup_message = soup_message;
+ source = e_backend_get_source (E_BACKEND (cbhttp));
+ auth_extension = e_source_get_extension (source, E_SOURCE_EXTENSION_AUTHENTICATION);
+ auth_user = e_source_authentication_dup_user (auth_extension);
- cancel_id = g_cancellable_connect (
- cancellable,
- G_CALLBACK (cal_backend_http_cancelled),
- &cancel_data, (GDestroyNotify) NULL);
+ username = auth_user;
}
- source = e_backend_get_source (E_BACKEND (backend));
-
- e_soup_ssl_trust_connect (soup_message, source);
+ if (!username || !*username || !cbhttp->priv->credentials ||
+ !e_named_parameters_exists (cbhttp->priv->credentials, E_SOURCE_CREDENTIAL_PASSWORD))
+ soup_message_set_status (msg, SOUP_STATUS_FORBIDDEN);
+ else
+ soup_auth_authenticate (auth, username, e_named_parameters_get (cbhttp->priv->credentials,
E_SOURCE_CREDENTIAL_PASSWORD));
- e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTING);
+ g_free (auth_user);
+}
- status_code = soup_session_send_message (soup_session, soup_message);
+static gboolean
+ecb_http_connect_sync (ECalMetaBackend *meta_backend,
+ const ENamedParameters *credentials,
+ ESourceAuthenticationResult *out_auth_result,
+ gchar **out_certificate_pem,
+ GTlsCertificateFlags *out_certificate_errors,
+ GCancellable *cancellable,
+ GError **error)
+{
+ ECalBackendHttp *cbhttp;
+ ESource *source;
+ SoupRequestHTTP *request;
+ GInputStream *input_stream = NULL;
+ gchar *uri;
+ gboolean success;
+ GError *local_error = NULL;
- if (G_IS_CANCELLABLE (cancellable))
- g_cancellable_disconnect (cancellable, cancel_id);
+ g_return_val_if_fail (E_IS_CAL_BACKEND_HTTP (meta_backend), FALSE);
+ g_return_val_if_fail (out_auth_result != NULL, FALSE);
- if (status_code == SOUP_STATUS_NOT_MODIFIED) {
- e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTED);
+ cbhttp = E_CAL_BACKEND_HTTP (meta_backend);
- /* attempts with ETag can result in 304 status code */
- g_object_unref (soup_message);
- priv->opened = TRUE;
+ if (cbhttp->priv->request && cbhttp->priv->input_stream)
return TRUE;
- }
- /* Handle redirection ourselves */
- if (SOUP_STATUS_IS_REDIRECTION (status_code)) {
- gboolean success;
+ source = e_backend_get_source (E_BACKEND (meta_backend));
- newuri = soup_message_headers_get_list (
- soup_message->response_headers, "Location");
+ g_clear_object (&cbhttp->priv->input_stream);
+ g_clear_object (&cbhttp->priv->request);
- d (g_message ("Redirected from %s to %s\n", async_context->uri, newuri));
+ uri = ecb_http_dup_uri (cbhttp);
- if (newuri != NULL) {
- gchar *redirected_uri;
+ if (!uri || !*uri) {
+ g_free (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);
+ g_propagate_error (error, EDC_ERROR_EX (OtherError, _("URI not set")));
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;
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTING);
- /* Update cache */
- old_cache = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_free);
+ e_named_parameters_free (cbhttp->priv->credentials);
+ cbhttp->priv->credentials = credentials ? e_named_parameters_new_clone (credentials) : NULL;
- 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;
+ request = soup_session_request_http (cbhttp->priv->soup_session, SOUP_METHOD_GET, uri, &local_error);
+ success = request != NULL;
- e_cal_component_get_uid (comp, &uid);
- g_hash_table_insert (old_cache, g_strdup (uid), e_cal_component_get_as_string (comp));
+ if (success) {
+ SoupMessage *message;
- 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);
+ message = soup_request_http_get_message (request);
+ if (message) {
+ soup_message_headers_append (message->request_headers, "User-Agent", "Evolution/"
VERSION);
+ soup_message_headers_append (message->request_headers, "Connection", "close");
}
- 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;
+ input_stream = soup_request_send (SOUP_REQUEST (request), cancellable, &local_error);
- e_cal_component_get_uid (comp, &uid);
+ success = input_stream != NULL;
- 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);
+ if (success && message && !SOUP_STATUS_IS_SUCCESSFUL (message->status_code)) {
+ g_clear_object (&input_stream);
+ success = FALSE;
+ }
- 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);
- }
+ if (success) {
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_CONNECTED);
+ } else {
+ guint status_code = message ? message->status_code : SOUP_STATUS_MALFORMED;
+ gboolean credentials_empty;
+
+ credentials_empty = !credentials || !e_named_parameters_count (credentials);
+
+ *out_auth_result = E_SOURCE_AUTHENTICATION_ERROR;
+
+ /* 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", message->reason_phrase);
+ } else if (status_code == SOUP_STATUS_FORBIDDEN && credentials_empty) {
+ *out_auth_result = E_SOURCE_AUTHENTICATION_REQUIRED;
+ } else if (status_code == SOUP_STATUS_UNAUTHORIZED ||
+ status_code == SOUP_STATUS_FORBIDDEN) {
+ *out_auth_result = E_SOURCE_AUTHENTICATION_REJECTED;
+ } else if (local_error) {
+ g_propagate_error (error, local_error);
+ local_error = NULL;
+ } else {
+ g_set_error (error, SOUP_HTTP_ERROR, status_code,
+ "%s", message ? message->reason_phrase : soup_status_get_phrase
(status_code));
}
- g_object_unref (comp);
- } else if (subcomp_kind == ICAL_VTIMEZONE_COMPONENT) {
- icaltimezone *zone;
+ if (status_code == SOUP_STATUS_SSL_FAILED) {
+ *out_auth_result = E_SOURCE_AUTHENTICATION_ERROR_SSL_FAILED;
- zone = icaltimezone_new ();
- icaltimezone_set_component (zone, icalcomponent_new_clone (subcomp));
- e_timezone_cache_add_timezone (timezone_cache, zone);
-
- icaltimezone_free (zone, 1);
+ e_source_set_connection_status (source,
E_SOURCE_CONNECTION_STATUS_SSL_FAILED);
+ if (message)
+ ecb_http_extract_ssl_failed_data (message, out_certificate_pem,
out_certificate_errors);
+ } else {
+ e_source_set_connection_status (source,
E_SOURCE_CONNECTION_STATUS_DISCONNECTED);
+ }
}
- subcomp = icalcomponent_get_next_component (icalcomp, ICAL_ANY_COMPONENT);
- }
+ g_clear_object (&message);
+ } else {
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED);
- e_cal_backend_store_thaw_changes (priv->store);
+ g_set_error (error, E_DATA_CAL_ERROR, OtherError, _("Malformed URI ā%sā: %s"),
+ uri, local_error ? local_error->message : _("Unknown error"));
+ }
- /* notify the removals */
- g_hash_table_foreach_remove (old_cache, (GHRFunc) notify_and_remove_from_cache, backend);
- g_hash_table_destroy (old_cache);
+ if (success) {
+ cbhttp->priv->request = request;
+ cbhttp->priv->input_stream = input_stream;
- /* free memory */
- icalcomponent_free (icalcomp);
+ *out_auth_result = E_SOURCE_AUTHENTICATION_ACCEPTED;
+ } else {
+ g_clear_object (&request);
+ g_clear_object (&input_stream);
+ }
- priv->opened = TRUE;
+ g_clear_error (&local_error);
+ g_free (uri);
- return TRUE;
+ return success;
}
-static const gchar *
-cal_backend_http_ensure_uri (ECalBackendHttp *backend)
+static gboolean
+ecb_http_disconnect_sync (ECalMetaBackend *meta_backend,
+ GCancellable *cancellable,
+ GError **error)
{
+ ECalBackendHttp *cbhttp;
ESource *source;
- ESourceSecurity *security_extension;
- ESourceWebdav *webdav_extension;
- SoupURI *soup_uri;
- gboolean secure_connection;
- const gchar *extension_name;
- gchar *uri_string;
- if (backend->priv->uri != NULL)
- return backend->priv->uri;
+ g_return_val_if_fail (E_IS_CAL_BACKEND_HTTP (meta_backend), FALSE);
- source = e_backend_get_source (E_BACKEND (backend));
+ cbhttp = E_CAL_BACKEND_HTTP (meta_backend);
- extension_name = E_SOURCE_EXTENSION_SECURITY;
- security_extension = e_source_get_extension (source, extension_name);
+ if (cbhttp->priv->soup_session)
+ soup_session_abort (cbhttp->priv->soup_session);
- extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
- webdav_extension = e_source_get_extension (source, extension_name);
+ g_clear_object (&cbhttp->priv->input_stream);
+ g_clear_object (&cbhttp->priv->request);
- secure_connection = e_source_security_get_secure (security_extension);
-
- soup_uri = e_source_webdav_dup_soup_uri (webdav_extension);
- uri_string = soup_uri_to_string (soup_uri, FALSE);
- soup_uri_free (soup_uri);
-
- backend->priv->uri = webcal_to_http_method (
- uri_string, secure_connection);
+ if (cbhttp->priv->components) {
+ g_hash_table_destroy (cbhttp->priv->components);
+ cbhttp->priv->components = NULL;
+ }
- g_free (uri_string);
+ source = e_backend_get_source (E_BACKEND (meta_backend));
+ e_source_set_connection_status (source, E_SOURCE_CONNECTION_STATUS_DISCONNECTED);
- return backend->priv->uri;
+ return TRUE;
}
-static void
-begin_retrieval_cb (GTask *task,
- gpointer source_object,
- gpointer task_tada,
- GCancellable *cancellable)
+static gchar *
+ecb_http_read_stream_sync (GInputStream *input_stream,
+ goffset expected_length,
+ GCancellable *cancellable,
+ GError **error)
{
- ECalBackendHttp *backend = source_object;
- const gchar *uri;
- gchar *certificate_pem = NULL;
- GTlsCertificateFlags certificate_errors = 0;
- GError *error = NULL;
-
- if (!e_backend_get_online (E_BACKEND (backend)) ||
- backend->priv->is_loading)
- return;
-
- d (g_message ("Starting retrieval...\n"));
+ GString *icalstr;
+ void *buffer;
+ gsize nread = 0;
+ gboolean success = FALSE;
- backend->priv->is_loading = TRUE;
+ g_return_val_if_fail (G_IS_INPUT_STREAM (input_stream), NULL);
- uri = cal_backend_http_ensure_uri (backend);
- cal_backend_http_load (backend, uri, &certificate_pem, &certificate_errors, cancellable, &error);
+ icalstr = g_string_sized_new (expected_length > 0 ? expected_length + 1 : 1024);
- if (g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_UNAUTHORIZED) ||
- g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) {
- GError *local_error = NULL;
- ESourceCredentialsReason reason = E_SOURCE_CREDENTIALS_REASON_REQUIRED;
+ buffer = g_malloc (16384);
- if (g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) {
- reason = E_SOURCE_CREDENTIALS_REASON_SSL_FAILED;
- }
-
- e_backend_credentials_required_sync (E_BACKEND (backend),
- reason, certificate_pem, certificate_errors, error, cancellable, &local_error);
-
- g_clear_error (&error);
- error = local_error;
- } else if (g_error_matches (error, SOUP_HTTP_ERROR, SOUP_STATUS_FORBIDDEN)) {
- GError *local_error = NULL;
-
- e_backend_credentials_required_sync (E_BACKEND (backend),
E_SOURCE_CREDENTIALS_REASON_REJECTED,
- certificate_pem, certificate_errors, error, cancellable, &local_error);
-
- g_clear_error (&error);
- error = local_error;
+ while (success = g_input_stream_read_all (input_stream, buffer, 16384, &nread, cancellable, error),
+ success && nread > 0) {
+ g_string_append_len (icalstr, (const gchar *) buffer, nread);
}
- g_free (certificate_pem);
- backend->priv->is_loading = FALSE;
-
- /* Ignore cancellations. */
- if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED)) {
- g_error_free (error);
-
- } else if (error != NULL) {
- e_cal_backend_notify_error (
- E_CAL_BACKEND (backend),
- error->message);
- empty_cache (backend);
- g_error_free (error);
- }
+ g_free (buffer);
- d (g_message ("Retrieval really done.\n"));
+ return g_string_free (icalstr, !success);
}
static void
-http_cal_schedule_begin_retrieval (ECalBackendHttp *cbhttp)
+ecb_http_gather_uids_cb (gpointer uid,
+ gpointer icalcomp,
+ gpointer user_data)
{
- GTask *task;
+ GHashTable *hash_table = user_data;
- task = g_task_new (cbhttp, NULL, NULL, NULL);
+ g_return_if_fail (hash_table != NULL);
- g_task_run_in_thread (task, begin_retrieval_cb);
-
- g_object_unref (task);
+ if (uid)
+ g_hash_table_insert (hash_table, g_strdup (uid), NULL);
}
-static void
-source_changed_cb (ESource *source,
- ECalBackendHttp *cbhttp)
+static gboolean
+ecb_http_remove_unchanged_cb (gpointer uid,
+ gpointer icalcomp,
+ gpointer user_data)
{
- g_return_if_fail (E_IS_CAL_BACKEND_HTTP (cbhttp));
+ GHashTable *unchanged = user_data;
- g_object_ref (cbhttp);
+ g_return_val_if_fail (unchanged != NULL, FALSE);
- if (cbhttp->priv->uri != NULL) {
- gboolean uri_changed;
- const gchar *new_uri;
- gchar *old_uri;
-
- old_uri = g_strdup (cbhttp->priv->uri);
-
- g_free (cbhttp->priv->uri);
- cbhttp->priv->uri = NULL;
+ return !uid || g_hash_table_contains (unchanged, uid);
+}
- new_uri = cal_backend_http_ensure_uri (cbhttp);
+static gboolean
+ecb_http_get_changes_sync (ECalMetaBackend *meta_backend,
+ const gchar *last_sync_tag,
+ gchar **out_new_sync_tag,
+ gboolean *out_repeat,
+ GSList **out_created_objects,
+ GSList **out_modified_objects,
+ GSList **out_removed_objects,
+ GCancellable *cancellable,
+ GError **error)
+{
+ ECalBackendHttp *cbhttp;
+ SoupMessage *message;
+ gchar *icalstring;
+ icalcomponent *vcalendar;
+ gboolean success = TRUE;
- uri_changed = (g_strcmp0 (old_uri, new_uri) != 0);
+ g_return_val_if_fail (E_IS_CAL_BACKEND_HTTP (meta_backend), FALSE);
+ g_return_val_if_fail (out_new_sync_tag != NULL, FALSE);
+ g_return_val_if_fail (out_created_objects != NULL, FALSE);
+ g_return_val_if_fail (out_modified_objects != NULL, FALSE);
+ g_return_val_if_fail (out_removed_objects != NULL, FALSE);
- if (uri_changed && !cbhttp->priv->is_loading)
- http_cal_schedule_begin_retrieval (cbhttp);
+ cbhttp = E_CAL_BACKEND_HTTP (meta_backend);
- g_free (old_uri);
+ if (!cbhttp->priv->request || !cbhttp->priv->input_stream) {
+ g_propagate_error (error, EDC_ERROR (RepositoryOffline));
+ return FALSE;
}
- g_object_unref (cbhttp);
-}
-
-static void
-http_cal_reload_cb (ESource *source,
- gpointer user_data)
-{
- ECalBackendHttp *cbhttp = user_data;
+ message = soup_request_http_get_message (cbhttp->priv->request);
+ if (message) {
+ const gchar *new_etag;
- g_return_if_fail (E_IS_CAL_BACKEND_HTTP (cbhttp));
+ new_etag = soup_message_headers_get_one (message->response_headers, "ETag");
+ if (new_etag && !*new_etag) {
+ new_etag = NULL;
+ } else if (g_strcmp0 (last_sync_tag, new_etag) == 0) {
+ /* Nothing changed */
+ g_object_unref (message);
- if (!e_backend_get_online (E_BACKEND (cbhttp)))
- return;
+ ecb_http_disconnect_sync (meta_backend, cancellable, NULL);
- http_cal_schedule_begin_retrieval (cbhttp);
-}
+ return TRUE;
+ }
-/* Open handler for the file backend */
-static void
-e_cal_backend_http_open (ECalBackendSync *backend,
- EDataCal *cal,
- GCancellable *cancellable,
- gboolean only_if_exists,
- GError **perror)
-{
- ECalBackendHttp *cbhttp;
- ECalBackendHttpPrivate *priv;
- ESource *source;
- ESourceWebdav *webdav_extension;
- const gchar *extension_name;
- const gchar *cache_dir;
- gboolean opened = TRUE;
- gchar *tmp;
- GError *local_error = NULL;
+ *out_new_sync_tag = g_strdup (new_etag);
+ }
- cbhttp = E_CAL_BACKEND_HTTP (backend);
- priv = cbhttp->priv;
+ g_clear_object (&message);
- /* already opened, thus can skip all this initialization */
- if (priv->opened)
- return;
+ icalstring = ecb_http_read_stream_sync (cbhttp->priv->input_stream,
+ soup_request_get_content_length (SOUP_REQUEST (cbhttp->priv->request)), cancellable, error);
- source = e_backend_get_source (E_BACKEND (backend));
- cache_dir = e_cal_backend_get_cache_dir (E_CAL_BACKEND (backend));
+ if (!icalstring) {
+ /* The error is already set */
+ e_cal_meta_backend_empty_cache_sync (meta_backend, cancellable, NULL);
+ ecb_http_disconnect_sync (meta_backend, cancellable, NULL);
+ return FALSE;
+ }
- extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
- webdav_extension = e_source_get_extension (source, extension_name);
+ vcalendar = icalparser_parse_string (icalstring);
- e_source_webdav_unset_temporary_ssl_trust (webdav_extension);
+ g_free (icalstring);
- if (priv->source_changed_id == 0) {
- priv->source_changed_id = g_signal_connect (
- source, "changed",
- G_CALLBACK (source_changed_cb), cbhttp);
+ if (!vcalendar) {
+ g_set_error (error, SOUP_HTTP_ERROR, SOUP_STATUS_MALFORMED, _("Bad file format."));
+ e_cal_meta_backend_empty_cache_sync (meta_backend, cancellable, NULL);
+ ecb_http_disconnect_sync (meta_backend, cancellable, NULL);
+ return FALSE;
}
- /* always read uri again */
- tmp = priv->uri;
- priv->uri = NULL;
- g_free (tmp);
-
- if (priv->store == NULL) {
- /* remove the old cache while migrating to ECalBackendStore */
- e_cal_backend_cache_remove (cache_dir, "cache.xml");
- priv->store = e_cal_backend_store_new (
- cache_dir, E_TIMEZONE_CACHE (backend));
- e_cal_backend_store_load (priv->store);
-
- if (!priv->store) {
- g_propagate_error (
- perror, EDC_ERROR_EX (OtherError,
- _("Could not create cache file")));
- return;
- }
+ if (icalcomponent_isa (vcalendar) != ICAL_VCALENDAR_COMPONENT) {
+ icalcomponent_free (vcalendar);
+ g_set_error (error, SOUP_HTTP_ERROR, SOUP_STATUS_MALFORMED, _("Not a calendar."));
+ e_cal_meta_backend_empty_cache_sync (meta_backend, cancellable, NULL);
+ ecb_http_disconnect_sync (meta_backend, cancellable, NULL);
+ return FALSE;
}
- e_cal_backend_set_writable (E_CAL_BACKEND (backend), FALSE);
+ success = e_cal_meta_backend_gather_timezones_sync (meta_backend, vcalendar, TRUE, cancellable,
error);
+ if (success) {
+ icalcomponent_kind kind = e_cal_backend_get_kind (E_CAL_BACKEND (meta_backend));
+ icalcomponent *subcomp;
+ GHashTable *components;
- if (e_backend_get_online (E_BACKEND (backend))) {
- gchar *certificate_pem = NULL;
- GTlsCertificateFlags certificate_errors = 0;
- const gchar *uri;
+ components = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify)
icalcomponent_free);
- uri = cal_backend_http_ensure_uri (cbhttp);
+ while (subcomp = icalcomponent_get_first_component (vcalendar, kind), subcomp) {
+ icalcomponent *existing_icalcomp;
+ gpointer orig_key, orig_value;
+ const gchar *uid;
- opened = cal_backend_http_load (cbhttp, uri, &certificate_pem,
- &certificate_errors, cancellable, &local_error);
+ icalcomponent_remove_component (vcalendar, subcomp);
- if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_UNAUTHORIZED) ||
- g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED) ||
- (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_FORBIDDEN) &&
- !cbhttp->priv->password)) {
- GError *local_error2 = NULL;
- ESourceCredentialsReason reason = E_SOURCE_CREDENTIALS_REASON_REQUIRED;
+ if (!icalcomponent_get_first_property (subcomp, ICAL_UID_PROPERTY)) {
+ gchar *new_uid = e_cal_component_gen_uid ();
+ icalcomponent_set_uid (subcomp, new_uid);
+ g_free (new_uid);
+ }
- if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) {
- reason = E_SOURCE_CREDENTIALS_REASON_SSL_FAILED;
+ uid = icalcomponent_get_uid (subcomp);
+
+ if (!g_hash_table_lookup_extended (components, uid, &orig_key, &orig_value)) {
+ orig_key = NULL;
+ orig_value = NULL;
}
- e_backend_credentials_required_sync (E_BACKEND (cbhttp), reason, certificate_pem,
- certificate_errors, local_error, cancellable, &local_error2);
- g_clear_error (&local_error);
- local_error = local_error2;
- } else if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_FORBIDDEN)) {
- GError *local_error2 = NULL;
+ existing_icalcomp = orig_value;
+ if (existing_icalcomp) {
+ if (icalcomponent_isa (existing_icalcomp) != ICAL_VCALENDAR_COMPONENT) {
+ icalcomponent *vcal;
- e_backend_credentials_required_sync (E_BACKEND (cbhttp),
E_SOURCE_CREDENTIALS_REASON_REJECTED,
- certificate_pem, certificate_errors, local_error, cancellable, &local_error2);
+ vcal = e_cal_util_new_top_level ();
- g_clear_error (&local_error);
- local_error = local_error2;
- }
+ g_warn_if_fail (g_hash_table_steal (components, uid));
- g_free (certificate_pem);
+ icalcomponent_add_component (vcal, existing_icalcomp);
+ g_hash_table_insert (components, g_strdup (uid), vcal);
- if (local_error != NULL)
- g_propagate_error (perror, local_error);
- }
+ g_free (orig_key);
- if (opened) {
- if (!priv->reload_timeout_id)
- priv->reload_timeout_id = e_source_refresh_add_timeout (source, NULL,
http_cal_reload_cb, backend, NULL);
- }
-}
+ existing_icalcomp = vcal;
+ }
-static void
-e_cal_backend_http_refresh (ECalBackendSync *backend,
- EDataCal *cal,
- GCancellable *cancellable,
- GError **perror)
-{
- ECalBackendHttp *cbhttp;
- ECalBackendHttpPrivate *priv;
- ESource *source;
+ icalcomponent_add_component (existing_icalcomp, subcomp);
+ } else {
+ g_hash_table_insert (components, g_strdup (uid), subcomp);
+ }
+ }
- cbhttp = E_CAL_BACKEND_HTTP (backend);
- priv = cbhttp->priv;
+ cbhttp->priv->components = components;
- if (!priv->opened ||
- priv->is_loading)
- return;
+ icalcomponent_free (vcalendar);
- source = e_backend_get_source (E_BACKEND (cbhttp));
- g_return_if_fail (source != NULL);
+ success = E_CAL_META_BACKEND_CLASS (e_cal_backend_http_parent_class)->get_changes_sync
(meta_backend,
+ last_sync_tag, out_new_sync_tag, out_repeat, out_created_objects,
+ out_modified_objects, out_removed_objects, cancellable, error);
- e_source_refresh_force_timeout (source);
-}
+ if (success) {
+ GHashTable *unchanged;
+ GSList *link;
-/* Set_mode handler for the http backend */
-static void
-e_cal_backend_http_notify_online_cb (ECalBackend *backend,
- GParamSpec *pspec)
-{
- gboolean loaded;
- gboolean online;
+ unchanged = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
+ g_hash_table_foreach (cbhttp->priv->components, ecb_http_gather_uids_cb, unchanged);
- online = e_backend_get_online (E_BACKEND (backend));
- loaded = e_cal_backend_is_opened (backend);
+ for (link = *out_created_objects; link; link = g_slist_next (link)) {
+ ECalMetaBackendInfo *nfo = link->data;
- if (online && loaded)
- http_cal_schedule_begin_retrieval (E_CAL_BACKEND_HTTP (backend));
-}
+ if (nfo && nfo->uid)
+ g_hash_table_remove (unchanged, nfo->uid);
+ }
-/* Get_object_component handler for the http backend */
-static void
-e_cal_backend_http_get_object (ECalBackendSync *backend,
- EDataCal *cal,
- GCancellable *cancellable,
- const gchar *uid,
- const gchar *rid,
- gchar **object,
- GError **error)
-{
- ECalBackendHttp *cbhttp;
- ECalBackendHttpPrivate *priv;
- ECalComponent *comp = NULL;
+ for (link = *out_modified_objects; link; link = g_slist_next (link)) {
+ ECalMetaBackendInfo *nfo = link->data;
- cbhttp = E_CAL_BACKEND_HTTP (backend);
- priv = cbhttp->priv;
+ if (nfo && nfo->uid)
+ g_hash_table_remove (unchanged, nfo->uid);
+ }
- if (!priv->store) {
- g_propagate_error (error, EDC_ERROR (ObjectNotFound));
- return;
- }
+ if (g_hash_table_size (unchanged))
+ g_hash_table_foreach_remove (cbhttp->priv->components,
ecb_http_remove_unchanged_cb, unchanged);
- if (rid && *rid) {
- comp = e_cal_backend_store_get_component (priv->store, uid, rid);
- if (!comp) {
- g_propagate_error (error, EDC_ERROR (ObjectNotFound));
- return;
+ g_hash_table_destroy (unchanged);
}
-
- *object = e_cal_component_get_as_string (comp);
- g_object_unref (comp);
} else {
- *object = e_cal_backend_store_get_components_by_uid_as_ical_string (priv->store, uid);
- if (!*object)
- g_propagate_error (error, EDC_ERROR (ObjectNotFound));
- }
-}
-
-/* Add_timezone handler for the file backend */
-static void
-e_cal_backend_http_add_timezone (ECalBackendSync *backend,
- EDataCal *cal,
- GCancellable *cancellable,
- const gchar *tzobj,
- GError **error)
-{
- ETimezoneCache *timezone_cache;
- icalcomponent *tz_comp;
- icaltimezone *zone;
-
- timezone_cache = E_TIMEZONE_CACHE (backend);
-
- tz_comp = icalparser_parse_string (tzobj);
- if (!tz_comp) {
- g_propagate_error (error, EDC_ERROR (InvalidObject));
- return;
+ icalcomponent_free (vcalendar);
}
- if (icalcomponent_isa (tz_comp) != ICAL_VTIMEZONE_COMPONENT) {
- icalcomponent_free (tz_comp);
- g_propagate_error (error, EDC_ERROR (InvalidObject));
- return;
- }
+ if (!success)
+ ecb_http_disconnect_sync (meta_backend, cancellable, NULL);
- zone = icaltimezone_new ();
- icaltimezone_set_component (zone, tz_comp);
- e_timezone_cache_add_timezone (timezone_cache, zone);
+ return success;
}
-/* Get_objects_in_range handler for the file backend */
-static void
-e_cal_backend_http_get_object_list (ECalBackendSync *backend,
- EDataCal *cal,
- GCancellable *cancellable,
- const gchar *sexp,
- GSList **objects,
- GError **perror)
+static gboolean
+ecb_http_list_existing_sync (ECalMetaBackend *meta_backend,
+ gchar **out_new_sync_tag,
+ GSList **out_existing_objects, /* ECalMetaBackendInfo * */
+ GCancellable *cancellable,
+ GError **error)
{
ECalBackendHttp *cbhttp;
- ECalBackendHttpPrivate *priv;
- GSList *components, *l;
- ECalBackendSExp *cbsexp;
- ETimezoneCache *timezone_cache;
- time_t occur_start = -1, occur_end = -1;
- gboolean prunning_by_time;
-
- cbhttp = E_CAL_BACKEND_HTTP (backend);
- priv = cbhttp->priv;
-
- timezone_cache = E_TIMEZONE_CACHE (backend);
-
- if (!priv->store) {
- g_propagate_error (perror, EDC_ERROR (NoSuchCal));
- return;
- }
-
- /* process all components in the cache */
- cbsexp = e_cal_backend_sexp_new (sexp);
-
- *objects = NULL;
- prunning_by_time = e_cal_backend_sexp_evaluate_occur_times (
- cbsexp,
- &occur_start,
- &occur_end);
-
- components = prunning_by_time ?
- e_cal_backend_store_get_components_occuring_in_range (priv->store, occur_start, occur_end)
- : e_cal_backend_store_get_components (priv->store);
+ ECalCache *cal_cache;
+ icalcomponent_kind kind;
+ GHashTableIter iter;
+ gpointer key, value;
- for (l = components; l != NULL; l = g_slist_next (l)) {
- if (e_cal_backend_sexp_match_comp (cbsexp, E_CAL_COMPONENT (l->data), timezone_cache)) {
- *objects = g_slist_append (*objects, e_cal_component_get_as_string (l->data));
- }
- }
+ g_return_val_if_fail (E_IS_CAL_BACKEND_HTTP (meta_backend), FALSE);
+ g_return_val_if_fail (out_existing_objects != NULL, FALSE);
- g_slist_foreach (components, (GFunc) g_object_unref, NULL);
- g_slist_free (components);
- g_object_unref (cbsexp);
-}
+ cbhttp = E_CAL_BACKEND_HTTP (meta_backend);
-static void
-e_cal_backend_http_start_view (ECalBackend *backend,
- EDataCalView *query)
-{
- ECalBackendHttp *cbhttp;
- ECalBackendHttpPrivate *priv;
- GSList *components, *l;
- GSList *objects = NULL;
- ECalBackendSExp *cbsexp;
- ETimezoneCache *timezone_cache;
- time_t occur_start = -1, occur_end = -1;
- gboolean prunning_by_time;
+ *out_existing_objects = NULL;
- cbhttp = E_CAL_BACKEND_HTTP (backend);
- priv = cbhttp->priv;
+ g_return_val_if_fail (cbhttp->priv->components != NULL, FALSE);
- timezone_cache = E_TIMEZONE_CACHE (backend);
+ cal_cache = e_cal_meta_backend_ref_cache (meta_backend);
+ g_return_val_if_fail (cal_cache != NULL, FALSE);
- cbsexp = e_data_cal_view_get_sexp (query);
+ kind = e_cal_backend_get_kind (E_CAL_BACKEND (meta_backend));
- d (g_message (G_STRLOC ": Starting query (%s)", e_cal_backend_sexp_text (cbsexp)));
+ g_hash_table_iter_init (&iter, cbhttp->priv->components);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ icalcomponent *icalcomp = value;
+ ECalMetaBackendInfo *nfo;
+ const gchar *uid;
+ gchar *revision;
- if (!priv->store) {
- GError *error = EDC_ERROR (NoSuchCal);
- e_data_cal_view_notify_complete (query, error);
- g_error_free (error);
- return;
- }
+ if (icalcomp && icalcomponent_isa (icalcomp) == ICAL_VCALENDAR_COMPONENT)
+ icalcomp = icalcomponent_get_first_component (icalcomp, kind);
- /* process all components in the cache */
- objects = NULL;
- prunning_by_time = e_cal_backend_sexp_evaluate_occur_times (
- cbsexp,
- &occur_start,
- &occur_end);
+ if (!icalcomp)
+ continue;
- components = prunning_by_time ?
- e_cal_backend_store_get_components_occuring_in_range (priv->store, occur_start, occur_end)
- : e_cal_backend_store_get_components (priv->store);
+ uid = icalcomponent_get_uid (icalcomp);
+ revision = e_cal_cache_dup_component_revision (cal_cache, icalcomp);
- for (l = components; l != NULL; l = g_slist_next (l)) {
- ECalComponent *comp = l->data;
+ nfo = e_cal_meta_backend_info_new (uid, NULL, revision);
+ *out_existing_objects = g_slist_prepend (*out_existing_objects, nfo);
- if (e_cal_backend_sexp_match_comp (cbsexp, comp, timezone_cache)) {
- objects = g_slist_append (objects, comp);
- }
+ g_free (revision);
}
- e_data_cal_view_notify_components_added (query, objects);
-
- g_slist_free_full (components, g_object_unref);
- g_slist_free (objects);
+ g_object_unref (cal_cache);
- e_data_cal_view_notify_complete (query, NULL /* Success */);
+ return TRUE;
}
-/***** static icaltimezone *
-resolve_tzid (const gchar *tzid,
- * gpointer user_data)
-{
- icalcomponent *vcalendar_comp = user_data;
- *
- if (!tzid || !tzid[0])
- return NULL;
- * else if (!strcmp (tzid, "UTC"))
- return icaltimezone_get_utc_timezone ();
- *
- return icalcomponent_get_timezone (vcalendar_comp, tzid);
-} *****/
-
static gboolean
-free_busy_instance (ECalComponent *comp,
- time_t instance_start,
- time_t instance_end,
- gpointer data)
+ecb_http_load_component_sync (ECalMetaBackend *meta_backend,
+ const gchar *uid,
+ icalcomponent **out_component,
+ gchar **out_extra,
+ GCancellable *cancellable,
+ GError **error)
{
- icalcomponent *vfb = data;
- icalproperty *prop;
- icalparameter *param;
- struct icalperiodtype ipt;
- icaltimezone *utc_zone;
-
- utc_zone = icaltimezone_get_utc_timezone ();
-
- ipt.start = icaltime_from_timet_with_zone (instance_start, FALSE, utc_zone);
- ipt.end = icaltime_from_timet_with_zone (instance_end, FALSE, utc_zone);
- ipt.duration = icaldurationtype_null_duration ();
+ ECalBackendHttp *cbhttp;
+ gpointer key = NULL, value = NULL;
- /* add busy information to the vfb component */
- prop = icalproperty_new (ICAL_FREEBUSY_PROPERTY);
- icalproperty_set_freebusy (prop, ipt);
+ g_return_val_if_fail (E_IS_CAL_BACKEND_HTTP (meta_backend), FALSE);
+ g_return_val_if_fail (uid != NULL, FALSE);
+ g_return_val_if_fail (out_component != NULL, FALSE);
- param = icalparameter_new_fbtype (ICAL_FBTYPE_BUSY);
- icalproperty_add_parameter (prop, param);
+ cbhttp = E_CAL_BACKEND_HTTP (meta_backend);
+ g_return_val_if_fail (cbhttp->priv->components != NULL, FALSE);
- icalcomponent_add_property (vfb, prop);
+ if (!cbhttp->priv->components ||
+ !g_hash_table_contains (cbhttp->priv->components, uid)) {
+ g_propagate_error (error, EDC_ERROR (ObjectNotFound));
+ return FALSE;
+ }
- return TRUE;
-}
+ g_warn_if_fail (g_hash_table_lookup_extended (cbhttp->priv->components, uid, &key, &value));
+ g_warn_if_fail (g_hash_table_steal (cbhttp->priv->components, uid));
-static icalcomponent *
-create_user_free_busy (ECalBackendHttp *cbhttp,
- const gchar *address,
- const gchar *cn,
- time_t start,
- time_t end)
-{
- GSList *slist = NULL, *l;
- icalcomponent *vfb;
- icaltimezone *utc_zone;
- ECalBackendSExp *obj_sexp;
- ECalBackendHttpPrivate *priv;
- ECalBackendStore *store;
- gchar *query, *iso_start, *iso_end;
-
- priv = cbhttp->priv;
- store = priv->store;
-
- /* create the (unique) VFREEBUSY object that we'll return */
- vfb = icalcomponent_new_vfreebusy ();
- if (address != NULL) {
- icalproperty *prop;
- icalparameter *param;
-
- prop = icalproperty_new_organizer (address);
- if (prop != NULL && cn != NULL) {
- param = icalparameter_new_cn (cn);
- icalproperty_add_parameter (prop, param);
- }
- if (prop != NULL)
- icalcomponent_add_property (vfb, prop);
- }
- utc_zone = icaltimezone_get_utc_timezone ();
- icalcomponent_set_dtstart (vfb, icaltime_from_timet_with_zone (start, FALSE, utc_zone));
- icalcomponent_set_dtend (vfb, icaltime_from_timet_with_zone (end, FALSE, utc_zone));
-
- /* add all objects in the given interval */
- iso_start = isodate_from_time_t (start);
- iso_end = isodate_from_time_t (end);
- query = g_strdup_printf (
- "occur-in-time-range? (make-time \"%s\") (make-time \"%s\")",
- iso_start, iso_end);
- obj_sexp = e_cal_backend_sexp_new (query);
- g_free (query);
- g_free (iso_start);
- g_free (iso_end);
-
- if (!obj_sexp)
- return vfb;
-
- slist = e_cal_backend_store_get_components (store);
-
- for (l = slist; l; l = g_slist_next (l)) {
- ECalComponent *comp = l->data;
- icalcomponent *icalcomp, *vcalendar_comp;
- icalproperty *prop;
-
- icalcomp = e_cal_component_get_icalcomponent (comp);
- if (!icalcomp)
- continue;
+ *out_component = value;
- /* If the event is TRANSPARENT, skip it. */
- prop = icalcomponent_get_first_property (
- icalcomp,
- ICAL_TRANSP_PROPERTY);
- if (prop) {
- icalproperty_transp transp_val = icalproperty_get_transp (prop);
- if (transp_val == ICAL_TRANSP_TRANSPARENT ||
- transp_val == ICAL_TRANSP_TRANSPARENTNOCONFLICT)
- continue;
- }
+ g_free (key);
- if (!e_cal_backend_sexp_match_comp (
- obj_sexp, l->data,
- E_TIMEZONE_CACHE (cbhttp)))
- continue;
+ if (!g_hash_table_size (cbhttp->priv->components)) {
+ g_hash_table_destroy (cbhttp->priv->components);
+ cbhttp->priv->components = NULL;
- vcalendar_comp = icalcomponent_get_parent (icalcomp);
- if (!vcalendar_comp)
- vcalendar_comp = icalcomp;
- e_cal_recur_generate_instances (
- comp, start, end,
- free_busy_instance,
- vfb,
- resolve_tzid,
- vcalendar_comp,
- icaltimezone_get_utc_timezone ());
+ ecb_http_disconnect_sync (meta_backend, cancellable, NULL);
}
- g_object_unref (obj_sexp);
- return vfb;
+ return value != NULL;
}
-/* Get_free_busy handler for the file backend */
static void
-e_cal_backend_http_get_free_busy (ECalBackendSync *backend,
- EDataCal *cal,
- GCancellable *cancellable,
- const GSList *users,
- time_t start,
- time_t end,
- GSList **freebusy,
- GError **error)
+e_cal_backend_http_dispose (GObject *object)
{
- ESourceRegistry *registry;
ECalBackendHttp *cbhttp;
- ECalBackendHttpPrivate *priv;
- gchar *address, *name;
- icalcomponent *vfb;
- gchar *calobj;
-
- cbhttp = E_CAL_BACKEND_HTTP (backend);
- priv = cbhttp->priv;
- if (!priv->store) {
- g_propagate_error (error, EDC_ERROR (NoSuchCal));
- return;
- }
+ cbhttp = E_CAL_BACKEND_HTTP (object);
- registry = e_cal_backend_get_registry (E_CAL_BACKEND (backend));
+ g_clear_object (&cbhttp->priv->request);
+ g_clear_object (&cbhttp->priv->input_stream);
- if (users == NULL) {
- if (e_cal_backend_mail_account_get_default (registry, &address, &name)) {
- vfb = create_user_free_busy (cbhttp, address, name, start, end);
- calobj = icalcomponent_as_ical_string_r (vfb);
- *freebusy = g_slist_append (*freebusy, calobj);
- icalcomponent_free (vfb);
- g_free (address);
- g_free (name);
- }
- } else {
- const GSList *l;
- for (l = users; l != NULL; l = l->next ) {
- address = l->data;
- if (e_cal_backend_mail_account_is_valid (registry, address, &name)) {
- vfb = create_user_free_busy (cbhttp, address, name, start, end);
- calobj = icalcomponent_as_ical_string_r (vfb);
- *freebusy = g_slist_append (*freebusy, calobj);
- icalcomponent_free (vfb);
- g_free (name);
- }
- }
+ if (cbhttp->priv->soup_session) {
+ soup_session_abort (cbhttp->priv->soup_session);
+ g_clear_object (&cbhttp->priv->soup_session);
}
-}
-static void
-e_cal_backend_http_create_objects (ECalBackendSync *backend,
- EDataCal *cal,
- GCancellable *cancellable,
- const GSList *calobjs,
- GSList **uids,
- GSList **new_components,
- GError **perror)
-{
- g_propagate_error (perror, EDC_ERROR (PermissionDenied));
-}
+ if (cbhttp->priv->components) {
+ g_hash_table_destroy (cbhttp->priv->components);
+ cbhttp->priv->components = NULL;
+ }
-static void
-e_cal_backend_http_modify_objects (ECalBackendSync *backend,
- EDataCal *cal,
- GCancellable *cancellable,
- const GSList *calobjs,
- ECalObjModType mod,
- GSList **old_components,
- GSList **new_components,
- GError **perror)
-{
- g_propagate_error (perror, EDC_ERROR (PermissionDenied));
+ /* Chain up to parent's method. */
+ G_OBJECT_CLASS (e_cal_backend_http_parent_class)->dispose (object);
}
-/* Remove_objects handler for the file backend */
static void
-e_cal_backend_http_remove_objects (ECalBackendSync *backend,
- EDataCal *cal,
- GCancellable *cancellable,
- const GSList *ids,
- ECalObjModType mod,
- GSList **old_components,
- GSList **new_components,
- GError **perror)
+e_cal_backend_http_finalize (GObject *object)
{
- *old_components = *new_components = NULL;
+ ECalBackendHttp *cbhttp = E_CAL_BACKEND_HTTP (object);
- g_propagate_error (perror, EDC_ERROR (PermissionDenied));
-}
+ e_named_parameters_free (cbhttp->priv->credentials);
+ cbhttp->priv->credentials = NULL;
-/* Update_objects handler for the file backend. */
-static void
-e_cal_backend_http_receive_objects (ECalBackendSync *backend,
- EDataCal *cal,
- GCancellable *cancellable,
- const gchar *calobj,
- GError **perror)
-{
- g_propagate_error (perror, EDC_ERROR (PermissionDenied));
+ /* Chain up to parent's method. */
+ G_OBJECT_CLASS (e_cal_backend_http_parent_class)->finalize (object);
}
static void
-e_cal_backend_http_send_objects (ECalBackendSync *backend,
- EDataCal *cal,
- GCancellable *cancellable,
- const gchar *calobj,
- GSList **users,
- gchar **modified_calobj,
- GError **perror)
-{
- *users = NULL;
- *modified_calobj = NULL;
-
- g_propagate_error (perror, EDC_ERROR (PermissionDenied));
-}
-
-static ESourceAuthenticationResult
-e_cal_backend_http_authenticate_sync (EBackend *backend,
- const ENamedParameters *credentials,
- gchar **out_certificate_pem,
- GTlsCertificateFlags *out_certificate_errors,
- GCancellable *cancellable,
- GError **error)
+e_cal_backend_http_init (ECalBackendHttp *cbhttp)
{
- ECalBackendHttp *cbhttp;
- ESourceAuthenticationResult result;
- const gchar *uri, *username;
- GError *local_error = NULL;
-
- cbhttp = E_CAL_BACKEND_HTTP (backend);
+ SoupSession *soup_session;
- g_free (cbhttp->priv->username);
- cbhttp->priv->username = NULL;
+ cbhttp->priv = G_TYPE_INSTANCE_GET_PRIVATE (cbhttp, E_TYPE_CAL_BACKEND_HTTP, ECalBackendHttpPrivate);
- g_free (cbhttp->priv->password);
- cbhttp->priv->password = g_strdup (e_named_parameters_get (credentials,
E_SOURCE_CREDENTIAL_PASSWORD));
+ e_cal_backend_set_writable (E_CAL_BACKEND (cbhttp), FALSE);
- username = e_named_parameters_get (credentials, E_SOURCE_CREDENTIAL_USERNAME);
- if (username && *username) {
- cbhttp->priv->username = g_strdup (username);
- }
-
- uri = cal_backend_http_ensure_uri (cbhttp);
- if (cal_backend_http_load (cbhttp, uri, out_certificate_pem, out_certificate_errors, cancellable,
&local_error)) {
- if (!cbhttp->priv->reload_timeout_id) {
- ESource *source = e_backend_get_source (backend);
+ soup_session = soup_session_new ();
+ g_object_set (
+ soup_session,
+ SOUP_SESSION_TIMEOUT, 90,
+ SOUP_SESSION_SSL_STRICT, TRUE,
+ SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE,
+ SOUP_SESSION_ACCEPT_LANGUAGE_AUTO, TRUE,
+ NULL);
- cbhttp->priv->reload_timeout_id = e_source_refresh_add_timeout (source, NULL,
http_cal_reload_cb, backend, NULL);
- }
- }
+ if (g_getenv ("WEBCAL_DEBUG") != NULL) {
+ SoupLogger *logger;
- if (local_error == NULL) {
- result = E_SOURCE_AUTHENTICATION_ACCEPTED;
- } else if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_UNAUTHORIZED)) {
- result = E_SOURCE_AUTHENTICATION_REJECTED;
- g_clear_error (&local_error);
- } else if (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) {
- result = E_SOURCE_AUTHENTICATION_ERROR_SSL_FAILED;
- g_propagate_error (error, local_error);
- } else {
- result = E_SOURCE_AUTHENTICATION_ERROR;
- g_propagate_error (error, local_error);
+ logger = soup_logger_new (SOUP_LOGGER_LOG_BODY, 1024 * 1024);
+ soup_session_add_feature (soup_session, SOUP_SESSION_FEATURE (logger));
+ g_object_unref (logger);
}
- return result;
-}
+ cbhttp->priv->soup_session = soup_session;
+ cbhttp->priv->request = NULL;
+ cbhttp->priv->input_stream = NULL;
-/* Object initialization function for the file backend */
-static void
-e_cal_backend_http_init (ECalBackendHttp *cbhttp)
-{
- cbhttp->priv = E_CAL_BACKEND_HTTP_GET_PRIVATE (cbhttp);
+ e_binding_bind_property (
+ cbhttp, "proxy-resolver",
+ cbhttp->priv->soup_session, "proxy-resolver",
+ G_BINDING_SYNC_CREATE);
g_signal_connect (
- cbhttp, "notify::online",
- G_CALLBACK (e_cal_backend_http_notify_online_cb), NULL);
+ cbhttp->priv->soup_session, "authenticate",
+ G_CALLBACK (ecb_http_soup_authenticate), cbhttp);
}
-/* Class initialization function for the file backend */
static void
-e_cal_backend_http_class_init (ECalBackendHttpClass *class)
+e_cal_backend_http_class_init (ECalBackendHttpClass *klass)
{
GObjectClass *object_class;
- EBackendClass *backend_class;
- ECalBackendClass *cal_backend_class;
- ECalBackendSyncClass *sync_class;
-
- g_type_class_add_private (class, sizeof (ECalBackendHttpPrivate));
-
- object_class = (GObjectClass *) class;
- backend_class = E_BACKEND_CLASS (class);
- cal_backend_class = (ECalBackendClass *) class;
- sync_class = (ECalBackendSyncClass *) class;
-
+ ECalBackendSyncClass *cal_backend_sync_class;
+ ECalMetaBackendClass *cal_meta_backend_class;
+
+ g_type_class_add_private (klass, sizeof (ECalBackendHttpPrivate));
+
+ cal_meta_backend_class = E_CAL_META_BACKEND_CLASS (klass);
+ cal_meta_backend_class->connect_sync = ecb_http_connect_sync;
+ cal_meta_backend_class->disconnect_sync = ecb_http_disconnect_sync;
+ cal_meta_backend_class->get_changes_sync = ecb_http_get_changes_sync;
+ cal_meta_backend_class->list_existing_sync = ecb_http_list_existing_sync;
+ cal_meta_backend_class->load_component_sync = ecb_http_load_component_sync;
+
+ /* Setting these methods to NULL will cause "Not supported" error,
+ which is more accurate than "Permission denied" error */
+ cal_backend_sync_class = E_CAL_BACKEND_SYNC_CLASS (klass);
+ cal_backend_sync_class->create_objects_sync = NULL;
+ cal_backend_sync_class->modify_objects_sync = NULL;
+ cal_backend_sync_class->remove_objects_sync = NULL;
+
+ object_class = G_OBJECT_CLASS (klass);
object_class->dispose = e_cal_backend_http_dispose;
object_class->finalize = e_cal_backend_http_finalize;
- object_class->constructed = e_cal_backend_http_constructed;
-
- backend_class->authenticate_sync = e_cal_backend_http_authenticate_sync;
-
- /* Execute one method at a time. */
- cal_backend_class->use_serial_dispatch_queue = TRUE;
- cal_backend_class->get_backend_property = e_cal_backend_http_get_backend_property;
- cal_backend_class->start_view = e_cal_backend_http_start_view;
-
- sync_class->open_sync = e_cal_backend_http_open;
- sync_class->refresh_sync = e_cal_backend_http_refresh;
- sync_class->create_objects_sync = e_cal_backend_http_create_objects;
- sync_class->modify_objects_sync = e_cal_backend_http_modify_objects;
- sync_class->remove_objects_sync = e_cal_backend_http_remove_objects;
- sync_class->receive_objects_sync = e_cal_backend_http_receive_objects;
- sync_class->send_objects_sync = e_cal_backend_http_send_objects;
- sync_class->get_object_sync = e_cal_backend_http_get_object;
- sync_class->get_object_list_sync = e_cal_backend_http_get_object_list;
- sync_class->add_timezone_sync = e_cal_backend_http_add_timezone;
- sync_class->get_free_busy_sync = e_cal_backend_http_get_free_busy;
}
diff --git a/src/calendar/backends/http/e-cal-backend-http.h b/src/calendar/backends/http/e-cal-backend-http.h
index b45ff33..b7c5df3 100644
--- a/src/calendar/backends/http/e-cal-backend-http.h
+++ b/src/calendar/backends/http/e-cal-backend-http.h
@@ -47,12 +47,12 @@ typedef struct _ECalBackendHttpClass ECalBackendHttpClass;
typedef struct _ECalBackendHttpPrivate ECalBackendHttpPrivate;
struct _ECalBackendHttp {
- ECalBackendSync backend;
+ ECalMetaBackend backend;
ECalBackendHttpPrivate *priv;
};
struct _ECalBackendHttpClass {
- ECalBackendSyncClass parent_class;
+ ECalMetaBackendClass parent_class;
};
GType e_cal_backend_http_get_type (void);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]