aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Barnes <mbarnes@redhat.com>2012-11-09 01:53:09 +0800
committerMatthew Barnes <mbarnes@redhat.com>2012-11-09 02:23:31 +0800
commit6de9a0e56e9a6800e39a43cb04bc5e0045ff8790 (patch)
tree9ef9a2a758c88ea176136d7c8ba461716f960685
parent75595d233ba382dee053d70cf35e26b7eff3befa (diff)
downloadgsoc2013-evolution-6de9a0e56e9a6800e39a43cb04bc5e0045ff8790.tar.gz
gsoc2013-evolution-6de9a0e56e9a6800e39a43cb04bc5e0045ff8790.tar.zst
gsoc2013-evolution-6de9a0e56e9a6800e39a43cb04bc5e0045ff8790.zip
EMailAutoconfig: Restructure XML parsing.
If we get a hit from the online database, parse the XML immediately and store the results in generic internal structs. Then when we're given an ESource to populate we can feed it the stored results instead of parsing the XML on demand (and repeatedly). What this is really doing is making room for other auto-configuration methods besides the online database lookup.
-rw-r--r--mail/e-mail-autoconfig.c388
-rw-r--r--mail/e-mail-autoconfig.h3
-rw-r--r--mail/test-mail-autoconfig.c2
3 files changed, 224 insertions, 169 deletions
diff --git a/mail/e-mail-autoconfig.c b/mail/e-mail-autoconfig.c
index aeebb0fa22..a9e9773050 100644
--- a/mail/e-mail-autoconfig.c
+++ b/mail/e-mail-autoconfig.c
@@ -35,23 +35,29 @@
#define ERROR_IS_NOT_FOUND(error) \
(g_error_matches ((error), SOUP_HTTP_ERROR, SOUP_STATUS_NOT_FOUND))
+typedef struct _EMailAutoconfigResult EMailAutoconfigResult;
typedef struct _ParserClosure ParserClosure;
+struct _EMailAutoconfigResult {
+ gboolean set;
+ gchar *user;
+ gchar *host;
+ guint16 port;
+ CamelNetworkSecurityMethod security_method;
+};
+
struct _EMailAutoconfigPrivate {
gchar *email_address;
gchar *email_local_part;
gchar *email_domain_part;
- gchar *markup_content;
+ EMailAutoconfigResult imap_result;
+ EMailAutoconfigResult pop3_result;
+ EMailAutoconfigResult smtp_result;
};
struct _ParserClosure {
- CamelNetworkSettings *network_settings;
- const gchar *expected_type;
- const gchar *email_address;
- const gchar *email_local_part;
- const gchar *email_domain_part;
- gboolean in_server_element;
- gboolean settings_modified;
+ EMailAutoconfig *autoconfig;
+ EMailAutoconfigResult *result;
};
enum {
@@ -73,90 +79,6 @@ G_DEFINE_TYPE_WITH_CODE (
G_IMPLEMENT_INTERFACE (
G_TYPE_ASYNC_INITABLE, NULL))
-static gchar *
-mail_autoconfig_resolve_name_server (const gchar *domain,
- GCancellable *cancellable,
- GError **error)
-{
- GResolver *resolver;
- GList *records;
- gchar *name_server = NULL;
-
- resolver = g_resolver_get_default ();
-
- records = g_resolver_lookup_records (
- resolver, domain, G_RESOLVER_RECORD_NS, cancellable, error);
-
- /* This list is sorted per RFC 2782, so use the first item. */
- if (records != NULL) {
- GVariant *variant = records->data;
- g_variant_get_child (variant, 0, "s", &name_server);
- }
-
- g_list_free_full (records, (GDestroyNotify) g_variant_unref);
-
- g_object_unref (resolver);
-
- return name_server;
-}
-
-static void
-mail_autoconfig_abort_soup_session_cb (GCancellable *cancellable,
- SoupSession *soup_session)
-{
- soup_session_abort (soup_session);
-}
-
-static gboolean
-mail_autoconfig_lookup (EMailAutoconfig *autoconfig,
- const gchar *domain,
- GCancellable *cancellable,
- GError **error)
-{
- SoupMessage *soup_message;
- SoupSession *soup_session;
- gulong cancel_id = 0;
- guint status;
- gchar *uri;
-
- soup_session = soup_session_sync_new ();
-
- uri = g_strconcat (AUTOCONFIG_BASE_URI, domain, NULL);
- soup_message = soup_message_new (SOUP_METHOD_GET, uri);
- g_free (uri);
-
- if (G_IS_CANCELLABLE (cancellable))
- cancel_id = g_cancellable_connect (
- cancellable,
- G_CALLBACK (mail_autoconfig_abort_soup_session_cb),
- g_object_ref (soup_session),
- (GDestroyNotify) g_object_unref);
-
- status = soup_session_send_message (soup_session, soup_message);
-
- if (cancel_id > 0)
- g_cancellable_disconnect (cancellable, cancel_id);
-
- if (SOUP_STATUS_IS_SUCCESSFUL (status)) {
-
- /* Just to make sure we don't leak. */
- g_free (autoconfig->priv->markup_content);
-
- autoconfig->priv->markup_content =
- g_strdup (soup_message->response_body->data);
- } else {
- g_set_error_literal (
- error, SOUP_HTTP_ERROR,
- soup_message->status_code,
- soup_message->reason_phrase);
- }
-
- g_object_unref (soup_message);
- g_object_unref (soup_session);
-
- return SOUP_STATUS_IS_SUCCESSFUL (status);
-}
-
static void
mail_autoconfig_parse_start_element (GMarkupParseContext *context,
const gchar *element_name,
@@ -166,9 +88,12 @@ mail_autoconfig_parse_start_element (GMarkupParseContext *context,
GError **error)
{
ParserClosure *closure = user_data;
+ EMailAutoconfigPrivate *priv;
gboolean is_incoming_server;
gboolean is_outgoing_server;
+ priv = closure->autoconfig->priv;
+
is_incoming_server = g_str_equal (element_name, "incomingServer");
is_outgoing_server = g_str_equal (element_name, "outgoingServer");
@@ -184,8 +109,12 @@ mail_autoconfig_parse_start_element (GMarkupParseContext *context,
"type", &type,
G_MARKUP_COLLECT_INVALID);
- closure->in_server_element =
- (g_strcmp0 (type, closure->expected_type) == 0);
+ if (g_strcmp0 (type, "imap") == 0)
+ closure->result = &priv->imap_result;
+ if (g_strcmp0 (type, "pop3") == 0)
+ closure->result = &priv->pop3_result;
+ if (g_strcmp0 (type, "smtp") == 0)
+ closure->result = &priv->smtp_result;
}
}
@@ -203,7 +132,7 @@ mail_autoconfig_parse_end_element (GMarkupParseContext *context,
is_outgoing_server = g_str_equal (element_name, "outgoingServer");
if (is_incoming_server || is_outgoing_server)
- closure->in_server_element = FALSE;
+ closure->result = NULL;
}
static void
@@ -214,10 +143,13 @@ mail_autoconfig_parse_text (GMarkupParseContext *context,
GError **error)
{
ParserClosure *closure = user_data;
+ EMailAutoconfigPrivate *priv;
const gchar *element_name;
GString *string;
- if (!closure->in_server_element)
+ priv = closure->autoconfig->priv;
+
+ if (closure->result == NULL)
return;
/* Perform the following text substitutions:
@@ -242,7 +174,7 @@ mail_autoconfig_parse_text (GMarkupParseContext *context,
}
variable = "%EMAILADDRESS%";
- substitute = closure->email_address;
+ substitute = priv->email_address;
if (strncmp (cp, variable, strlen (variable)) == 0) {
g_string_append (string, substitute);
@@ -251,7 +183,7 @@ mail_autoconfig_parse_text (GMarkupParseContext *context,
}
variable = "%EMAILLOCALPART%";
- substitute = closure->email_local_part;
+ substitute = priv->email_local_part;
if (strncmp (cp, variable, strlen (variable)) == 0) {
g_string_append (string, substitute);
@@ -260,7 +192,7 @@ mail_autoconfig_parse_text (GMarkupParseContext *context,
}
variable = "%EMAILDOMAIN%";
- substitute = closure->email_domain_part;
+ substitute = priv->email_domain_part;
if (strncmp (cp, variable, strlen (variable)) == 0) {
g_string_append (string, substitute);
@@ -275,39 +207,33 @@ mail_autoconfig_parse_text (GMarkupParseContext *context,
element_name = g_markup_parse_context_get_element (context);
if (g_str_equal (element_name, "hostname")) {
- camel_network_settings_set_host (
- closure->network_settings, string->str);
- closure->settings_modified = TRUE;
+ closure->result->host = g_strdup (string->str);
+ closure->result->set = TRUE;
} else if (g_str_equal (element_name, "username")) {
- camel_network_settings_set_user (
- closure->network_settings, string->str);
- closure->settings_modified = TRUE;
+ 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)) {
- camel_network_settings_set_port (
- closure->network_settings, (guint16) port);
- closure->settings_modified = TRUE;
+ closure->result->port = (guint16) port;
+ closure->result->set = TRUE;
}
} else if (g_str_equal (element_name, "socketType")) {
if (g_str_equal (string->str, "plain")) {
- camel_network_settings_set_security_method (
- closure->network_settings,
- CAMEL_NETWORK_SECURITY_METHOD_NONE);
- closure->settings_modified = TRUE;
+ closure->result->security_method =
+ CAMEL_NETWORK_SECURITY_METHOD_NONE;
+ closure->result->set = TRUE;
} else if (g_str_equal (string->str, "SSL")) {
- camel_network_settings_set_security_method (
- closure->network_settings,
- CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT);
- closure->settings_modified = TRUE;
+ closure->result->security_method =
+ CAMEL_NETWORK_SECURITY_METHOD_SSL_ON_ALTERNATE_PORT;
+ closure->result->set = TRUE;
} else if (g_str_equal (string->str, "STARTTLS")) {
- camel_network_settings_set_security_method (
- closure->network_settings,
- CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT);
- closure->settings_modified = TRUE;
+ closure->result->security_method =
+ CAMEL_NETWORK_SECURITY_METHOD_STARTTLS_ON_STANDARD_PORT;
+ closure->result->set = TRUE;
}
}
@@ -323,20 +249,123 @@ static GMarkupParser mail_autoconfig_parser = {
mail_autoconfig_parse_text
};
+static gchar *
+mail_autoconfig_resolve_name_server (const gchar *domain,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GResolver *resolver;
+ GList *records;
+ gchar *name_server = NULL;
+
+ resolver = g_resolver_get_default ();
+
+ records = g_resolver_lookup_records (
+ resolver, domain, G_RESOLVER_RECORD_NS, cancellable, error);
+
+ /* This list is sorted per RFC 2782, so use the first item. */
+ if (records != NULL) {
+ GVariant *variant = records->data;
+ g_variant_get_child (variant, 0, "s", &name_server);
+ }
+
+ g_list_free_full (records, (GDestroyNotify) g_variant_unref);
+
+ g_object_unref (resolver);
+
+ return name_server;
+}
+
+static void
+mail_autoconfig_abort_soup_session_cb (GCancellable *cancellable,
+ SoupSession *soup_session)
+{
+ soup_session_abort (soup_session);
+}
+
+static gboolean
+mail_autoconfig_lookup (EMailAutoconfig *autoconfig,
+ const gchar *domain,
+ GCancellable *cancellable,
+ GError **error)
+{
+ GMarkupParseContext *context;
+ SoupMessage *soup_message;
+ SoupSession *soup_session;
+ ParserClosure closure;
+ gulong cancel_id = 0;
+ gboolean success;
+ guint status;
+ gchar *uri;
+
+ soup_session = soup_session_sync_new ();
+
+ uri = g_strconcat (AUTOCONFIG_BASE_URI, domain, NULL);
+ soup_message = soup_message_new (SOUP_METHOD_GET, uri);
+ g_free (uri);
+
+ if (G_IS_CANCELLABLE (cancellable))
+ cancel_id = g_cancellable_connect (
+ cancellable,
+ G_CALLBACK (mail_autoconfig_abort_soup_session_cb),
+ g_object_ref (soup_session),
+ (GDestroyNotify) g_object_unref);
+
+ status = soup_session_send_message (soup_session, soup_message);
+
+ if (cancel_id > 0)
+ g_cancellable_disconnect (cancellable, cancel_id);
+
+ success = SOUP_STATUS_IS_SUCCESSFUL (status);
+
+ if (!success) {
+ g_set_error_literal (
+ error, SOUP_HTTP_ERROR,
+ soup_message->status_code,
+ soup_message->reason_phrase);
+ goto exit;
+ }
+
+ closure.autoconfig = autoconfig;
+ closure.result = NULL;
+
+ context = g_markup_parse_context_new (
+ &mail_autoconfig_parser, 0,
+ &closure, (GDestroyNotify) NULL);
+
+ success = g_markup_parse_context_parse (
+ context,
+ soup_message->response_body->data,
+ soup_message->response_body->length,
+ error);
+
+ if (success)
+ success = g_markup_parse_context_end_parse (context, error);
+
+ g_markup_parse_context_free (context);
+
+exit:
+ g_object_unref (soup_message);
+ g_object_unref (soup_session);
+
+ return success;
+}
+
static gboolean
mail_autoconfig_set_details (EMailAutoconfig *autoconfig,
- const gchar *expected_type,
+ EMailAutoconfigResult *result,
ESource *source,
const gchar *extension_name)
{
- GMarkupParseContext *context;
ESourceCamel *camel_ext;
ESourceBackend *backend_ext;
CamelSettings *settings;
- ParserClosure closure;
const gchar *backend_name;
- const gchar *markup_content;
- gboolean success;
+
+ g_return_val_if_fail (result != NULL, FALSE);
+
+ if (!result->set)
+ return FALSE;
if (!e_source_has_extension (source, extension_name))
return FALSE;
@@ -349,33 +378,15 @@ mail_autoconfig_set_details (EMailAutoconfig *autoconfig,
settings = e_source_camel_get_settings (camel_ext);
g_return_val_if_fail (CAMEL_IS_NETWORK_SETTINGS (settings), FALSE);
- markup_content = e_mail_autoconfig_get_markup_content (autoconfig);
- g_return_val_if_fail (markup_content != NULL, FALSE);
-
- closure.network_settings = CAMEL_NETWORK_SETTINGS (settings);
- closure.expected_type = expected_type;
- closure.in_server_element = FALSE;
- closure.settings_modified = FALSE;
-
- /* These are used for text substitutions. */
- closure.email_address = autoconfig->priv->email_address;
- closure.email_local_part = autoconfig->priv->email_local_part;
- closure.email_domain_part = autoconfig->priv->email_domain_part;
-
- context = g_markup_parse_context_new (
- &mail_autoconfig_parser, 0, &closure, (GDestroyNotify) NULL);
-
- success = g_markup_parse_context_parse (
- context, markup_content, strlen (markup_content), NULL);
-
- success &= g_markup_parse_context_end_parse (context, NULL);
-
- /* Did we actually configure anything? */
- success &= closure.settings_modified;
-
- g_markup_parse_context_free (context);
+ g_object_set (
+ settings,
+ "user", result->user,
+ "host", result->host,
+ "port", result->port,
+ "security-method", result->security_method,
+ NULL);
- return success;
+ return TRUE;
}
static void
@@ -433,7 +444,13 @@ mail_autoconfig_finalize (GObject *object)
g_free (priv->email_address);
g_free (priv->email_local_part);
g_free (priv->email_domain_part);
- g_free (priv->markup_content);
+
+ g_free (priv->imap_result.user);
+ g_free (priv->imap_result.host);
+ g_free (priv->pop3_result.user);
+ g_free (priv->pop3_result.host);
+ g_free (priv->smtp_result.user);
+ g_free (priv->smtp_result.host);
/* Chain up to parent's finalize() method. */
G_OBJECT_CLASS (e_mail_autoconfig_parent_class)->finalize (object);
@@ -634,14 +651,6 @@ e_mail_autoconfig_get_email_address (EMailAutoconfig *autoconfig)
return autoconfig->priv->email_address;
}
-const gchar *
-e_mail_autoconfig_get_markup_content (EMailAutoconfig *autoconfig)
-{
- g_return_val_if_fail (E_IS_MAIL_AUTOCONFIG (autoconfig), NULL);
-
- return autoconfig->priv->markup_content;
-}
-
gboolean
e_mail_autoconfig_set_imap_details (EMailAutoconfig *autoconfig,
ESource *imap_source)
@@ -650,8 +659,8 @@ e_mail_autoconfig_set_imap_details (EMailAutoconfig *autoconfig,
g_return_val_if_fail (E_IS_SOURCE (imap_source), FALSE);
return mail_autoconfig_set_details (
- autoconfig, "imap", imap_source,
- E_SOURCE_EXTENSION_MAIL_ACCOUNT);
+ autoconfig, &autoconfig->priv->imap_result,
+ imap_source, E_SOURCE_EXTENSION_MAIL_ACCOUNT);
}
gboolean
@@ -662,8 +671,8 @@ e_mail_autoconfig_set_pop3_details (EMailAutoconfig *autoconfig,
g_return_val_if_fail (E_IS_SOURCE (pop3_source), FALSE);
return mail_autoconfig_set_details (
- autoconfig, "pop3", pop3_source,
- E_SOURCE_EXTENSION_MAIL_ACCOUNT);
+ autoconfig, &autoconfig->priv->pop3_result,
+ pop3_source, E_SOURCE_EXTENSION_MAIL_ACCOUNT);
}
gboolean
@@ -674,7 +683,54 @@ e_mail_autoconfig_set_smtp_details (EMailAutoconfig *autoconfig,
g_return_val_if_fail (E_IS_SOURCE (smtp_source), FALSE);
return mail_autoconfig_set_details (
- autoconfig, "smtp", smtp_source,
- E_SOURCE_EXTENSION_MAIL_TRANSPORT);
+ autoconfig, &autoconfig->priv->smtp_result,
+ smtp_source, E_SOURCE_EXTENSION_MAIL_TRANSPORT);
+}
+
+void
+e_mail_autoconfig_dump_results (EMailAutoconfig *autoconfig)
+{
+ const gchar *email_address;
+ gboolean have_results;
+
+ g_return_if_fail (E_IS_MAIL_AUTOCONFIG (autoconfig));
+
+ email_address = autoconfig->priv->email_address;
+
+ have_results =
+ autoconfig->priv->imap_result.set ||
+ autoconfig->priv->pop3_result.set ||
+ autoconfig->priv->smtp_result.set;
+
+ if (have_results) {
+ g_print ("Results for <%s>\n", email_address);
+
+ if (autoconfig->priv->imap_result.set) {
+ g_print (
+ "IMAP: %s@%s:%u\n",
+ autoconfig->priv->imap_result.user,
+ autoconfig->priv->imap_result.host,
+ autoconfig->priv->imap_result.port);
+ }
+
+ if (autoconfig->priv->pop3_result.set) {
+ g_print (
+ "POP3: %s@%s:%u\n",
+ autoconfig->priv->pop3_result.user,
+ autoconfig->priv->pop3_result.host,
+ autoconfig->priv->pop3_result.port);
+ }
+
+ if (autoconfig->priv->smtp_result.set) {
+ g_print (
+ "SMTP: %s@%s:%u\n",
+ autoconfig->priv->smtp_result.user,
+ autoconfig->priv->smtp_result.host,
+ autoconfig->priv->smtp_result.port);
+ }
+
+ } else {
+ g_print ("No results for <%s>\n", email_address);
+ }
}
diff --git a/mail/e-mail-autoconfig.h b/mail/e-mail-autoconfig.h
index b0cfb93b13..c59897c8b0 100644
--- a/mail/e-mail-autoconfig.h
+++ b/mail/e-mail-autoconfig.h
@@ -70,8 +70,6 @@ EMailAutoconfig *
GError **error);
const gchar * e_mail_autoconfig_get_email_address
(EMailAutoconfig *autoconfig);
-const gchar * e_mail_autoconfig_get_markup_content
- (EMailAutoconfig *autoconfig);
gboolean e_mail_autoconfig_set_imap_details
(EMailAutoconfig *autoconfig,
ESource *imap_source);
@@ -81,6 +79,7 @@ gboolean e_mail_autoconfig_set_pop3_details
gboolean e_mail_autoconfig_set_smtp_details
(EMailAutoconfig *autoconfig,
ESource *smtp_source);
+void e_mail_autoconfig_dump_results (EMailAutoconfig *autoconfig);
G_END_DECLS
diff --git a/mail/test-mail-autoconfig.c b/mail/test-mail-autoconfig.c
index 10977a17b2..2ce8cb600a 100644
--- a/mail/test-mail-autoconfig.c
+++ b/mail/test-mail-autoconfig.c
@@ -45,7 +45,7 @@ main (gint argc,
g_assert (E_IS_MAIL_AUTOCONFIG (autoconfig));
- g_print ("%s\n", e_mail_autoconfig_get_markup_content (autoconfig));
+ e_mail_autoconfig_dump_results (autoconfig);
g_object_unref (autoconfig);