diff options
Diffstat (limited to 'mail/mail-guess-servers.c')
-rw-r--r-- | mail/mail-guess-servers.c | 370 |
1 files changed, 370 insertions, 0 deletions
diff --git a/mail/mail-guess-servers.c b/mail/mail-guess-servers.c new file mode 100644 index 0000000000..8ab9670e8c --- /dev/null +++ b/mail/mail-guess-servers.c @@ -0,0 +1,370 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* + * 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/> + * + * + * Authors: + * Srinivasa Ragavan <srini@linux.intel.com> + * + * Copyright (C) 2009 Intel Corporation (www.intel.com) + * + */ + +/* Template of the code is taken from libsoup tests/ */ + +#ifdef HAVE_CONFIG_H +#include <config.h> +#endif + +#include <ctype.h> +#include <errno.h> +#include <fcntl.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <sys/stat.h> +#include <unistd.h> + +#include <libsoup/soup.h> + +#include <libxml/parser.h> +#include <libxml/tree.h> +#include <libxml/xmlmemory.h> + +#include <libedataserver/e-proxy.h> + +#include <shell/e-shell.h> +#include <e-util/e-util-private.h> + +#include "mail-guess-servers.h" + +static gchar * +xml_to_gchar (xmlChar *xml, + EmailProvider *provider) +{ + gchar *gxml = NULL; + gchar *tmp; + gchar *repl = NULL; + const gchar *sec_part; + + tmp = xml ? strstr((gchar *) xml, "\%EMAIL") : NULL; + + if (!tmp) { + gxml = xml ? g_strdup ((gchar *) xml) : NULL; + } else { + decodepart: + *tmp = 0; + tmp+=6; + if (*tmp == 'A') + repl = provider->email; + else if (*tmp == 'L') + repl = provider->username; + else if (*tmp == 'D') + repl = provider->domain; + sec_part = strstr(tmp, "\%"); + sec_part++; + if (!*sec_part) + sec_part = ""; + + gxml = g_strdup_printf("%s%s%s", gxml ? gxml : (gchar *)xml, repl, sec_part); + tmp = strstr (gxml, "\%EMAIL"); + if (tmp) { + goto decodepart; + } + } + + xmlFree (xml); + + return gxml; +} + +static SoupMessage * +get_url (SoupSession *session, + const gchar *url) +{ + SoupMessage *msg; + const gchar *header; + + msg = soup_message_new (SOUP_METHOD_GET, url); + soup_message_set_flags (msg, SOUP_MESSAGE_NO_REDIRECT); + + soup_session_send_message (session, msg); + + if (SOUP_STATUS_IS_REDIRECTION (msg->status_code)) { + header = soup_message_headers_get_one (msg->response_headers, + "Location"); + if (header) { + return get_url (session, header); + } + } else if (SOUP_STATUS_IS_SUCCESSFUL (msg->status_code)) { + return msg; + } + + return NULL; +} + +static void +handle_incoming (xmlNodePtr head, + EmailProvider *provider) +{ + xmlNodePtr node = head->children; + + provider->recv_type = xml_to_gchar ( + xmlGetProp (head, (xmlChar *) "type"), provider); + + while (node != NULL) { + if (strcmp ((gchar *)node->name, "hostname") == 0) { + provider->recv_hostname = xml_to_gchar ( + xmlNodeGetContent (node), provider); + } else if (strcmp ((gchar *)node->name, "port") == 0) { + provider->recv_port = xml_to_gchar ( + xmlNodeGetContent (node), provider); + } else if (strcmp ((gchar *)node->name, "socketType") == 0) { + provider->recv_socket_type = xml_to_gchar ( + xmlNodeGetContent (node), provider); + } else if (strcmp ((gchar *)node->name, "username") == 0) { + provider->recv_username = xml_to_gchar ( + xmlNodeGetContent (node), provider); + } else if (strcmp ((gchar *)node->name, "authentication") == 0) { + provider->recv_auth = xml_to_gchar ( + xmlNodeGetContent (node), provider); + } + + node = node->next; + } +} + +static void +handle_outgoing (xmlNodePtr head, + EmailProvider *provider) +{ + xmlNodePtr node = head->children; + + provider->send_type = xml_to_gchar ( + xmlGetProp (head, (xmlChar *) "type"), provider); + + while (node != NULL) { + if (strcmp ((gchar *)node->name, "hostname") == 0) { + provider->send_hostname = xml_to_gchar ( + xmlNodeGetContent (node), provider); + } else if (strcmp ((gchar *)node->name, "port") == 0) { + provider->send_port = xml_to_gchar ( + xmlNodeGetContent (node), provider); + } else if (strcmp ((gchar *)node->name, "socketType") == 0) { + provider->send_socket_type = xml_to_gchar ( + xmlNodeGetContent (node), provider); + } else if (strcmp ((gchar *)node->name, "username") == 0) { + provider->send_username = xml_to_gchar ( + xmlNodeGetContent (node), provider); + } else if (strcmp ((gchar *)node->name, "authentication") == 0) { + provider->send_auth = xml_to_gchar ( + xmlNodeGetContent (node), provider); + } + + node = node->next; + } +} + +static gboolean +parse_message (const gchar *msg, + gint length, + EmailProvider *provider) +{ + xmlDocPtr doc; + xmlNodePtr node; + + doc = xmlReadMemory (msg, length, "file.xml", NULL, 0); + + node = doc->children; + while (node) { + if (strcmp ((gchar *)node->name, "clientConfig") == 0) { + break; + } + node = node->next; + } + + if (!node) { + g_warning ("Incorrect data: ClientConfig not found ... Quitting\n"); + return FALSE; + } + + node = node->children; + while (node) { + if (strcmp ((gchar *)node->name, "emailProvider") == 0) { + break; + } + node = node->next; + } + + if (!node) { + g_warning ("Incorrect data: ClientConfig not found ... Quitting\n"); + return FALSE; + } + + node = node->children; + while (node) { + if (strcmp ((gchar *)node->name, "incomingServer") == 0) { + /* Handle Incoming */ + handle_incoming (node, provider); + } else if (strcmp ((gchar *)node->name, "outgoingServer") == 0) { + /* Handle Outgoing */ + handle_outgoing (node, provider); + } + + node = node->next; + } + + xmlFreeDoc (doc); + + return TRUE; +} + +static gboolean +parse_soup_message (SoupMessage *msg, + EmailProvider *provider) +{ + return parse_message ( + msg->response_body->data, + msg->response_body->length, provider); +} + +static gboolean +is_online (void) +{ + EShell *shell; + + /* FIXME Pass this in. */ + shell = e_shell_get_default (); + + return e_shell_get_online (shell); +} + +static gboolean +guess_when_online (EmailProvider *provider) +{ + const gchar *cafile = NULL; + gchar *url; + EProxy *proxy; + SoupURI *parsed; + SoupMessage *msg; + SoupSession *session; + + proxy = e_proxy_new (); + e_proxy_setup_proxy (proxy); + + url = g_strdup_printf ( + "%s/%s", "http://api.gnome.org/evolution/autoconfig", + provider->domain); + parsed = soup_uri_new (url); + soup_uri_free (parsed); + + session = soup_session_sync_new_with_options ( + SOUP_SESSION_SSL_CA_FILE, cafile, + SOUP_SESSION_USER_AGENT, "get ", + NULL); + + if (e_proxy_require_proxy_for_uri (proxy, url)) { + SoupURI *proxy_uri = e_proxy_peek_uri_for (proxy, url); +/* fprintf (stderr, "URL '%s' requires a proxy: '%s'\n", + url, soup_uri_to_string (proxy_uri, FALSE)); */ + g_object_set (session, SOUP_SESSION_PROXY_URI, proxy_uri, NULL); + } + + msg = get_url (session, url); + if (!msg) + return FALSE; + + parse_soup_message (msg, provider); + + g_object_unref (proxy); + g_object_unref (msg); + g_object_unref (session); + g_free (url); + + return TRUE; + +} + +static gchar * +get_filename_for_offline_autoconfig (const gchar *domain) +{ + return g_build_filename (EVOLUTION_PRIVDATADIR, "mail-autoconfig", domain, NULL); +} + +static gboolean +guess_when_offline (EmailProvider *provider) +{ + gchar *filename; + gchar *contents; + gsize length; + gboolean success; + + if (!provider->domain || provider->domain[0] == 0) + return FALSE; + + success = FALSE; + + filename = get_filename_for_offline_autoconfig (provider->domain); + if (!g_file_get_contents (filename, &contents, &length, NULL)) /* NULL-GError */ + goto out; + + success = parse_message (contents, (gint) length, provider); + +out: + g_free (filename); + g_free (contents); + + return success; +} + +gboolean +mail_guess_servers (EmailProvider *provider) +{ + if (is_online () && guess_when_online (provider)) + return TRUE; + else + return guess_when_offline (provider); +} + +#ifdef TEST +gint +main (gint argc, + gchar **argv) +{ + EmailProvider *provider; + + g_type_init (); + + provider = g_new0 (EmailProvider, 1); + + provider->email = "sragavan@iijmio-mail.jp"; + provider->domain = "iijmio-mail.jp"; + provider->username = "sragavan"; + + mail_guess_servers (provider); + + printf ( + "Recv: %s\n%s(%s), %s by %s \n " + "Send: %s\n%s(%s), %s by %s\n via %s to %s\n", + provider->recv_type, provider->recv_hostname, + provider->recv_port, provider->recv_username, + provider->recv_auth, + provider->send_type, provider->send_hostname, + provider->send_port, provider->send_username, + provider->send_auth, + provider->recv_socket_type, + provider->send_socket_type); + return 0; +} +#endif |