[evolution] I#1637 - EMailAutoconfig: Autoconfig with Exchange accounts



commit c99f1c8c7b684bd6c0061ec9bfde320a721ca39e
Author: Milan Crha <mcrha redhat com>
Date:   Thu Sep 23 12:39:03 2021 +0200

    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

 src/mail/e-mail-autoconfig.c | 194 ++++++++++++++++++++++++++++++++-----------
 1 file changed, 145 insertions(+), 49 deletions(-)
---
diff --git a/src/mail/e-mail-autoconfig.c b/src/mail/e-mail-autoconfig.c
index aeb6724c07..38f470e28c 100644
--- a/src/mail/e-mail-autoconfig.c
+++ b/src/mail/e-mail-autoconfig.c
@@ -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,8 +211,22 @@ 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 */
@@ -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")) {
-               closure->result->host = g_strdup (string->str);
-               closure->result->set = TRUE;
+               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")) {
-               closure->result->user = g_strdup (string->str);
-               closure->result->set = TRUE;
+               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")) {
-               glong port = strtol (string->str, NULL, 10);
-               if (port == CLAMP (port, 1, G_MAXUINT16)) {
-                       closure->result->port = (guint16) port;
-                       closure->result->set = TRUE;
+               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")) {
+               CamelNetworkSecurityMethod security_method = CAMEL_NETWORK_SECURITY_METHOD_NONE;
+               gboolean set = FALSE;
+
                if (g_str_equal (string->str, "plain")) {
-                       closure->result->security_method =
-                               CAMEL_NETWORK_SECURITY_METHOD_NONE;
-                       closure->result->set = TRUE;
+                       security_method = CAMEL_NETWORK_SECURITY_METHOD_NONE;
+                       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;
+                       security_method = CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT;
+                       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;
+                       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");
 
-                       closure->result->auth_mechanism = auth_mechanism;
-                       closure->result->set = TRUE;
-               }
-
-               /* "password-encrypted" apparently maps to CRAM-MD5,
-                * or at least that's how Thunderbird interprets it. */
-
-               if (g_str_equal (string->str, "password-encrypted")) {
-                       closure->result->auth_mechanism = g_strdup ("CRAM-MD5");
-                       closure->result->set = TRUE;
+                       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 (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);
+       }
 }


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]