static void
e_book_backend_webdav_remove_contacts (EBookBackend *backend,
                                       EDataBook *book,
                                       guint32 opid,
                                       GCancellable *cancellable,
                                       const GSList *id_list)
{
	EBookBackendWebdav        *webdav      = E_BOOK_BACKEND_WEBDAV (backend);
	EBookBackendWebdavPrivate *priv        = webdav->priv;
	gchar                     *uid         = id_list->data;
	GSList                     deleted_ids = {NULL,};
	guint                      status;

	if (!e_backend_get_online (E_BACKEND (backend))) {
		e_data_book_respond_remove_contacts (
			book, opid,
			EDB_ERROR (REPOSITORY_OFFLINE), NULL);
		return;
	}

	/* We make the assumption that the ID list we're passed is always exactly one element long, since we haven't specified "bulk-removes"
	 * in our static capability list. */
	if (id_list->next != NULL) {
		e_data_book_respond_remove_contacts (
			book, opid,
			EDB_ERROR_EX (NOT_SUPPORTED,
			_("The backend does not support bulk removals")),
			NULL);
		return;
	}

	status = delete_contact (webdav, uid, cancellable);
	if (status != 204) {
		if (status == 401 || status == 407) {
			e_data_book_respond_remove_contacts (
				book, opid,
				webdav_handle_auth_request (webdav), NULL);
		} else {
			g_warning ("DELETE failed with HTTP status %d", status);
			e_data_book_respond_remove_contacts (
				book, opid,
				e_data_book_create_error_fmt (E_DATA_BOOK_STATUS_OTHER_ERROR,
				_("DELETE failed with HTTP status %d"), status),
				NULL);
		}
		return;
	}

	g_mutex_lock (&priv->cache_lock);
	e_book_backend_cache_remove_contact (priv->cache, uid);
	g_mutex_unlock (&priv->cache_lock);

	deleted_ids.data = uid;
	e_data_book_respond_remove_contacts (book, opid, EDB_ERROR (SUCCESS), &deleted_ids);
}
Esempio n. 2
0
static void
http_cal_reload_cb (ESource *source,
                    gpointer user_data)
{
	ECalBackendHttp *cbhttp = user_data;

	g_return_if_fail (E_IS_CAL_BACKEND_HTTP (cbhttp));

	if (!e_backend_get_online (E_BACKEND (cbhttp)))
		return;

	http_cal_schedule_begin_retrieval (cbhttp);
}
Esempio n. 3
0
/* Set_mode handler for the http backend */
static void
e_cal_backend_http_notify_online_cb (ECalBackend *backend,
                                     GParamSpec *pspec)
{
	gboolean loaded;
	gboolean online;

	online = e_backend_get_online (E_BACKEND (backend));
	loaded = e_cal_backend_is_opened (backend);

	if (online && loaded)
		http_cal_schedule_begin_retrieval (E_CAL_BACKEND_HTTP (backend));
}
static void
e_book_backend_webdav_notify_online_cb (EBookBackend *backend,
                                        GParamSpec *pspec)
{
	/* set_mode is called before the backend is loaded */
	if (!e_book_backend_is_opened (backend))
		return;

	if (!e_backend_get_online (E_BACKEND (backend))) {
		e_book_backend_notify_readonly (backend, TRUE);
		e_book_backend_notify_online (backend, FALSE);
	} else {
		e_book_backend_notify_readonly (backend, FALSE);
		e_book_backend_notify_online (backend, TRUE);
	}
}
Esempio n. 5
0
/** Periodic sync callback.
 *
 * @param cb 3e calendar backend.
 *
 * @return Always TRUE (continue sync).
 */
