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 }