/* 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); }
/** Load calendar name, owner and permission from the ESource. * * @param cb 3e calendar backend. * * @return TRUE on success, FALSE otherwise. */ gboolean e_cal_backend_3e_calendar_info_load(ECalBackend3e *cb) { ESource *source; const char *immediate_sync; source = e_backend_get_source(E_BACKEND(cb)); immediate_sync = e_source_get_property(source, "eee-immediate-sync"); g_free(cb->priv->calname); g_free(cb->priv->owner); g_free(cb->priv->perm); cb->priv->calname = g_strdup(e_source_get_property(source, "eee-calname")); cb->priv->owner = g_strdup(e_source_get_property(source, "eee-owner")); cb->priv->perm = g_strdup(e_source_get_property(source, "eee-perm")); cb->priv->sync_immediately = (immediate_sync == NULL || !g_strcmp0(immediate_sync, "1")); g_free(cb->priv->calspec); cb->priv->calspec = g_strdup_printf("%s:%s", cb->priv->owner, cb->priv->calname); if (cb->priv->calname == NULL || cb->priv->owner == NULL) { return FALSE; } return TRUE; }
static void ebbm_contacts_open (EBookBackendMAPI *ebma, GCancellable *cancellable, gboolean only_if_exists, GError **perror) { ESource *source = e_backend_get_source (E_BACKEND (ebma)); ESourceMapiFolder *ext_mapi_folder; EBookBackendMAPIContactsPrivate *priv = ((EBookBackendMAPIContacts *) ebma)->priv; GError *err = NULL; if (e_book_backend_is_opened (E_BOOK_BACKEND (ebma))) { if (E_BOOK_BACKEND_MAPI_CLASS (e_book_backend_mapi_contacts_parent_class)->op_open) E_BOOK_BACKEND_MAPI_CLASS (e_book_backend_mapi_contacts_parent_class)->op_open (ebma, cancellable, only_if_exists, perror); return; } ext_mapi_folder = e_source_get_extension (source, E_SOURCE_EXTENSION_MAPI_FOLDER); priv->fid = e_source_mapi_folder_get_id (ext_mapi_folder); priv->is_public_folder = e_source_mapi_folder_is_public (ext_mapi_folder); priv->foreign_username = e_source_mapi_folder_dup_foreign_username (ext_mapi_folder); if (priv->foreign_username && !*priv->foreign_username) { g_free (priv->foreign_username); priv->foreign_username = NULL; } /* Chain up to parent's op_load_source() method. */ if (E_BOOK_BACKEND_MAPI_CLASS (e_book_backend_mapi_contacts_parent_class)->op_open) E_BOOK_BACKEND_MAPI_CLASS (e_book_backend_mapi_contacts_parent_class)->op_open (ebma, cancellable, only_if_exists, &err); if (err) g_propagate_error (perror, err); }
static const gchar * cal_backend_http_ensure_uri (ECalBackendHttp *backend) { 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; source = e_backend_get_source (E_BACKEND (backend)); extension_name = E_SOURCE_EXTENSION_SECURITY; security_extension = e_source_get_extension (source, extension_name); extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND; webdav_extension = e_source_get_extension (source, extension_name); 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); g_free (uri_string); return backend->priv->uri; }
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); }
static ESourceAuthenticationResult book_backend_webdav_try_password_sync (ESourceAuthenticator *authenticator, const GString *password, GCancellable *cancellable, GError **error) { EBookBackendWebdav *webdav = E_BOOK_BACKEND_WEBDAV (authenticator); ESourceAuthentication *auth_extension; ESourceAuthenticationResult result; ESource *source; SoupMessage *message; const gchar *extension_name; source = e_backend_get_source (E_BACKEND (authenticator)); extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; auth_extension = e_source_get_extension (source, extension_name); webdav->priv->username = e_source_authentication_dup_user (auth_extension); webdav->priv->password = g_strdup (password->str); /* Send a PROPFIND to test whether user/password is correct. */ message = send_propfind (webdav, cancellable); switch (message->status_code) { case SOUP_STATUS_OK: case SOUP_STATUS_MULTI_STATUS: result = E_SOURCE_AUTHENTICATION_ACCEPTED; break; case SOUP_STATUS_UNAUTHORIZED: case SOUP_STATUS_PROXY_UNAUTHORIZED: /* XXX really? */ g_free (webdav->priv->username); webdav->priv->username = NULL; g_free (webdav->priv->password); webdav->priv->password = NULL; result = E_SOURCE_AUTHENTICATION_REJECTED; break; default: g_set_error ( error, SOUP_HTTP_ERROR, message->status_code, "%s", message->reason_phrase); result = E_SOURCE_AUTHENTICATION_ERROR; break; } g_object_unref (message); return result; }
static void outlook_backend_child_added (ECollectionBackend *backend, ESource *child_source) { ESource *collection_source; const gchar *extension_name; gboolean is_mail = FALSE; collection_source = e_backend_get_source (E_BACKEND (backend)); extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; is_mail |= e_source_has_extension (child_source, extension_name); extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY; is_mail |= e_source_has_extension (child_source, extension_name); extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT; is_mail |= e_source_has_extension (child_source, extension_name); /* Synchronize mail-related user with the collection identity. */ extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; if (is_mail && e_source_has_extension (child_source, extension_name)) { ESourceAuthentication *auth_child_extension; ESourceCollection *collection_extension; const gchar *collection_identity; const gchar *auth_child_user; extension_name = E_SOURCE_EXTENSION_COLLECTION; collection_extension = e_source_get_extension ( collection_source, extension_name); collection_identity = e_source_collection_get_identity ( collection_extension); extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; auth_child_extension = e_source_get_extension ( child_source, extension_name); auth_child_user = e_source_authentication_get_user ( auth_child_extension); /* XXX Do not override an existing user name setting. * The IMAP or (especially) SMTP configuration may * have been modified to use a non-Outlook server. */ if (auth_child_user == NULL) e_source_authentication_set_user ( auth_child_extension, collection_identity); } /* Chain up to parent's child_added() method. */ E_COLLECTION_BACKEND_CLASS (e_outlook_backend_parent_class)-> child_added (backend, child_source); }
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); }
/* 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 google_backend_add_tasks (ECollectionBackend *backend) { ESource *source; ESource *collection_source; ESourceRegistryServer *server; ESourceExtension *extension; ESourceCollection *collection_extension; const gchar *backend_name; const gchar *extension_name; const gchar *resource_id; collection_source = e_backend_get_source (E_BACKEND (backend)); resource_id = GOOGLE_TASKS_RESOURCE_ID; source = e_collection_backend_new_child (backend, resource_id); e_source_set_display_name (source, _("Tasks")); collection_extension = e_source_get_extension ( collection_source, E_SOURCE_EXTENSION_COLLECTION); /* Configure the tasks source. */ backend_name = GOOGLE_TASKS_BACKEND_NAME; extension_name = E_SOURCE_EXTENSION_TASK_LIST; extension = e_source_get_extension (source, extension_name); e_source_backend_set_backend_name ( E_SOURCE_BACKEND (extension), backend_name); extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; extension = e_source_get_extension (source, extension_name); g_object_bind_property ( collection_extension, "identity", extension, "user", G_BINDING_SYNC_CREATE); extension_name = E_SOURCE_EXTENSION_SECURITY; extension = e_source_get_extension (source, extension_name); e_source_security_set_secure ( E_SOURCE_SECURITY (extension), TRUE); server = e_collection_backend_ref_server (backend); e_source_registry_server_add_source (server, source); g_object_unref (server); g_object_unref (source); }
static void google_backend_add_contacts (ECollectionBackend *backend) { ESource *source; ESource *collection_source; ESourceRegistryServer *server; ESourceExtension *extension; ESourceCollection *collection_extension; const gchar *backend_name; const gchar *extension_name; const gchar *resource_id; collection_source = e_backend_get_source (E_BACKEND (backend)); resource_id = GOOGLE_CONTACTS_RESOURCE_ID; source = e_collection_backend_new_child (backend, resource_id); e_source_set_display_name (source, _("Contacts")); /* Add the address book source to the collection. */ collection_extension = e_source_get_extension ( collection_source, E_SOURCE_EXTENSION_COLLECTION); /* Configure the address book source. */ backend_name = GOOGLE_CONTACTS_BACKEND_NAME; extension_name = E_SOURCE_EXTENSION_ADDRESS_BOOK; extension = e_source_get_extension (source, extension_name); e_source_backend_set_backend_name ( E_SOURCE_BACKEND (extension), backend_name); extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; extension = e_source_get_extension (source, extension_name); e_source_authentication_set_host ( E_SOURCE_AUTHENTICATION (extension), GOOGLE_CONTACTS_HOST); g_object_bind_property ( collection_extension, "identity", extension, "user", G_BINDING_SYNC_CREATE); server = e_collection_backend_ref_server (backend); e_source_registry_server_add_source (server, source); g_object_unref (server); g_object_unref (source); }
static void eee_backend_child_added (ECollectionBackend *backend, ESource *child_source) { ESource *collection_source; const gchar *extension_name; gboolean is_mail = FALSE; collection_source = e_backend_get_source (E_BACKEND (backend)); extension_name = E_SOURCE_EXTENSION_MAIL_ACCOUNT; is_mail |= e_source_has_extension (child_source, extension_name); extension_name = E_SOURCE_EXTENSION_MAIL_IDENTITY; is_mail |= e_source_has_extension (child_source, extension_name); extension_name = E_SOURCE_EXTENSION_MAIL_TRANSPORT; is_mail |= e_source_has_extension (child_source, extension_name); /* Synchronize mail-related display names with the collection. */ if (is_mail) g_object_bind_property ( collection_source, "display-name", child_source, "display-name", G_BINDING_SYNC_CREATE); /* Synchronize mail-related user with the collection identity. */ extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; if (is_mail && e_source_has_extension (child_source, extension_name)) { ESourceAuthentication *auth_child_extension; ESourceCollection *collection_extension; extension_name = E_SOURCE_EXTENSION_COLLECTION; collection_extension = e_source_get_extension ( collection_source, extension_name); extension_name = E_SOURCE_EXTENSION_AUTHENTICATION; auth_child_extension = e_source_get_extension ( child_source, extension_name); g_object_bind_property ( collection_extension, "identity", auth_child_extension, "user", G_BINDING_SYNC_CREATE); } /* Chain up to parent's child_added() method. */ E_COLLECTION_BACKEND_CLASS (e_eee_backend_parent_class)-> child_added (backend, child_source); }
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); } }
static void ebbm_contacts_connection_status_changed (EBookBackendMAPI *ebma, gboolean is_online) { ESource *source; ESourceMapiFolder *ext_mapi_folder; e_book_backend_set_writable (E_BOOK_BACKEND (ebma), is_online); if (!is_online) return; source = e_backend_get_source (E_BACKEND (ebma)); ext_mapi_folder = e_source_get_extension (source, E_SOURCE_EXTENSION_MAPI_FOLDER); if (e_source_mapi_folder_get_server_notification (ext_mapi_folder)) { EMapiConnection *conn; mapi_object_t obj_folder; gboolean status; GError *mapi_error = NULL; e_book_backend_mapi_lock_connection (ebma); conn = e_book_backend_mapi_get_connection (ebma, NULL, NULL); if (!conn) { e_book_backend_mapi_unlock_connection (ebma); return; } status = ebbm_contacts_open_folder (E_BOOK_BACKEND_MAPI_CONTACTS (ebma), conn, &obj_folder, NULL, &mapi_error); if (status) { e_mapi_connection_enable_notifications (conn, &obj_folder, fnevObjectCreated | fnevObjectModified | fnevObjectDeleted | fnevObjectMoved | fnevObjectCopied, NULL, &mapi_error); e_mapi_connection_close_folder (conn, &obj_folder, NULL, &mapi_error); } e_book_backend_mapi_maybe_disconnect (ebma, mapi_error); g_clear_error (&mapi_error); g_signal_connect (conn, "server-notification", G_CALLBACK (ebbmc_server_notification_cb), ebma); e_book_backend_mapi_unlock_connection (ebma); } }
/** 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 EBackend * subprocess_cal_factory_ref_backend (ESourceRegistry *registry, ESource *source, const gchar *backend_factory_type_name) { ECalBackend *backend; ECalBackendFactoryClass *backend_factory_class; GType backend_factory_type; backend_factory_type = g_type_from_name (backend_factory_type_name); backend_factory_class = g_type_class_ref (backend_factory_type); backend = g_object_new ( backend_factory_class->backend_type, "kind", backend_factory_class->component_kind, "registry", registry, "source", source, NULL); return E_BACKEND (backend); }
static guint send_and_handle_ssl (EBookBackendWebdav *webdav, SoupMessage *message, GCancellable *cancellable) { guint status_code; status_code = soup_session_send_message (webdav->priv->session, message); if (status_code == SOUP_STATUS_SSL_FAILED) { ESource *source; ESourceWebdav *extension; ESourceRegistry *registry; EBackend *backend; ETrustPromptResponse response; ENamedParameters *parameters; backend = E_BACKEND (webdav); source = e_backend_get_source (backend); registry = e_book_backend_get_registry (E_BOOK_BACKEND (backend)); extension = e_source_get_extension (source, E_SOURCE_EXTENSION_WEBDAV_BACKEND); parameters = e_named_parameters_new (); response = e_source_webdav_prepare_ssl_trust_prompt (extension, message, registry, parameters); if (response == E_TRUST_PROMPT_RESPONSE_UNKNOWN) { response = e_backend_trust_prompt_sync (backend, parameters, cancellable, NULL); if (response != E_TRUST_PROMPT_RESPONSE_UNKNOWN) e_source_webdav_store_ssl_trust_prompt (extension, message, response); } e_named_parameters_free (parameters); if (response == E_TRUST_PROMPT_RESPONSE_ACCEPT || response == E_TRUST_PROMPT_RESPONSE_ACCEPT_TEMPORARILY) { g_object_set (webdav->priv->session, SOUP_SESSION_SSL_STRICT, FALSE, NULL); status_code = soup_session_send_message (webdav->priv->session, message); } } return status_code; }
static void e_cal_backend_http_refresh (ECalBackendSync *backend, EDataCal *cal, GCancellable *cancellable, GError **perror) { ECalBackendHttp *cbhttp; ECalBackendHttpPrivate *priv; ESource *source; cbhttp = E_CAL_BACKEND_HTTP (backend); priv = cbhttp->priv; if (!priv->opened || priv->is_loading) return; source = e_backend_get_source (E_BACKEND (cbhttp)); g_return_if_fail (source != NULL); e_source_refresh_force_timeout (source); }
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 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); }
/** Setup 3e server connection information. * * @param cb 3e calendar backend. * @param username Username used for authentication. * @param password Password. * @param err Error pointer. */ gboolean e_cal_backend_3e_setup_connection(ECalBackend3e *cb, const char *username, const char *password) { ESource *source; g_return_val_if_fail(cb != NULL, FALSE); g_return_val_if_fail(username != NULL, FALSE); g_return_val_if_fail(password != NULL, FALSE); source = e_backend_get_source(E_BACKEND(cb)); g_free(cb->priv->username); g_free(cb->priv->password); g_free(cb->priv->server_uri); cb->priv->server_uri = NULL; if (e_source_get_property(source, "eee-server")) { cb->priv->server_uri = g_strdup_printf("https://%s/RPC2", e_source_get_property(source, "eee-server")); } cb->priv->username = g_strdup(username); cb->priv->password = g_strdup(password); return TRUE; }
/** 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; }
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); }
/** 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; }
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); }
static guint upload_contact (EBookBackendWebdav *webdav, EContact *contact, gchar **reason, GCancellable *cancellable) { ESource *source; ESourceWebdav *webdav_extension; SoupMessage *message; gchar *uri; gchar *etag; const gchar *new_etag, *redir_uri; gchar *request; guint status; gboolean avoid_ifmatch; const gchar *extension_name; source = e_backend_get_source (E_BACKEND (webdav)); extension_name = E_SOURCE_EXTENSION_WEBDAV_BACKEND; webdav_extension = e_source_get_extension (source, extension_name); source = e_backend_get_source (E_BACKEND (webdav)); uri = e_contact_get (contact, E_CONTACT_UID); if (uri == NULL) { g_warning ("can't upload contact without UID"); return 400; } message = soup_message_new (SOUP_METHOD_PUT, uri); soup_message_headers_append (message->request_headers, "User-Agent", USERAGENT); soup_message_headers_append (message->request_headers, "Connection", "close"); avoid_ifmatch = e_source_webdav_get_avoid_ifmatch (webdav_extension); /* some servers (like apache < 2.2.8) don't handle If-Match, correctly so * we can leave it out */ if (!avoid_ifmatch) { /* only override if etag is still the same on the server */ etag = e_contact_get (contact, E_CONTACT_REV); if (etag == NULL) { soup_message_headers_append ( message->request_headers, "If-None-Match", "*"); } else if (etag[0] == 'W' && etag[1] == '/') { g_warning ("we only have a weak ETag, don't use If-Match synchronisation"); } else { soup_message_headers_append ( message->request_headers, "If-Match", etag); g_free (etag); } } request = e_vcard_to_string (E_VCARD (contact), EVC_FORMAT_VCARD_30); soup_message_set_request ( message, "text/vcard", SOUP_MEMORY_TEMPORARY, request, strlen (request)); status = send_and_handle_ssl (webdav, message, cancellable); new_etag = soup_message_headers_get_list (message->response_headers, "ETag"); redir_uri = soup_message_headers_get_list (message->response_headers, "Location"); /* set UID and REV fields */ e_contact_set (contact, E_CONTACT_REV, (gconstpointer) new_etag); if (redir_uri && *redir_uri) { if (!strstr (redir_uri, "://")) { /* it's a relative URI */ SoupURI *suri = soup_uri_new (uri); gchar *full_uri; soup_uri_set_path (suri, redir_uri); full_uri = soup_uri_to_string (suri, TRUE); e_contact_set (contact, E_CONTACT_UID, full_uri); g_free (full_uri); soup_uri_free (suri); } else { e_contact_set (contact, E_CONTACT_UID, redir_uri); } } else { e_contact_set (contact, E_CONTACT_UID, uri); } if (reason) { *reason = g_strdup (message->reason_phrase && *message->reason_phrase ? message->reason_phrase : (soup_status_get_phrase (message->status_code) ? soup_status_get_phrase (message->status_code) : _("Unknown error"))); } g_object_unref (message); g_free (request); g_free (uri); return status; }
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); }