static gpointer sync_thread(ECalBackend3e *cb)
{
    int timeout = 5;

    while (TRUE)
    {
        switch (g_atomic_int_get(&cb->priv->sync_request))
        {
        case SYNC_NORMAL:
            g_usleep(1000000);
            if (--timeout > 0)
            {
                break;
            }

        case SYNC_NOW:
            if (g_atomic_int_get(&cb->priv->sync_request) == SYNC_STOP)
            {
                return NULL;
            }
            timeout = 5;

            g_atomic_int_set(&cb->priv->sync_request, SYNC_NORMAL);
            if (e_backend_get_online(E_BACKEND(cb)) && e_cal_backend_3e_calendar_load_perm(cb))
            {
                e_cal_backend_3e_sync_server_to_cache(cb);

                if (e_cal_backend_3e_calendar_has_perm(cb, "write"))
                {
                    e_cal_backend_3e_sync_cache_to_server(cb);
                }
            }
            break;

        case SYNC_PAUSE:
            g_usleep(1000000);
            break;

        case SYNC_STOP:
            return NULL;
        }
    }

    return NULL;
}
static void
e_book_backend_webdav_get_contact_list_uids (EBookBackend *backend,
                                             EDataBook *book,
                                             guint32 opid,
                                             GCancellable *cancellable,
                                             const gchar *query)
{
	EBookBackendWebdav        *webdav = E_BOOK_BACKEND_WEBDAV (backend);
	EBookBackendWebdavPrivate *priv   = webdav->priv;
	GList                     *contact_list;
	GSList                    *uids_list;
	GList                     *c;

	if (e_backend_get_online (E_BACKEND (backend))) {
		/* make sure the cache is up to date */
		GError *error = download_contacts (webdav, NULL, NULL, cancellable);

		if (error) {
			e_data_book_respond_get_contact_list_uids (book, opid, error, NULL);
			return;
		}
	}

	/* answer query from cache */
	g_mutex_lock (&priv->cache_lock);
	contact_list = e_book_backend_cache_get_contacts (priv->cache, query);
	g_mutex_unlock (&priv->cache_lock);

	uids_list   = NULL;
	for (c = contact_list; c != NULL; c = g_list_next (c)) {
		EContact *contact = c->data;

		uids_list = g_slist_append (uids_list, e_contact_get (contact, E_CONTACT_UID));

		g_object_unref (contact);
	}
	g_list_free (contact_list);

	e_data_book_respond_get_contact_list_uids (book, opid, EDB_ERROR (SUCCESS), uids_list);

	g_slist_foreach (uids_list, (GFunc) g_free, NULL);
	g_slist_free (uids_list);
}
static void
e_book_backend_webdav_start_view (EBookBackend *backend,
                                  EDataBookView *book_view)
{
	EBookBackendWebdav        *webdav = E_BOOK_BACKEND_WEBDAV (backend);
	EBookBackendWebdavPrivate *priv   = webdav->priv;
	EBookBackendSExp *sexp;
	const gchar *query;
	GList *contacts;
	GList *l;

	sexp = e_data_book_view_get_sexp (book_view);
	query = e_book_backend_sexp_text (sexp);

	g_mutex_lock (&priv->cache_lock);
	contacts = e_book_backend_cache_get_contacts (priv->cache, query);
	g_mutex_unlock (&priv->cache_lock);

	for (l = contacts; l != NULL; l = g_list_next (l)) {
		EContact *contact = l->data;
		e_data_book_view_notify_update (book_view, contact);
		g_object_unref (contact);
	}
	g_list_free (contacts);

	/* this way the UI is notified about cached contacts immediately,
	 * and the update thread notifies about possible changes only */
	e_data_book_view_notify_complete (book_view, NULL /* Success */);

	if (e_backend_get_online (E_BACKEND (backend))) {
		WebdavBackendSearchClosure *closure
			= init_closure (book_view, E_BOOK_BACKEND_WEBDAV (backend));

		closure->thread
			= g_thread_new (NULL, book_view_thread, book_view);

		e_flag_wait (closure->running);
	}
}
static void
e_book_backend_webdav_stop_view (EBookBackend *backend,
                                 EDataBookView *book_view)
{
	WebdavBackendSearchClosure *closure;
	gboolean                    need_join;

	if (!e_backend_get_online (E_BACKEND (backend)))
		return;

	closure = get_closure (book_view);
	if (closure == NULL)
		return;

	need_join = e_flag_is_set (closure->running);
	e_flag_clear (closure->running);

	if (need_join) {
		g_thread_join (closure->thread);
		closure->thread = NULL;
	}
}
static void
e_book_backend_webdav_get_contact (EBookBackend *backend,
                                   EDataBook *book,
                                   guint32 opid,
                                   GCancellable *cancellable,
                                   const gchar *uid)
{
	EBookBackendWebdav        *webdav = E_BOOK_BACKEND_WEBDAV (backend);
	EBookBackendWebdavPrivate *priv   = webdav->priv;
	EContact                  *contact;
	gchar                      *vcard;

	if (!e_backend_get_online (E_BACKEND (backend))) {
		g_mutex_lock (&priv->cache_lock);
		contact = e_book_backend_cache_get_contact (priv->cache, uid);
		g_mutex_unlock (&priv->cache_lock);
	} else {
		contact = download_contact (webdav, uid, cancellable);
		/* update cache as we possibly have changes */
		if (contact != NULL) {
			g_mutex_lock (&priv->cache_lock);
			e_book_backend_cache_remove_contact (priv->cache, uid);
			e_book_backend_cache_add_contact (priv->cache, contact);
			g_mutex_unlock (&priv->cache_lock);
		}
	}

	if (contact == NULL) {
		e_data_book_respond_get_contact (book, opid, EDB_ERROR (CONTACT_NOT_FOUND), NULL);
		return;
	}

	vcard = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30);
	e_data_book_respond_get_contact (book, opid, EDB_ERROR (SUCCESS), vcard);
	g_free (vcard);
	g_object_unref (contact);
}
static void
e_book_backend_webdav_modify_contacts (EBookBackend *backend,
                                       EDataBook *book,
                                       guint32 opid,
                                       GCancellable *cancellable,
                                       const GSList *vcards)
{
	EBookBackendWebdav        *webdav  = E_BOOK_BACKEND_WEBDAV (backend);
	EBookBackendWebdavPrivate *priv    = webdav->priv;
	EContact                  *contact;
	GSList                     modified_contacts = {NULL,};
	const gchar                *uid;
	const gchar                *etag;
	guint status;
	gchar *status_reason = NULL;
	const gchar *vcard = vcards->data;

	if (!e_backend_get_online (E_BACKEND (backend))) {
		e_data_book_respond_create_contacts (
			book, opid,
			EDB_ERROR (REPOSITORY_OFFLINE), NULL);
		return;
	}

	/* We make the assumption that the vCard list we're passed is always exactly one element long, since we haven't specified "bulk-modifies"
	 * in our static capability list. This is because there is no clean way to roll back changes in case of an error. */
	if (vcards->next != NULL) {
		e_data_book_respond_modify_contacts (
			book, opid,
			EDB_ERROR_EX (
				NOT_SUPPORTED,
				_("The backend does not support bulk modifications")),
			NULL);
		return;
	}

	/* modify contact */
	contact = e_contact_new_from_vcard (vcard);
	status = upload_contact (webdav, contact, &status_reason, cancellable);
	if (status != 201 && status != 204) {
		g_object_unref (contact);
		if (status == 401 || status == 407) {
			e_data_book_respond_modify_contacts (book, opid, webdav_handle_auth_request (webdav), NULL);
			g_free (status_reason);
			return;
		}
		/* data changed on server while we were editing */
		if (status == 412) {
			/* too bad no special error code in evolution for this... */
			e_data_book_respond_modify_contacts (book, opid,
				e_data_book_create_error_fmt (
				E_DATA_BOOK_STATUS_OTHER_ERROR,
				_("Contact on server changed -> not modifying")),
				NULL);
			g_free (status_reason);
			return;
		}

		e_data_book_respond_modify_contacts (book, opid,
			e_data_book_create_error_fmt (
			E_DATA_BOOK_STATUS_OTHER_ERROR,
			_("Modify contact failed with HTTP status: %d (%s)"),
			status, status_reason),
			NULL);
		g_free (status_reason);
		return;
	}

	g_free (status_reason);

	uid = e_contact_get_const (contact, E_CONTACT_UID);
	g_mutex_lock (&priv->cache_lock);
	e_book_backend_cache_remove_contact (priv->cache, uid);

	etag = e_contact_get_const (contact, E_CONTACT_REV);

	/* PUT request didn't return an etag? try downloading to get one */
	if (etag == NULL || (etag[0] == 'W' && etag[1] == '/')) {
		EContact *new_contact;

		g_warning ("Server didn't return etag for modified address resource");
		new_contact = download_contact (webdav, uid, cancellable);
		if (new_contact != NULL) {
			contact = new_contact;
		}
	}
	e_book_backend_cache_add_contact (priv->cache, contact);
	g_mutex_unlock (&priv->cache_lock);

	modified_contacts.data = contact;
	e_data_book_respond_modify_contacts (book, opid, EDB_ERROR (SUCCESS), &modified_contacts);

	g_object_unref (contact);
}
Esempio n. 11
0
/* 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;

	cbhttp = E_CAL_BACKEND_HTTP (backend);
	priv = cbhttp->priv;

	/* already opened, thus can skip all this initialization */
	if (priv->opened)
		return;

	source = e_backend_get_source (E_BACKEND (backend));
	cache_dir = e_cal_backend_get_cache_dir (E_CAL_BACKEND (backend));

	extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
	webdav_extension = e_source_get_extension (source, extension_name);

	e_source_webdav_unset_temporary_ssl_trust (webdav_extension);

	if (priv->source_changed_id == 0) {
		priv->source_changed_id = g_signal_connect (
			source, "changed",
			G_CALLBACK (source_changed_cb), cbhttp);
	}

	/* 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;
		}
	}

	e_cal_backend_set_writable (E_CAL_BACKEND (backend), FALSE);

	if (e_backend_get_online (E_BACKEND (backend))) {
		gchar *certificate_pem = NULL;
		GTlsCertificateFlags certificate_errors = 0;
		const gchar *uri;

		uri = cal_backend_http_ensure_uri (cbhttp);

		opened = cal_backend_http_load (cbhttp, uri, &certificate_pem,
			&certificate_errors, cancellable, &local_error);

		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 (g_error_matches (local_error, SOUP_HTTP_ERROR, SOUP_STATUS_SSL_FAILED)) {
				reason = E_SOURCE_CREDENTIALS_REASON_SSL_FAILED;
			}

			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;

			e_backend_credentials_required_sync (E_BACKEND (cbhttp), E_SOURCE_CREDENTIALS_REASON_REJECTED,
				certificate_pem, certificate_errors, local_error, cancellable, &local_error2);

			g_clear_error (&local_error);
			local_error = local_error2;
		}

		g_free (certificate_pem);

		if (local_error != NULL)
			g_propagate_error (perror, local_error);
	}

	if (opened) {
		if (!priv->reload_timeout_id)
			priv->reload_timeout_id = e_source_refresh_add_timeout (source, NULL, http_cal_reload_cb, backend, NULL);
	}
}
static void
e_book_backend_webdav_create_contacts (EBookBackend *backend,
                                       EDataBook *book,
                                       guint32 opid,
                                       GCancellable *cancellable,
                                       const GSList *vcards)
{
	EBookBackendWebdav        *webdav = E_BOOK_BACKEND_WEBDAV (backend);
	EBookBackendWebdavPrivate *priv   = webdav->priv;
	EContact                  *contact;
	gchar                     *uid;
	guint                      status;
	gchar                     *status_reason = NULL;
	const gchar               *vcard = (const gchar *) vcards->data;
	GSList                     added_contacts = {NULL,};

	/* We make the assumption that the vCard list we're passed is always exactly one element long, since we haven't specified "bulk-adds"
	 * in our static capability list. This is because there is no clean way to roll back changes in case of an error. */
	if (vcards->next != NULL) {
		e_data_book_respond_create_contacts (
			book, opid,
			EDB_ERROR_EX (NOT_SUPPORTED,
			_("The backend does not support bulk additions")),
			NULL);
		return;
	}

	if (!e_backend_get_online (E_BACKEND (backend))) {
		e_data_book_respond_create_contacts (book, opid, EDB_ERROR (REPOSITORY_OFFLINE), NULL);
		return;
	}

	/* do 3 rand() calls to construct a unique ID... poor way but should be
	 * good enough for us */
	uid = g_strdup_printf (
		"%s%08X-%08X-%08X.vcf",
		priv->uri, rand (), rand (), rand ());

	contact = e_contact_new_from_vcard_with_uid (vcard, uid);

	/* kill revision field (might have been set by some other backend) */
	e_contact_set (contact, E_CONTACT_REV, NULL);

	status = upload_contact (webdav, contact, &status_reason, cancellable);
	if (status != 201 && status != 204) {
		g_object_unref (contact);
		if (status == 401 || status == 407) {
			e_data_book_respond_create_contacts (book, opid, webdav_handle_auth_request (webdav), NULL);
		} else {
			e_data_book_respond_create_contacts (
				book, opid,
				e_data_book_create_error_fmt (
				E_DATA_BOOK_STATUS_OTHER_ERROR,
				_("Create resource '%s' failed with HTTP status: %d (%s)"),
				uid, status, status_reason),
					NULL);
		}
		g_free (uid);
		g_free (status_reason);
		return;
	}

	g_free (status_reason);

	/* PUT request didn't return an etag? try downloading to get one */
	if (e_contact_get_const (contact, E_CONTACT_REV) == NULL) {
		const gchar *new_uid;
		EContact *new_contact;

		g_warning ("Server didn't return etag for new address resource");
		new_uid = e_contact_get_const (contact, E_CONTACT_UID);
		new_contact = download_contact (webdav, new_uid, cancellable);
		g_object_unref (contact);

		if (new_contact == NULL) {
			e_data_book_respond_create_contacts (
				book, opid,
				EDB_ERROR (OTHER_ERROR), NULL);
			g_free (uid);
			return;
		}
		contact = new_contact;
	}

	g_mutex_lock (&priv->cache_lock);
	e_book_backend_cache_add_contact (priv->cache, contact);
	g_mutex_unlock (&priv->cache_lock);

	added_contacts.data = contact;
	e_data_book_respond_create_contacts (book, opid, EDB_ERROR (SUCCESS), &added_contacts);

	g_object_unref (contact);
	g_free (uid);
}
Esempio n. 13
0
/** Check if calendar is online (i.e. network operations should be enabled).
 *
 * @param cb 3e calendar backend.
 *
 * @return TRUE if it is OK to run network communication.
 */
