I#1637 - EMailAutoconfig: Autoconfig with Exchange accounts

Let the EMailAutoconfig gather unknown types and pass them to anyone
listening to process those known to it.

Closes https://gitlab.gnome.org/GNOME/evolution/-/issues/1637
This commit is contained in:
Milan Crha
2021-09-23 12:39:03 +02:00
parent b92acd6106
commit c99f1c8c7b

View File

@ -103,11 +103,15 @@ struct _EMailAutoconfigPrivate {
EMailAutoconfigResult imap_result;
EMailAutoconfigResult pop3_result;
EMailAutoconfigResult smtp_result;
EMailAutoconfigResult custom_result;
GHashTable *custom_types; /* gchar *type ~> ENamedParameters *params */
};
struct _ParserClosure {
EMailAutoconfig *autoconfig;
EMailAutoconfigResult *result;
gchar *current_type;
ENamedParameters *custom_params;
};
enum {
@ -117,19 +121,33 @@ enum {
PROP_USE_DOMAIN
};
enum {
PROCESS_CUSTOM_TYPES,
LAST_SIGNAL
};
static guint signals[LAST_SIGNAL];
/* Forward Declarations */
static void e_mail_autoconfig_initable_init (GInitableIface *iface);
/* By default, the GAsyncInitable interface calls GInitable.init()
* from a separate thread, so we only have to override GInitable. */
G_DEFINE_TYPE_WITH_CODE (
EMailAutoconfig,
e_mail_autoconfig,
G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (
G_TYPE_INITABLE, e_mail_autoconfig_initable_init)
G_IMPLEMENT_INTERFACE (
G_TYPE_ASYNC_INITABLE, NULL))
G_DEFINE_TYPE_WITH_CODE (EMailAutoconfig, e_mail_autoconfig, G_TYPE_OBJECT,
G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, e_mail_autoconfig_initable_init)
G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, NULL)
G_IMPLEMENT_INTERFACE (E_TYPE_EXTENSIBLE, NULL))
static void
e_mail_config_result_clear (EMailAutoconfigResult *result)
{
if (!result)
return;
g_clear_pointer (&result->user, g_free);
g_clear_pointer (&result->host, g_free);
g_clear_pointer (&result->auth_mechanism, g_free);
}
static void
mail_autoconfig_parse_start_element (GMarkupParseContext *context,
@ -167,6 +185,16 @@ mail_autoconfig_parse_start_element (GMarkupParseContext *context,
closure->result = &priv->pop3_result;
if (g_strcmp0 (type, "smtp") == 0)
closure->result = &priv->smtp_result;
if (type != NULL && closure->result == NULL) {
g_return_if_fail (closure->current_type == NULL);
g_return_if_fail (closure->custom_params == NULL);
closure->current_type = g_strdup (type);
closure->custom_params = e_named_parameters_new ();
e_named_parameters_set (closure->custom_params, "kind", element_name);
}
}
}
@ -183,9 +211,23 @@ mail_autoconfig_parse_end_element (GMarkupParseContext *context,
is_incoming_server = g_str_equal (element_name, "incomingServer");
is_outgoing_server = g_str_equal (element_name, "outgoingServer");
if (is_incoming_server || is_outgoing_server)
if (is_incoming_server || is_outgoing_server) {
if (closure->custom_params && e_named_parameters_count (closure->custom_params) > 1) {
if (!closure->autoconfig->priv->custom_types)
closure->autoconfig->priv->custom_types =
g_hash_table_new_full (g_str_hash, g_str_equal, g_free, (GDestroyNotify) e_named_parameters_free);
g_hash_table_insert (closure->autoconfig->priv->custom_types, closure->current_type, closure->custom_params);
closure->current_type = NULL;
closure->custom_params = NULL;
}
g_clear_pointer (&closure->current_type, g_free);
g_clear_pointer (&closure->custom_params, e_named_parameters_free);
closure->result = NULL;
}
}
/* Returns NULL when not being there */
static gchar *
@ -239,7 +281,7 @@ mail_autoconfig_parse_text (GMarkupParseContext *context,
priv = closure->autoconfig->priv;
if (closure->result == NULL)
if (closure->result == NULL && closure->custom_params == NULL)
return;
to_free = mail_autoconfig_replace_case_insensitive (in_text, FAKE_EVOLUTION_USER_STRING, priv->email_local_part);
@ -300,35 +342,58 @@ mail_autoconfig_parse_text (GMarkupParseContext *context,
element_name = g_markup_parse_context_get_element (context);
if (g_str_equal (element_name, "hostname")) {
if (closure->custom_params) {
e_named_parameters_set (closure->custom_params, "host", string->str);
} else {
closure->result->host = g_strdup (string->str);
closure->result->set = TRUE;
}
} else if (g_str_equal (element_name, "username")) {
if (closure->custom_params) {
e_named_parameters_set (closure->custom_params, "user", string->str);
} else {
closure->result->user = g_strdup (string->str);
closure->result->set = TRUE;
}
} else if (g_str_equal (element_name, "port")) {
if (closure->custom_params) {
e_named_parameters_set (closure->custom_params, "port", string->str);
} else {
glong port = strtol (string->str, NULL, 10);
if (port == CLAMP (port, 1, G_MAXUINT16)) {
closure->result->port = (guint16) port;
closure->result->set = TRUE;
}
} else if (g_str_equal (element_name, "socketType")) {
if (g_str_equal (string->str, "plain")) {
closure->result->security_method =
CAMEL_NETWORK_SECURITY_METHOD_NONE;
closure->result->set = TRUE;
} else if (g_str_equal (string->str, "SSL")) {
closure->result->security_method =
CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT;
closure->result->set = TRUE;
} else if (g_str_equal (string->str, "STARTTLS")) {
closure->result->security_method =
CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT;
closure->result->set = TRUE;
}
} else if (g_str_equal (element_name, "socketType")) {
CamelNetworkSecurityMethod security_method = CAMEL_NETWORK_SECURITY_METHOD_NONE;
gboolean set = FALSE;
if (g_str_equal (string->str, "plain")) {
security_method = CAMEL_NETWORK_SECURITY_METHOD_NONE;
set = TRUE;
} else if (g_str_equal (string->str, "SSL")) {
security_method = CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT;
set = TRUE;
} else if (g_str_equal (string->str, "STARTTLS")) {
security_method = CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT;
set = TRUE;
}
if (set) {
if (closure->custom_params) {
const gchar *enum_str = e_enum_to_string (CAMEL_TYPE_NETWORK_SECURITY_METHOD, security_method);
g_warn_if_fail (enum_str != NULL);
if (enum_str)
e_named_parameters_set (closure->custom_params, "security-method", enum_str);
} else {
closure->result->set = set;
closure->result->security_method = security_method;
}
}
} else if (g_str_equal (element_name, "authentication")) {
gboolean use_plain_auth = FALSE;
@ -358,20 +423,30 @@ mail_autoconfig_parse_text (GMarkupParseContext *context,
if (closure->result == &priv->smtp_result)
auth_mechanism = g_strdup ("LOGIN");
if (closure->custom_params) {
e_named_parameters_set (closure->custom_params, "auth-mechanism", auth_mechanism);
g_free (auth_mechanism);
} else {
closure->result->auth_mechanism = auth_mechanism;
closure->result->set = TRUE;
}
} else if (g_str_equal (string->str, "password-encrypted")) {
/* "password-encrypted" apparently maps to CRAM-MD5,
* or at least that's how Thunderbird interprets it. */
if (g_str_equal (string->str, "password-encrypted")) {
if (closure->custom_params) {
e_named_parameters_set (closure->custom_params, "auth-mechanism", "CRAM-MD5");
} else {
closure->result->auth_mechanism = g_strdup ("CRAM-MD5");
closure->result->set = TRUE;
}
} else if (closure->custom_params) {
e_named_parameters_set (closure->custom_params, "auth-mechanism", string->str);
}
/* XXX Other <authentication> values not handled,
* but they are corner cases for the most part. */
} else if (closure->custom_params) {
e_named_parameters_set (closure->custom_params, element_name, string->str);
}
g_string_free (string, TRUE);
@ -451,6 +526,8 @@ mail_autoconfig_lookup_uri_sync (EMailAutoconfig *autoconfig,
closure.autoconfig = autoconfig;
closure.result = NULL;
closure.current_type = NULL;
closure.custom_params = NULL;
context = g_markup_parse_context_new (
&mail_autoconfig_parser, 0,
@ -465,6 +542,9 @@ mail_autoconfig_lookup_uri_sync (EMailAutoconfig *autoconfig,
if (success)
success = g_markup_parse_context_end_parse (context, error);
g_clear_pointer (&closure.custom_params, e_named_parameters_free);
g_clear_pointer (&closure.current_type, g_free);
g_markup_parse_context_free (context);
} else {
g_set_error_literal (
@ -671,9 +751,7 @@ mail_config_lookup_result_finalize (GObject *object)
{
EMailConfigLookupResult *mail_result = E_MAIL_CONFIG_LOOKUP_RESULT (object);
g_free (mail_result->result.user);
g_free (mail_result->result.host);
g_free (mail_result->result.auth_mechanism);
e_mail_config_result_clear (&mail_result->result);
g_free (mail_result->extension_name);
/* Chain up to parent's method. */
@ -900,6 +978,15 @@ mail_autoconfig_get_property (GObject *object,
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
}
static void
mail_autoconfig_constructed (GObject *object)
{
/* Chain up to parent's method. */
G_OBJECT_CLASS (e_mail_autoconfig_parent_class)->constructed (object);
e_extensible_load_extensions (E_EXTENSIBLE (object));
}
static void
mail_autoconfig_dispose (GObject *object)
{
@ -925,15 +1012,9 @@ mail_autoconfig_finalize (GObject *object)
g_free (priv->email_domain_part);
g_free (priv->use_domain);
g_free (priv->imap_result.user);
g_free (priv->imap_result.host);
g_free (priv->imap_result.auth_mechanism);
g_free (priv->pop3_result.user);
g_free (priv->pop3_result.host);
g_free (priv->pop3_result.auth_mechanism);
g_free (priv->smtp_result.user);
g_free (priv->smtp_result.host);
g_free (priv->smtp_result.auth_mechanism);
e_mail_config_result_clear (&priv->imap_result);
e_mail_config_result_clear (&priv->pop3_result);
e_mail_config_result_clear (&priv->smtp_result);
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (e_mail_autoconfig_parent_class)->finalize (object);
@ -1058,6 +1139,7 @@ e_mail_autoconfig_class_init (EMailAutoconfigClass *class)
object_class = G_OBJECT_CLASS (class);
object_class->set_property = mail_autoconfig_set_property;
object_class->get_property = mail_autoconfig_get_property;
object_class->constructed = mail_autoconfig_constructed;
object_class->dispose = mail_autoconfig_dispose;
object_class->finalize = mail_autoconfig_finalize;
@ -1096,6 +1178,15 @@ e_mail_autoconfig_class_init (EMailAutoconfigClass *class)
G_PARAM_READWRITE |
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS));
signals[PROCESS_CUSTOM_TYPES] = g_signal_new (
"process-custom-types",
G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST,
0, NULL, NULL, NULL,
G_TYPE_NONE, 2,
E_TYPE_CONFIG_LOOKUP,
G_TYPE_HASH_TABLE);
}
static void
@ -1334,4 +1425,9 @@ e_mail_autoconfig_copy_results_to_config_lookup (EMailAutoconfig *mail_autoconfi
"smtp",
_("SMTP server"),
E_SOURCE_EXTENSION_MAIL_TRANSPORT);
if (mail_autoconfig->priv->custom_types) {
g_signal_emit (mail_autoconfig, signals[PROCESS_CUSTOM_TYPES], 0,
config_lookup, mail_autoconfig->priv->custom_types);
}
}