mail-notification

Fork of Jean-Yves Lefort's mail-notification, a tray icon to notify of new mail
git clone https://code.djc.id.au/git/mail-notification/

src/mn-hotmail-mailbox.gob (9644B) - raw

      1 /*
      2  * Mail Notification
      3  * Copyright (C) 2003-2008 Jean-Yves Lefort <jylefort@brutele.be>
      4  *
      5  * This program is free software; you can redistribute it and/or modify
      6  * it under the terms of the GNU General Public License as published by
      7  * the Free Software Foundation; either version 3 of the License, or
      8  * (at your option) any later version.
      9  *
     10  * This program is distributed in the hope that it will be useful,
     11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
     12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     13  * GNU General Public License for more details.
     14  *
     15  * You should have received a copy of the GNU General Public License along
     16  * with this program; if not, write to the Free Software Foundation, Inc.,
     17  * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
     18  */
     19 
     20 %headertop{
     21 #include "mn-webmail-mailbox.h"
     22 %}
     23 
     24 %{
     25 #include <unistd.h>
     26 #include <glib/gi18n.h>
     27 #include "mn-conf.h"
     28 #include "mn-webmail-mailbox-private.h"
     29 #include "mn-stock.h"
     30 #include "mn-util.h"
     31 
     32 typedef struct
     33 {
     34   const char	*code;
     35   const char	*folder;
     36 } InboxMapping;
     37 
     38 /* this list is not exhaustive */
     39 static const InboxMapping inbox_mappings_array[] = {
     40   { "da",	"Indbakke"		},
     41   { "de",	"Posteingang"		},
     42   { "es",	"Band. entrada"		},
     43   { "fi",	"Saapuneet"		},
     44   { "fr",	"Boîte de réception"	},
     45   { "it",	"Posta in arrivo"	},
     46   { "nl",	"Postvak IN"		},
     47   { "no",	"Innboks"		},
     48   { "pl",	"Skrzynka odbiorcza"	},
     49   { "pt_BR",	"Caixa de Entrada"	},
     50   { "pt_PT",	"A Receber"		},
     51   { "sv",	"Inkorgen"		},
     52 };
     53 
     54 static GHashTable *inbox_mappings;
     55 %}
     56 
     57 class MN:Hotmail:Mailbox from MN:Webmail:Mailbox
     58 {
     59   class_init (class)
     60   {
     61     MN_MAILBOX_CLASS(class)->type = "hotmail";
     62 
     63     /* 5 minutes is a good default */
     64     MN_MAILBOX_CLASS(class)->default_check_delay = 60 * 5;
     65 
     66     MN_WEBMAIL_MAILBOX_CLASS(class)->default_domain = "hotmail.com";
     67 
     68     self_init_inbox_mappings();
     69   }
     70 
     71   private void
     72     init_inbox_mappings (void)
     73   {
     74     int i;
     75 
     76     inbox_mappings = g_hash_table_new(g_str_hash, g_str_equal);
     77 
     78     for (i = 0; i < G_N_ELEMENTS(inbox_mappings_array); i++)
     79       {
     80 	const InboxMapping *mapping = &inbox_mappings_array[i];
     81 
     82 	g_hash_table_insert(inbox_mappings, (gpointer) mapping->code, (gpointer) mapping->folder);
     83       }
     84   }
     85 
     86   init (self)
     87   {
     88     mn_mailbox_set_format(MN_MAILBOX(self), "Windows Live Hotmail");
     89     mn_mailbox_set_stock_id(MN_MAILBOX(self), MN_STOCK_HOTMAIL);
     90   }
     91 
     92   private void
     93     parse_language (const char *code (check null),
     94 		    char **language,
     95 		    char **country)
     96   {
     97     char *stripped = NULL;
     98     char *sep;
     99 
    100     /* strip the charset if any */
    101     sep = strchr(code, '.');
    102     if (sep)
    103       {
    104 	stripped = g_strndup(code, sep - code);
    105 	code = stripped;
    106       }
    107 
    108     sep = strchr(code, '_');
    109     if (sep)
    110       {
    111 	*language = g_strndup(code, sep - code);
    112 	*country = g_strdup(sep + 1);
    113       }
    114     else
    115       {
    116 	*language = g_strdup(code);
    117 	*country = NULL;
    118       }
    119 
    120     g_free(stripped);
    121   }
    122 
    123   private const char *
    124     get_localized_folder (const char *folder (check null))
    125   {
    126     if (! strcmp(folder, "Inbox"))
    127       {
    128 	int i;
    129 	const char* const *language_codes;
    130 
    131 	language_codes = g_get_language_names();
    132 
    133 	for (i = 0; language_codes[i]; i++)
    134 	  {
    135 	    const char *code = language_codes[i];
    136 	    char *language;
    137 	    char *country;
    138 	    const char *mapping = NULL;
    139 
    140 	    self_parse_language(code, &language, &country);
    141 
    142 	    if (country)
    143 	      {
    144 		char *full;
    145 
    146 		full = g_strdup_printf("%s_%s", language, country);
    147 		mapping = g_hash_table_lookup(inbox_mappings, full);
    148 		g_free(full);
    149 	      }
    150 
    151 	    if (! mapping)
    152 	      mapping = g_hash_table_lookup(inbox_mappings, language);
    153 
    154 	    g_free(language);
    155 	    g_free(country);
    156 
    157 	    if (mapping)
    158 	      return mapping;
    159 	  }
    160       }
    161 
    162     return folder;
    163   }
    164 
    165   private char *
    166     encode_with_character_references (const char *str (check null))
    167   {
    168     GString *encoded;
    169     const char *p;
    170 
    171     encoded = g_string_new(NULL);
    172     for (p = str; *p; p = g_utf8_next_char(p))
    173       {
    174 	gunichar c = g_utf8_get_char(p);
    175 
    176 	if (c < 128 && (g_ascii_isalnum(c) || g_ascii_isspace(c) || c == '.'))
    177 	  g_string_append_c(encoded, c);
    178 	else
    179 	  g_string_append_printf(encoded, "&#%i;", (int) c);
    180       }
    181 
    182     return g_string_free(encoded, FALSE);
    183   }
    184 
    185   private char *
    186     create_config_file (self,
    187 			const char *spool_file (check null),
    188 			gboolean getlive_pre_1_40,
    189 			GError **err)
    190   {
    191     char *username;
    192     char *domain;
    193     const char *localized_folder;
    194     char *folder;
    195     GString *contents;
    196     char *filename;
    197     const char *charset;
    198 
    199     mn_webmail_mailbox_parse_username(MN_WEBMAIL_MAILBOX(self), &username, &domain);
    200 
    201     contents = g_string_new(NULL);
    202 
    203     localized_folder = self_get_localized_folder(MN_WEBMAIL_MAILBOX(self)->folder);
    204 
    205     if (getlive_pre_1_40)
    206       folder = self_encode_with_character_references(localized_folder);
    207     else
    208       folder = g_strdup(localized_folder);
    209 
    210     g_string_append_printf(contents,
    211 			   "UserName = %s\n"
    212 			   "Domain = %s\n"
    213 			   "Password = %s\n"
    214 			   "FetchOnlyUnread = Yes\n"
    215 			   "Folder = %s\n"
    216 			   "Processor = cat >> '%s'\n"
    217 			   "MarkRead = No\n",
    218 			   username,
    219 			   domain,
    220 			   MN_AUTHENTICATED_MAILBOX(self)->runtime_password,
    221 			   folder,
    222 			   spool_file);
    223 
    224     g_free(username);
    225     g_free(domain);
    226     g_free(folder);
    227 
    228     if (mn_conf_get_bool(MN_CONF_SYSTEM_HTTP_PROXY_USE_HTTP_PROXY))
    229       {
    230 	char *host;
    231 
    232 	host = mn_conf_get_string(MN_CONF_SYSTEM_HTTP_PROXY_HOST);
    233 	if (host && *host)
    234 	  {
    235 	    g_string_append_printf(contents, "Proxy = %s:%i\n", host, mn_conf_get_int(MN_CONF_SYSTEM_HTTP_PROXY_PORT));
    236 
    237 	    if (mn_conf_get_bool(MN_CONF_SYSTEM_HTTP_PROXY_USE_AUTHENTICATION))
    238 	      {
    239 		char *user;
    240 		char *password;
    241 
    242 		user = mn_conf_get_string(MN_CONF_SYSTEM_HTTP_PROXY_AUTHENTICATION_USER);
    243 		password = mn_conf_get_string(MN_CONF_SYSTEM_HTTP_PROXY_AUTHENTICATION_PASSWORD);
    244 
    245 		if (user && *user && password && *password)
    246 		  g_string_append_printf(contents, "ProxyAuth = %s:%s\n", user, password);
    247 
    248 		g_free(user);
    249 		g_free(password);
    250 	      }
    251 	  }
    252 	g_free(host);
    253       }
    254 
    255     mn_webmail_mailbox_print_config(MN_WEBMAIL_MAILBOX(self), contents->str);
    256 
    257     /*
    258      * As of this commit:
    259      *
    260      *   http://getlive.cvs.sourceforge.net/getlive/GetLive/GetLive.pl?r1=1.39&r2=1.40
    261      *
    262      * GetLive expects the config file to be encoded in the charset of
    263      * the user's locale.
    264      */
    265     if (getlive_pre_1_40)
    266       charset = "UTF-8";
    267     else
    268       g_get_charset(&charset);
    269 
    270     filename = mn_webmail_mailbox_write_temporary_file(contents->str, charset, err);
    271 
    272     g_string_free(contents, TRUE);
    273 
    274     return filename;
    275   }
    276 
    277   override (MN:Webmail:Mailbox) char *
    278     get_error_message (MNWebmailMailbox *mailbox,
    279 		       const char *helper_stdout,
    280 		       const char *helper_stderr,
    281 		       gboolean *is_auth_failure)
    282   {
    283     if (helper_stderr && mn_ascii_strcasestr(helper_stderr, "error logging in"))
    284       {
    285 	*is_auth_failure = TRUE;
    286 	return g_strdup(_("authentication failed"));
    287       }
    288     return NULL;
    289   }
    290 
    291   private gboolean
    292     run_getlive (self, const char *config_file (check null), GError **err)
    293   {
    294     char *command;
    295     gboolean status;
    296 
    297     command = g_strdup_printf("GetLive --config-file %s", config_file);
    298     status = mn_webmail_mailbox_run_helper(MN_WEBMAIL_MAILBOX(self), "GetLive", command, err);
    299     g_free(command);
    300 
    301     return status;
    302   }
    303 
    304   private gboolean
    305     get_getlive_cvs_revision (int *major (check null), int *minor (check null))
    306   {
    307     char *getlive_stderr;
    308     char **lines;
    309     int i;
    310 
    311     if (! g_spawn_command_line_sync("GetLive --version", NULL, &getlive_stderr, NULL, NULL))
    312       return FALSE;
    313 
    314     lines = g_strsplit(getlive_stderr, "\n", 0);
    315     g_free(getlive_stderr);
    316 
    317     for (i = 0; lines[i]; i++)
    318       {
    319 	char *str;
    320 
    321 	str = mn_strstr_span(lines[i], "GetLive $Revision: ");
    322 	if (str)
    323 	  {
    324 	    char *end;
    325 
    326 	    end = strchr(str, ' ');
    327 	    if (end)
    328 	      {
    329 		char *rev;
    330 		char **versions;
    331 
    332 		rev = g_strndup(str, end - str);
    333 		versions = g_strsplit(rev, ".", 0);
    334 		g_free(rev);
    335 
    336 		if (g_strv_length(versions) >= 2
    337 		    && mn_str_isnumeric(versions[0])
    338 		    && mn_str_isnumeric(versions[1]))
    339 		  {
    340 		    *major = atoi(versions[0]);
    341 		    *minor = atoi(versions[1]);
    342 
    343 		    g_strfreev(versions);
    344 		    g_strfreev(lines);
    345 
    346 		    return TRUE;
    347 		  }
    348 
    349 		g_strfreev(versions);
    350 	      }
    351 	  }
    352       }
    353 
    354     g_strfreev(lines);
    355 
    356     return FALSE;
    357   }
    358 
    359   override (MN:Webmail:Mailbox) gboolean
    360     webmail_check (MNWebmailMailbox *mailbox, GError **err)
    361   {
    362     Self *self = SELF(mailbox);
    363     int getlive_major;
    364     int getlive_minor;
    365     gboolean getlive_pre_1_40;
    366     char *spool_file;
    367     char *config_file = NULL;
    368     gboolean status = FALSE;
    369 
    370     /* see https://sourceforge.net/tracker/?func=detail&atid=948290&aid=1881842&group_id=194154 */
    371     getlive_pre_1_40 = ! self_get_getlive_cvs_revision(&getlive_major, &getlive_minor)
    372       || getlive_major < 1
    373       || (getlive_major == 1 && getlive_minor < 40);
    374 
    375     /*
    376      * We create an empty spool file beforehand to make sure it is not
    377      * world-readable.
    378      */
    379     spool_file = mn_webmail_mailbox_create_spool_file(err);
    380     if (! spool_file)
    381       return FALSE;
    382 
    383     config_file = self_create_config_file(self, spool_file, getlive_pre_1_40, err);
    384     if (! config_file)
    385       goto end;
    386 
    387     if (! self_run_getlive(self, config_file, err))
    388       goto end;
    389 
    390     if (! mn_webmail_mailbox_read_spool_file(mailbox, spool_file, err))
    391       goto end;
    392 
    393     status = TRUE;
    394 
    395   end:
    396     unlink(spool_file);
    397     g_free(spool_file);
    398 
    399     if (config_file)
    400       {
    401 	unlink(config_file);
    402 	g_free(config_file);
    403       }
    404 
    405     return status;
    406   }
    407 }