gboolean e_cal_backend_3e_calendar_is_online(ECalBackend3e *cb)
{
    return e_backend_get_online (E_BACKEND (cb));
//    return cb->priv->mode == CAL_MODE_REMOTE;
}
static void
e_book_backend_webdav_open (EBookBackend *backend,
                            EDataBook *book,
                            guint opid,
                            GCancellable *cancellable,
                            gboolean only_if_exists)
{
	EBookBackendWebdav        *webdav = E_BOOK_BACKEND_WEBDAV (backend);
	EBookBackendWebdavPrivate *priv   = webdav->priv;
	ESourceAuthentication     *auth_extension;
	ESourceOffline            *offline_extension;
	ESourceWebdav             *webdav_extension;
	ESource                   *source;
	const gchar               *extension_name;
	const gchar               *cache_dir;
	gchar                     *filename;
	SoupSession               *session;
	SoupURI                   *suri;
	GError                    *error = NULL;

	/* will try fetch ctag for the first time, if it fails then sets this to FALSE */
	priv->supports_getctag = TRUE;

	source = e_backend_get_source (E_BACKEND (backend));
	cache_dir = e_book_backend_get_cache_dir (backend);

	extension_name = E_SOURCE_EXTENSION_AUTHENTICATION;
	auth_extension = e_source_get_extension (source, extension_name);

	extension_name = E_SOURCE_EXTENSION_OFFLINE;
	offline_extension = e_source_get_extension (source, extension_name);

	extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND;
	webdav_extension = e_source_get_extension (source, extension_name);

	priv->marked_for_offline =
		e_source_offline_get_stay_synchronized (offline_extension);

	if (!e_backend_get_online (E_BACKEND (backend)) && !priv->marked_for_offline ) {
		e_book_backend_respond_opened (backend, book, opid, EDB_ERROR (OFFLINE_UNAVAILABLE));
		return;
	}

	suri = e_source_webdav_dup_soup_uri (webdav_extension);

	priv->uri = soup_uri_to_string (suri, FALSE);
	if (!priv->uri || !*priv->uri) {
		g_free (priv->uri);
		priv->uri = NULL;
		soup_uri_free (suri);
		e_book_backend_respond_opened (backend, book, opid, EDB_ERROR_EX (OTHER_ERROR, _("Cannot transform SoupURI to string")));
		return;
	}

	g_mutex_lock (&priv->cache_lock);

	/* make sure the priv->uri ends with a forward slash */
	if (priv->uri[strlen (priv->uri) - 1] != '/') {
		gchar *tmp = priv->uri;
		priv->uri = g_strconcat (tmp, "/", NULL);
		g_free (tmp);
	}

	if (!priv->cache) {
		filename = g_build_filename (cache_dir, "cache.xml", NULL);
		priv->cache = e_book_backend_cache_new (filename);
		g_free (filename);
	}
	g_mutex_unlock (&priv->cache_lock);

	session = soup_session_sync_new ();
	g_object_set (
		session,
		SOUP_SESSION_TIMEOUT, 90,
		SOUP_SESSION_SSL_STRICT, TRUE,
		SOUP_SESSION_SSL_USE_SYSTEM_CA_FILE, TRUE,
		NULL);

	e_source_webdav_unset_temporary_ssl_trust (webdav_extension);

	g_signal_connect (
		session, "authenticate",
		G_CALLBACK (soup_authenticate), webdav);

	priv->session = session;
	priv->proxy = e_proxy_new ();
	e_proxy_setup_proxy (priv->proxy);
	g_signal_connect (
		priv->proxy, "changed",
		G_CALLBACK (proxy_settings_changed), priv);
	proxy_settings_changed (priv->proxy, priv);
	webdav_debug_setup (priv->session);

	e_book_backend_notify_online (backend, TRUE);
	e_book_backend_notify_readonly (backend, FALSE);

	if (e_source_authentication_required (auth_extension))
		e_backend_authenticate_sync (
			E_BACKEND (backend),
			E_SOURCE_AUTHENTICATOR (backend),
			cancellable, &error);

	soup_uri_free (suri);

	/* This function frees the GError passed to it. */
	e_book_backend_respond_opened (backend, book, opid, error);
}
Esempio n. 15
0
/** Check if backend method should call sync immediately after cache
 * modification.
 *
 * @param cb 3e calendar backend.
 *
 * @return TRUE if sync is needed.
 */
