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 }