/*
* e-mail-config-auth-check.c
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) version 3.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with the program; if not, see <http://www.gnu.org/licenses/>
*
*/
#include <config.h>
#include <glib/gi18n-lib.h>
#include <libevolution-utils/e-alert.h>
#include <e-util/e-mktemp.h>
#include <misc/e-auth-combo-box.h>
#include <mail/e-mail-config-service-page.h>
#include "e-mail-ui-session.h"
#include "e-mail-config-auth-check.h"
#define E_MAIL_CONFIG_AUTH_CHECK_GET_PRIVATE(obj) \
(G_TYPE_INSTANCE_GET_PRIVATE \
((obj), E_TYPE_MAIL_CONFIG_AUTH_CHECK, EMailConfigAuthCheckPrivate))
typedef struct _AsyncContext AsyncContext;
struct _EMailConfigAuthCheckPrivate {
EMailConfigServiceBackend *backend;
gchar *active_mechanism;
GtkWidget *combo_box; /* not referenced */
};
struct _AsyncContext {
EMailConfigAuthCheck *auth_check;
CamelSession *temporary_session;
EActivity *activity;
};
enum {
PROP_0,
PROP_ACTIVE_MECHANISM,
PROP_BACKEND
};
G_DEFINE_TYPE (
EMailConfigAuthCheck,
e_mail_config_auth_check,
GTK_TYPE_BOX)
static void
async_context_free (AsyncContext *async_context)
{
if (async_context->auth_check != NULL)
g_object_unref (async_context->auth_check);
if (async_context->temporary_session != NULL)
g_object_unref (async_context->temporary_session);
if (async_context->activity != NULL)
g_object_unref (async_context->activity);
g_slice_free (AsyncContext, async_context);
}
static void
mail_config_auth_check_update_done_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
AsyncContext *async_context = user_data;
EMailConfigAuthCheck *auth_check;
EAlertSink *alert_sink;
GList *available_authtypes;
GError *error = NULL;
auth_check = async_context->auth_check;
alert_sink = e_activity_get_alert_sink (async_context->activity);
available_authtypes = camel_service_query_auth_types_finish (
CAMEL_SERVICE (source_object), result, &error);
if (e_activity_handle_cancellation (async_context->activity, error)) {
g_warn_if_fail (available_authtypes == NULL);
g_error_free (error);
} else if (error != NULL) {
g_warn_if_fail (available_authtypes == NULL);
e_alert_submit (
alert_sink,
"mail:checking-service-error",
error->message, NULL);
g_error_free (error);
} else {
e_auth_combo_box_update_available (
E_AUTH_COMBO_BOX (auth_check->priv->combo_box),
available_authtypes);
g_list_free (available_authtypes);
}
gtk_widget_set_sensitive (GTK_WIDGET (auth_check), TRUE);
async_context_free (async_context);
}
static void
mail_config_auth_check_update (EMailConfigAuthCheck *auth_check)
{
EActivity *activity;
EMailConfigServicePage *page;
EMailConfigServiceBackend *backend;
EMailConfigServicePageClass *page_class;
EMailConfigServiceBackendClass *backend_class;
CamelService *service;
CamelSession *session;
CamelSettings *settings;
GCancellable *cancellable;
AsyncContext *async_context;
gchar *temp_dir;
GError *error = NULL;
backend = e_mail_config_auth_check_get_backend (auth_check);
page = e_mail_config_service_backend_get_page (backend);
settings = e_mail_config_service_backend_get_settings (backend);
page_class = E_MAIL_CONFIG_SERVICE_PAGE_GET_CLASS (page);
backend_class = E_MAIL_CONFIG_SERVICE_BACKEND_GET_CLASS (backend);
temp_dir = e_mkdtemp ("evolution-auth-check-XXXXXX");
/* Create a temporary session for our temporary service.
* Use the same temporary directory for "user-data-dir" and
* "user-cache-dir". For our purposes it shouldn't matter. */
session = g_object_new (
CAMEL_TYPE_SESSION,
"user-data-dir", temp_dir,
"user-cache-dir", temp_dir,
NULL);
/* to be able to answer for invalid/self-signed server certificates */
CAMEL_SESSION_GET_CLASS (session)->alert_user = e_mail_ui_session_alert_user;
service = camel_session_add_service (
session, "fake-uid",
backend_class->backend_name,
page_class->provider_type, &error);
g_free (temp_dir);
if (error != NULL) {
g_warn_if_fail (service == NULL);
e_alert_submit (
E_ALERT_SINK (page),
"mail:checking-service-error",
error->message, NULL);
g_error_free (error);
return;
}
g_return_if_fail (CAMEL_IS_SERVICE (service));
camel_service_set_settings (service, settings);
activity = e_mail_config_activity_page_new_activity (
E_MAIL_CONFIG_ACTIVITY_PAGE (page));
cancellable = e_activity_get_cancellable (activity);
gtk_widget_set_sensitive (GTK_WIDGET (auth_check), FALSE);
async_context = g_slice_new (AsyncContext);
async_context->auth_check = g_object_ref (auth_check);
async_context->temporary_session = session; /* takes ownership */
async_context->activity = activity; /* takes ownership */
camel_service_query_auth_types (
service, G_PRIORITY_DEFAULT, cancellable,
mail_config_auth_check_update_done_cb, async_context);
g_object_unref (service);
}
static void
mail_config_auth_check_clicked_cb (GtkButton *button,
EMailConfigAuthCheck *auth_check)
{
mail_config_auth_check_update (auth_check);
}
static void
mail_config_auth_check_init_mechanism (EMailConfigAuthCheck *auth_check)
{
EMailConfigServiceBackend *backend;
CamelProvider *provider;
CamelSettings *settings;
const gchar *auth_mechanism = NULL;
/* Pick an initial active mechanism name by examining both
* the corresponding CamelNetworkSettings and CamelProvider. */
backend = e_mail_config_auth_check_get_backend (auth_check);
provider = e_mail_config_service_backend_get_provider (backend);
settings = e_mail_config_service_backend_get_settings (backend);
g_return_if_fail (CAMEL_IS_NETWORK_SETTINGS (settings));
auth_mechanism =
camel_network_settings_get_auth_mechanism (
CAMEL_NETWORK_SETTINGS (settings));
/* If CamelNetworkSettings does not have a mechanism name set,
* choose from the CamelProvider's list of supported mechanisms. */
if (auth_mechanism == NULL && provider != NULL) {
if (provider->authtypes != NULL) {
CamelServiceAuthType *auth_type;
auth_type = provider->authtypes->data;
auth_mechanism = auth_type->authproto;
}
}
if (auth_mechanism != NULL)
e_mail_config_auth_check_set_active_mechanism (
auth_check, auth_mechanism);
}
static void
mail_config_auth_check_set_backend (EMailConfigAuthCheck *auth_check,
EMailConfigServiceBackend *backend)
{
g_return_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend));
g_return_if_fail (auth_check->priv->backend == NULL);
auth_check->priv->backend = g_object_ref (backend);
}
static void
mail_config_auth_check_set_property (GObject *object,
guint property_id,
const GValue *value,
GParamSpec *pspec)
{
switch (property_id) {
case PROP_ACTIVE_MECHANISM:
e_mail_config_auth_check_set_active_mechanism (
E_MAIL_CONFIG_AUTH_CHECK (object),
g_value_get_string (value));
return;
case PROP_BACKEND:
mail_config_auth_check_set_backend (
E_MAIL_CONFIG_AUTH_CHECK (object),
g_value_get_object (value));
return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
static void
mail_config_auth_check_get_property (GObject *object,
guint property_id,
GValue *value,
GParamSpec *pspec)
{
switch (property_id) {
case PROP_ACTIVE_MECHANISM:
g_value_set_string (
value,
e_mail_config_auth_check_get_active_mechanism (
E_MAIL_CONFIG_AUTH_CHECK (object)));
return;
case PROP_BACKEND:
g_value_set_object (
value,
e_mail_config_auth_check_get_backend (
E_MAIL_CONFIG_AUTH_CHECK (object)));
return;
}
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
static void
mail_config_auth_check_dispose (GObject *object)
{
EMailConfigAuthCheckPrivate *priv;
priv = E_MAIL_CONFIG_AUTH_CHECK_GET_PRIVATE (object);
if (priv->backend != NULL) {
g_object_unref (priv->backend);
priv->backend = NULL;
}
/* Chain up to parent's dispose() method. */
G_OBJECT_CLASS (e_mail_config_auth_check_parent_class)->
dispose (object);
}
static void
mail_config_auth_check_finalize (GObject *object)
{
EMailConfigAuthCheckPrivate *priv;
priv = E_MAIL_CONFIG_AUTH_CHECK_GET_PRIVATE (object);
g_free (priv->active_mechanism);
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (e_mail_config_auth_check_parent_class)->
finalize (object);
}
static void
mail_config_auth_check_constructed (GObject *object)
{
EMailConfigAuthCheck *auth_check;
EMailConfigServiceBackend *backend;
CamelProvider *provider;
GtkWidget *widget;
const gchar *text;
/* Chain up to parent's constructed() method. */
G_OBJECT_CLASS (e_mail_config_auth_check_parent_class)->
constructed (object);
auth_check = E_MAIL_CONFIG_AUTH_CHECK (object);
backend = e_mail_config_auth_check_get_backend (auth_check);
provider = e_mail_config_service_backend_get_provider (backend);
widget = e_auth_combo_box_new ();
e_auth_combo_box_set_provider (E_AUTH_COMBO_BOX (widget), provider);
gtk_box_pack_start (GTK_BOX (object), widget, FALSE, FALSE, 0);
auth_check->priv->combo_box = widget; /* do not reference */
gtk_widget_show (widget);
g_object_bind_property (
widget, "active-id",
auth_check, "active-mechanism",
G_BINDING_BIDIRECTIONAL |
G_BINDING_SYNC_CREATE);
text = _("Check for Supported Types");
widget = gtk_button_new_with_label (text);
gtk_box_pack_start (GTK_BOX (object), widget, FALSE, FALSE, 0);
gtk_widget_show (widget);
g_signal_connect (
widget, "clicked",
G_CALLBACK (mail_config_auth_check_clicked_cb),
auth_check);
mail_config_auth_check_init_mechanism (auth_check);
}
static void
e_mail_config_auth_check_class_init (EMailConfigAuthCheckClass *class)
{
GObjectClass *object_class;
g_type_class_add_private (class, sizeof (EMailConfigAuthCheckPrivate));
object_class = G_OBJECT_CLASS (class);
object_class->set_property = mail_config_auth_check_set_property;
object_class->get_property = mail_config_auth_check_get_property;
object_class->dispose = mail_config_auth_check_dispose;
object_class->finalize = mail_config_auth_check_finalize;
object_class->constructed = mail_config_auth_check_constructed;
g_object_class_install_property (
object_class,
PROP_ACTIVE_MECHANISM,
g_param_spec_string (
"active-mechanism",
"Active Mechanism",
"Active authentication mechanism",
NULL,
G_PARAM_READWRITE |
G_PARAM_STATIC_STRINGS));
g_object_class_install_property (
object_class,
PROP_BACKEND,
g_param_spec_object (
"backend",
"Backend",
"Mail configuration backend",
E_TYPE_MAIL_CONFIG_SERVICE_BACKEND,
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
}
static void
e_mail_config_auth_check_init (EMailConfigAuthCheck *auth_check)
{
auth_check->priv = E_MAIL_CONFIG_AUTH_CHECK_GET_PRIVATE (auth_check);
gtk_orientable_set_orientation (
GTK_ORIENTABLE (auth_check),
GTK_ORIENTATION_HORIZONTAL);
gtk_box_set_spacing (GTK_BOX (auth_check), 6);
}
GtkWidget *
e_mail_config_auth_check_new (EMailConfigServiceBackend *backend)
{
g_return_val_if_fail (E_IS_MAIL_CONFIG_SERVICE_BACKEND (backend), NULL);
return g_object_new (
E_TYPE_MAIL_CONFIG_AUTH_CHECK,
"backend", backend, NULL);
}
EMailConfigServiceBackend *
e_mail_config_auth_check_get_backend (EMailConfigAuthCheck *auth_check)
{
g_return_val_if_fail (E_IS_MAIL_CONFIG_AUTH_CHECK (auth_check), NULL);
return auth_check->priv->backend;
}
const gchar *
e_mail_config_auth_check_get_active_mechanism (EMailConfigAuthCheck *auth_check)
{
g_return_val_if_fail (E_IS_MAIL_CONFIG_AUTH_CHECK (auth_check), NULL);
return auth_check->priv->active_mechanism;
}
void
e_mail_config_auth_check_set_active_mechanism (EMailConfigAuthCheck *auth_check,
const gchar *active_mechanism)
{
g_return_if_fail (E_IS_MAIL_CONFIG_AUTH_CHECK (auth_check));
if (g_strcmp0 (auth_check->priv->active_mechanism, active_mechanism) == 0)
return;
g_free (auth_check->priv->active_mechanism);
auth_check->priv->active_mechanism = g_strdup (active_mechanism);
g_object_notify (G_OBJECT (auth_check), "active-mechanism");
}