gboolean e_cal_backend_3e_calendar_needs_immediate_sync(ECalBackend3e *cb)
{
    return cb->priv->sync_immediately && e_backend_get_online(E_BACKEND(cb)) && !cb->priv->last_conn_failed;
}
Esempio n. 16
0
static void
begin_retrieval_cb (GTask *task,
		    gpointer source_object,
		    gpointer task_tada,
		    GCancellable *cancellable)
{
	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"));

	backend->priv->is_loading = TRUE;

	uri = cal_backend_http_ensure_uri (backend);
	cal_backend_http_load (backend, uri, &certificate_pem, &certificate_errors, cancellable, &error);

	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;

		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;
	}

	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);
	}

	d (g_message ("Retrieval really done.\n"));
}
Esempio n. 17
0
/** Open connection to the 3e server and authenticate user.
 *
 * This function will do nothing and return TRUE if connection is already
 * opened.
 *
 * @param cb 3E calendar backend.
 * @param err Error pointer.
 *
 * @return TRUE if connection was already open, FALSE on error.
 */
gboolean e_cal_backend_3e_open_connection(ECalBackend3e *cb, GError * *err)
{
    GError *local_err = NULL;

    g_return_val_if_fail(cb != NULL, FALSE);
    g_return_val_if_fail(err == NULL || *err == NULL, FALSE);

    cb->priv->last_conn_failed = FALSE;

    /* if user tried to open connection in offline mode, close current connection
       if any and return error. this shouldn't happen, but let's check it anyway */
    if (!e_backend_get_online(E_BACKEND(cb)))
    {
        g_set_error(err, 0, -1, "Can't open 3e server connection in offline mode.");
        e_cal_backend_3e_close_connection(cb);
        return FALSE;
    }

    g_static_rec_mutex_lock(&cb->priv->conn_mutex);

    /* resolve server URI from DNS TXT if necessary */
    if (cb->priv->server_uri == NULL)
    {
        char *server_hostname = get_eee_server_hostname(cb->priv->username);
        if (server_hostname == NULL)
        {
            g_set_error(err, 0, -1, "Can't resolve server URI for username '%s'", cb->priv->username);
            goto err;
        }
        cb->priv->server_uri = g_strdup_printf("https://%s/RPC2", server_hostname);
        g_free(server_hostname);
    }

    /* check that we have all info that is necessary to create conn */
    if (cb->priv->username == NULL || cb->priv->password == NULL || cb->priv->server_uri == NULL)
    {
        g_set_error(err, 0, -1, "Connection was not setup correctly, can't open.");
        goto err;
    }

    /* create conn object */
    if (cb->priv->conn == NULL)
    {
        cb->priv->conn = xr_client_new(err);
        if (cb->priv->conn == NULL)
        {
            goto err;
        }
        cb->priv->is_open = FALSE;
    }

    if (cb->priv->is_open)
    {
        /* was already locked in this thread */
        g_static_rec_mutex_unlock(&cb->priv->conn_mutex);
        return TRUE;
    }

    if (!xr_client_open(cb->priv->conn, cb->priv->server_uri, err))
    {
        goto err;
    }

    ESClient_authenticate(cb->priv->conn, cb->priv->username, cb->priv->password, &local_err);
    if (local_err)
    {
        g_propagate_error(err, local_err);
        xr_client_close(cb->priv->conn);
        goto err;
    }

    cb->priv->is_open = TRUE;

    return TRUE;

err:
    cb->priv->last_conn_failed = TRUE;
    g_static_rec_mutex_unlock(&cb->priv->conn_mutex);
    return FALSE;
}