1 /*
2 * Claws Mail -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2016 Hiroyuki Yamamoto and the Claws Mail team
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
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18
19 #ifdef HAVE_CONFIG_H
20 # include "config.h"
21 #include "claws-features.h"
22 #endif
23
24 #include "defs.h"
25
26 #include <glib.h>
27 #include <glib/gi18n.h>
28 #include <gtk/gtk.h>
29 #include <stdio.h>
30 #include <unistd.h>
31 #include <string.h>
32
33 #include "main.h"
34 #include "inc.h"
35 #include "mainwindow.h"
36 #include "folderview.h"
37 #include "summaryview.h"
38 #include "prefs_common.h"
39 #include "prefs_account.h"
40 #include "account.h"
41 #include "procmsg.h"
42 #include "proxy.h"
43 #include "socket.h"
44 #include "ssl.h"
45 #include "pop.h"
46 #include "recv.h"
47 #include "mbox.h"
48 #include "file-utils.h"
49 #include "utils.h"
50 #include "gtkutils.h"
51 #include "statusbar.h"
52 #include "msgcache.h"
53 #include "manage_window.h"
54 #include "stock_pixmap.h"
55 #include "progressdialog.h"
56 #include "inputdialog.h"
57 #include "alertpanel.h"
58 #include "folder.h"
59 #include "filtering.h"
60 #include "log.h"
61 #include "hooks.h"
62 #include "logwindow.h"
63 #include "passwordstore.h"
64 #include "oauth2.h"
65
66 extern SessionStats session_stats;
67
68 static GList *inc_dialog_list = NULL;
69
70 static time_t inc_offline_overridden_yes = 0;
71 static time_t inc_offline_overridden_no = 0;
72
73 guint inc_lock_count = 0;
74
75 static GdkPixbuf *currentpix;
76 static GdkPixbuf *errorpix;
77 static GdkPixbuf *okpix;
78
79 #define MESSAGEBUFSIZE 8192
80
81 static void inc_update_stats(gint new_msgs);
82 static void inc_finished (MainWindow *mainwin,
83 gboolean new_messages,
84 gboolean autocheck);
85 static gint inc_account_mail_real (MainWindow *mainwin,
86 PrefsAccount *account);
87
88 static IncProgressDialog *inc_progress_dialog_create
89 (gboolean autocheck);
90 static void inc_progress_dialog_set_list(IncProgressDialog *inc_dialog);
91 static void inc_progress_dialog_destroy (IncProgressDialog *inc_dialog);
92
93 static IncSession *inc_session_new (PrefsAccount *account);
94 static void inc_session_destroy (IncSession *session);
95 static gint inc_start (IncProgressDialog *inc_dialog);
96 static IncState inc_pop3_session_do (IncSession *session);
97
98 static void inc_progress_dialog_update (IncProgressDialog *inc_dialog,
99 IncSession *inc_session);
100
101 static void inc_progress_dialog_set_label
102 (IncProgressDialog *inc_dialog,
103 IncSession *inc_session);
104 static void inc_progress_dialog_set_progress
105 (IncProgressDialog *inc_dialog,
106 IncSession *inc_session);
107
108 static void inc_progress_dialog_update_periodic
109 (IncProgressDialog *inc_dialog,
110 IncSession *inc_session);
111
112 static gint inc_recv_data_progressive (Session *session,
113 guint cur_len,
114 guint total_len,
115 gpointer data);
116 static gint inc_recv_data_finished (Session *session,
117 guint len,
118 gpointer data);
119 static gint inc_recv_message (Session *session,
120 const gchar *msg,
121 gpointer data);
122 static gint inc_drop_message (Pop3Session *session,
123 const gchar *file);
124
125 static void inc_put_error (IncState istate,
126 Pop3Session *session);
127
128 static void inc_showlog_cb (GtkWidget *widget,
129 gpointer data);
130 static void inc_cancel_cb (GtkWidget *widget,
131 gpointer data);
132 static gint inc_dialog_delete_cb (GtkWidget *widget,
133 GdkEventAny *event,
134 gpointer data);
135
136 static gint get_spool (FolderItem *dest,
137 const gchar *mbox,
138 PrefsAccount *account);
139
140 static gint inc_spool_account(PrefsAccount *account);
141 static void inc_autocheck_timer_set_interval (guint interval);
142 static gint inc_autocheck_func (gpointer data);
143
144 static void inc_notify_cmd (gint new_msgs,
145 gboolean notify);
146
inc_update_stats(gint new_msgs)147 static void inc_update_stats(gint new_msgs)
148 {
149 /* update session statistics */
150 session_stats.received += new_msgs;
151 }
152
153 /**
154 * inc_finished:
155 * @mainwin: Main window.
156 * @new_messages: TRUE if some messages have been received.
157 *
158 * Update the folder view and the summary view after receiving
159 * messages. If @new_messages is FALSE, this function avoids unneeded
160 * updating.
161 **/
inc_finished(MainWindow * mainwin,gboolean new_messages,gboolean autocheck)162 static void inc_finished(MainWindow *mainwin, gboolean new_messages, gboolean autocheck)
163 {
164 if (prefs_common.scan_all_after_inc)
165 folderview_check_new(NULL);
166
167 if (!autocheck && new_messages && prefs_common.open_inbox_on_inc) {
168 FolderItem *item = NULL;
169
170 if (cur_account && cur_account->inbox)
171 item = folder_find_item_from_identifier(cur_account->inbox);
172 if (item == NULL && cur_account && cur_account->folder)
173 item = cur_account->folder->inbox;
174 if (item == NULL)
175 item = folder_get_default_inbox();
176
177 folderview_unselect(mainwin->folderview);
178 folderview_select(mainwin->folderview, item);
179 }
180 statusbar_progress_all(0,0,0);
181 }
182
inc_mail(MainWindow * mainwin,gboolean notify)183 void inc_mail(MainWindow *mainwin, gboolean notify)
184 {
185 gint new_msgs = 0;
186 gint account_new_msgs = 0;
187
188 if (inc_lock_count) return;
189
190 if (prefs_common.work_offline &&
191 !inc_offline_should_override(TRUE,
192 _("Claws Mail needs network access in order "
193 "to get mails.")))
194 return;
195
196 inc_lock();
197 inc_autocheck_timer_remove();
198 main_window_lock(mainwin);
199
200 if (prefs_common.use_extinc && prefs_common.extinc_cmd) {
201 /* external incorporating program */
202 if (execute_command_line(prefs_common.extinc_cmd, FALSE, NULL) < 0) {
203 main_window_unlock(mainwin);
204 inc_autocheck_timer_set();
205 inc_unlock();
206 return;
207 }
208 } else {
209 account_new_msgs = inc_account_mail_real(mainwin, cur_account);
210 if (account_new_msgs > 0)
211 new_msgs += account_new_msgs;
212 }
213
214 inc_update_stats(new_msgs);
215 inc_finished(mainwin, new_msgs > 0, FALSE);
216 main_window_unlock(mainwin);
217 inc_notify_cmd(new_msgs, notify);
218 inc_autocheck_timer_set();
219 inc_unlock();
220 }
221
inc_pop_before_smtp(PrefsAccount * acc)222 void inc_pop_before_smtp(PrefsAccount *acc)
223 {
224 IncProgressDialog *inc_dialog;
225 IncSession *session;
226 MainWindow *mainwin;
227
228 mainwin = mainwindow_get_mainwindow();
229
230 session = inc_session_new(acc);
231 if (!session) return;
232 POP3_SESSION(session->session)->pop_before_smtp = TRUE;
233
234 inc_dialog = inc_progress_dialog_create(FALSE);
235 inc_dialog->queue_list = g_list_append(inc_dialog->queue_list,
236 session);
237 /* FIXME: assumes to attach to first main window */
238 inc_dialog->mainwin = mainwin;
239 inc_progress_dialog_set_list(inc_dialog);
240
241 if (mainwin) {
242 toolbar_main_set_sensitive(mainwin);
243 main_window_set_menu_sensitive(mainwin);
244 }
245
246 inc_start(inc_dialog);
247 }
248
inc_account_mail_real(MainWindow * mainwin,PrefsAccount * account)249 static gint inc_account_mail_real(MainWindow *mainwin, PrefsAccount *account)
250 {
251 IncProgressDialog *inc_dialog;
252 IncSession *session;
253
254 switch (account->protocol) {
255 case A_IMAP4:
256 case A_NNTP:
257 /* Melvin: bug [14]
258 * FIXME: it should return foldeview_check_new() value.
259 * TODO: do it when bug [19] is fixed (IMAP folder sets
260 * an incorrect new message count)
261 */
262 folderview_check_new(FOLDER(account->folder));
263 return 0;
264 case A_POP3:
265 session = inc_session_new(account);
266 if (!session) return 0;
267
268 inc_dialog = inc_progress_dialog_create(FALSE);
269 inc_dialog->queue_list = g_list_append(inc_dialog->queue_list,
270 session);
271 inc_dialog->mainwin = mainwin;
272 inc_progress_dialog_set_list(inc_dialog);
273
274 if (mainwin) {
275 toolbar_main_set_sensitive(mainwin);
276 main_window_set_menu_sensitive(mainwin);
277 }
278
279 return inc_start(inc_dialog);
280
281 case A_LOCAL:
282 return inc_spool_account(account);
283
284 default:
285 break;
286 }
287 return 0;
288 }
289
inc_account_mail(MainWindow * mainwin,PrefsAccount * account)290 gint inc_account_mail(MainWindow *mainwin, PrefsAccount *account)
291 {
292 gint new_msgs;
293
294 if (inc_lock_count) return 0;
295
296 if (account->receive_in_progress) return 0;
297
298 if (prefs_common.work_offline &&
299 !inc_offline_should_override(TRUE,
300 _("Claws Mail needs network access in order "
301 "to get mails.")))
302 return 0;
303
304 inc_autocheck_timer_remove();
305 main_window_lock(mainwin);
306
307 new_msgs = inc_account_mail_real(mainwin, account);
308
309 inc_update_stats(new_msgs);
310 inc_finished(mainwin, new_msgs > 0, FALSE);
311 main_window_unlock(mainwin);
312 inc_autocheck_timer_set();
313
314 return new_msgs;
315 }
316
inc_account_list_mail(MainWindow * mainwin,GList * account_list,gboolean autocheck,gboolean notify)317 void inc_account_list_mail(MainWindow *mainwin, GList *account_list, gboolean autocheck,
318 gboolean notify)
319 {
320 GList *list, *queue_list = NULL;
321 IncProgressDialog *inc_dialog;
322 gint new_msgs = 0, num;
323
324 if (prefs_common.work_offline &&
325 !inc_offline_should_override( (autocheck == FALSE),
326 _("Claws Mail needs network access in order "
327 "to get mails.")))
328 return;
329
330 if (inc_lock_count) return;
331
332 main_window_lock(mainwin);
333
334 if (!account_list) {
335 inc_update_stats(new_msgs);
336 inc_finished(mainwin, new_msgs > 0, autocheck);
337 main_window_unlock(mainwin);
338 inc_notify_cmd(new_msgs, notify);
339 return;
340 }
341
342 if (prefs_common.use_extinc && prefs_common.extinc_cmd) {
343 /* external incorporating program */
344 if (execute_command_line(prefs_common.extinc_cmd, FALSE, NULL) < 0) {
345 log_error(LOG_PROTOCOL, _("%s failed\n"), prefs_common.extinc_cmd);
346
347 main_window_unlock(mainwin);
348 return;
349 }
350 }
351
352 /* Check all accounts in the list, one by one. */
353 for (list = account_list; list != NULL; list = list->next) {
354 PrefsAccount *account = list->data;
355
356 if (account == NULL) {
357 debug_print("INC: Huh? inc_account_list_mail() got a NULL account, this should not happen!\n");
358 continue;
359 }
360
361 debug_print("INC: checking account %d\n", account->account_id);
362 switch (account->protocol) {
363 case A_POP3:
364 if (!(account->receive_in_progress)) {
365 IncSession *session = inc_session_new(account);
366
367 if (session != NULL) {
368 debug_print("INC: adding POP3 account %d to inc queue\n",
369 account->account_id);
370 queue_list = g_list_append(queue_list, session);
371 }
372 }
373 break;
374
375 case A_IMAP4:
376 case A_NNTP:
377 new_msgs += folderview_check_new(FOLDER(account->folder));
378 break;
379
380 case A_LOCAL:
381 num = inc_spool_account(account);
382 if (num > 0)
383 new_msgs += num;
384 break;
385
386 case A_NONE:
387 /* Nothing to do here, it's a SMTP-only account. */
388 break;
389
390 default:
391 debug_print("INC: encountered account %d with unknown protocol %d, ignoring\n",
392 account->account_id, account->protocol);
393 break;
394 }
395 }
396
397
398
399 if (queue_list) {
400 inc_dialog = inc_progress_dialog_create(autocheck);
401 inc_dialog->queue_list = queue_list;
402 inc_dialog->mainwin = mainwin;
403 inc_progress_dialog_set_list(inc_dialog);
404
405 toolbar_main_set_sensitive(mainwin);
406 main_window_set_menu_sensitive(mainwin);
407 new_msgs += inc_start(inc_dialog);
408 }
409
410 inc_update_stats(new_msgs);
411 inc_finished(mainwin, new_msgs > 0, autocheck);
412 main_window_unlock(mainwin);
413 inc_notify_cmd(new_msgs, notify);
414 }
415
inc_all_account_mail(MainWindow * mainwin,gboolean autocheck,gboolean check_at_startup,gboolean notify)416 void inc_all_account_mail(MainWindow *mainwin, gboolean autocheck,
417 gboolean check_at_startup, gboolean notify)
418 {
419 GList *list, *list2 = NULL;
420 gboolean condition;
421 gboolean hide_dialog = FALSE;
422
423 debug_print("INC: inc_all_account_mail(), autocheck: %s\n",
424 autocheck ? "YES" : "NO");
425
426 /* Collect list of accounts which use the global autocheck interval. */
427 for (list = account_get_list(); list != NULL; list = list->next) {
428 PrefsAccount *account = list->data;
429
430 /* Nothing to do for SMTP-only accounts. */
431 if (account->protocol == A_NONE)
432 continue;
433
434 /* Set up condition which decides whether or not to check
435 * this account, based on whether we're doing global autocheck
436 * or a check at startup or a manual 'Get all' check. */
437 if (autocheck)
438 condition = prefs_common_get_prefs()->autochk_newmail
439 && account->autochk_use_default;
440 else if (check_at_startup || (!check_at_startup && !autocheck))
441 condition = account->recv_at_getall;
442
443 if (condition) {
444 debug_print("INC: will check account %d\n", account->account_id);
445 list2 = g_list_append(list2, account);
446 }
447 }
448
449 /* Do the check on the collected accounts. */
450 if (list2 != NULL) {
451 if (autocheck || check_at_startup)
452 hide_dialog = TRUE;
453 inc_account_list_mail(mainwin, list2, hide_dialog, notify);
454 g_list_free(list2);
455 }
456 }
457
inc_progress_dialog_size_allocate_cb(GtkWidget * widget,GtkAllocation * allocation)458 static void inc_progress_dialog_size_allocate_cb(GtkWidget *widget,
459 GtkAllocation *allocation)
460 {
461 cm_return_if_fail(allocation != NULL);
462
463 prefs_common.receivewin_width = allocation->width;
464 prefs_common.receivewin_height = allocation->height;
465 }
466
inc_progress_dialog_create(gboolean autocheck)467 static IncProgressDialog *inc_progress_dialog_create(gboolean autocheck)
468 {
469 IncProgressDialog *dialog;
470 ProgressDialog *progress;
471 static GdkGeometry geometry;
472
473 dialog = g_new0(IncProgressDialog, 1);
474
475 progress = progress_dialog_create();
476 gtk_window_set_title(GTK_WINDOW(progress->window),
477 _("Retrieving new messages"));
478 g_signal_connect(G_OBJECT(progress->showlog_btn), "clicked",
479 G_CALLBACK(inc_showlog_cb), dialog);
480 g_signal_connect(G_OBJECT(progress->cancel_btn), "clicked",
481 G_CALLBACK(inc_cancel_cb), dialog);
482 g_signal_connect(G_OBJECT(progress->window), "delete_event",
483 G_CALLBACK(inc_dialog_delete_cb), dialog);
484 g_signal_connect(G_OBJECT(progress->window), "size_allocate",
485 G_CALLBACK(inc_progress_dialog_size_allocate_cb), NULL);
486 /* manage_window_set_transient(GTK_WINDOW(progress->window)); */
487
488 progress_dialog_get_fraction(progress);
489
490 stock_pixbuf_gdk(STOCK_PIXMAP_COMPLETE, &okpix);
491 stock_pixbuf_gdk(STOCK_PIXMAP_CONTINUE, ¤tpix);
492 stock_pixbuf_gdk(STOCK_PIXMAP_ERROR, &errorpix);
493
494 if (!geometry.min_height) {
495 geometry.min_width = 460;
496 geometry.min_height = 250;
497 }
498
499 gtk_window_set_geometry_hints(GTK_WINDOW(progress->window), NULL, &geometry,
500 GDK_HINT_MIN_SIZE);
501 gtk_widget_set_size_request(progress->window, prefs_common.receivewin_width,
502 prefs_common.receivewin_height);
503
504 if (prefs_common.recv_dialog_mode == RECV_DIALOG_ALWAYS ||
505 (prefs_common.recv_dialog_mode == RECV_DIALOG_MANUAL &&
506 !autocheck)) {
507 dialog->show_dialog = TRUE;
508 gtk_widget_show_now(progress->window);
509 }
510
511 dialog->dialog = progress;
512 dialog->progress_tv = g_date_time_new_now_local();
513 dialog->folder_tv = g_date_time_new_now_local();
514 dialog->queue_list = NULL;
515 dialog->cur_row = 0;
516
517 inc_dialog_list = g_list_append(inc_dialog_list, dialog);
518
519 return dialog;
520 }
521
inc_progress_dialog_set_list(IncProgressDialog * inc_dialog)522 static void inc_progress_dialog_set_list(IncProgressDialog *inc_dialog)
523 {
524 GList *list;
525
526 for (list = inc_dialog->queue_list; list != NULL; list = list->next) {
527 IncSession *session = list->data;
528 Pop3Session *pop3_session = POP3_SESSION(session->session);
529
530 session->data = inc_dialog;
531
532 progress_dialog_list_set(inc_dialog->dialog,
533 -1, NULL,
534 pop3_session->ac_prefs->account_name,
535 _("Standby"));
536 }
537 }
538
inc_progress_dialog_clear(IncProgressDialog * inc_dialog)539 static void inc_progress_dialog_clear(IncProgressDialog *inc_dialog)
540 {
541 progress_dialog_get_fraction(inc_dialog->dialog);
542 progress_dialog_set_label(inc_dialog->dialog, "");
543 if (inc_dialog->mainwin)
544 main_window_progress_off(inc_dialog->mainwin);
545 }
546
inc_progress_dialog_destroy(IncProgressDialog * inc_dialog)547 static void inc_progress_dialog_destroy(IncProgressDialog *inc_dialog)
548 {
549 cm_return_if_fail(inc_dialog != NULL);
550
551 inc_dialog_list = g_list_remove(inc_dialog_list, inc_dialog);
552
553 if (inc_dialog->mainwin)
554 main_window_progress_off(inc_dialog->mainwin);
555 progress_dialog_destroy(inc_dialog->dialog);
556
557 g_date_time_unref(inc_dialog->progress_tv);
558 g_date_time_unref(inc_dialog->folder_tv);
559
560 g_free(inc_dialog);
561 }
562
inc_session_new(PrefsAccount * account)563 static IncSession *inc_session_new(PrefsAccount *account)
564 {
565 IncSession *session;
566
567 cm_return_val_if_fail(account != NULL, NULL);
568
569 if (account->protocol != A_POP3)
570 return NULL;
571 if (!account->recv_server || !account->userid)
572 return NULL;
573
574 session = g_new0(IncSession, 1);
575
576 session->session = pop3_session_new(account);
577 session->session->data = session;
578 POP3_SESSION(session->session)->drop_message = inc_drop_message;
579 session_set_recv_message_notify(session->session,
580 inc_recv_message, session);
581 session_set_recv_data_progressive_notify(session->session,
582 inc_recv_data_progressive,
583 session);
584 session_set_recv_data_notify(session->session,
585 inc_recv_data_finished, session);
586
587 return session;
588 }
589
inc_session_destroy(IncSession * session)590 static void inc_session_destroy(IncSession *session)
591 {
592 cm_return_if_fail(session != NULL);
593
594 session_destroy(session->session);
595 g_free(session);
596 }
597
pop3_get_port(Pop3Session * pop3_session)598 static gint pop3_get_port(Pop3Session *pop3_session)
599 {
600 #ifdef USE_GNUTLS
601 return pop3_session->ac_prefs->set_popport ?
602 pop3_session->ac_prefs->popport :
603 pop3_session->ac_prefs->ssl_pop == SSL_TUNNEL ? 995 : 110;
604 #else
605 return pop3_session->ac_prefs->set_popport ?
606 pop3_session->ac_prefs->popport : 110;
607 #endif
608 }
609
inc_start(IncProgressDialog * inc_dialog)610 static gint inc_start(IncProgressDialog *inc_dialog)
611 {
612 IncSession *session;
613 GList *qlist;
614 Pop3Session *pop3_session;
615 IncState inc_state;
616 gint error_num = 0;
617 gint new_msgs = 0;
618 gchar *msg;
619 gchar *fin_msg;
620 FolderItem *processing, *inbox;
621 GSList *msglist, *msglist_element;
622 gboolean cancelled = FALSE;
623
624 qlist = inc_dialog->queue_list;
625 while (qlist != NULL) {
626 GList *next = qlist->next;
627
628 session = qlist->data;
629 pop3_session = POP3_SESSION(session->session);
630 pop3_session->user = g_strdup(pop3_session->ac_prefs->userid);
631
632 if (inc_dialog->show_dialog)
633 manage_window_focus_in
634 (inc_dialog->dialog->window,
635 NULL, NULL);
636
637 if(pop3_session->ac_prefs->use_pop_auth &&
638 pop3_session->ac_prefs->pop_auth_type == POPAUTH_OAUTH2)
639 oauth2_check_passwds (pop3_session->ac_prefs);
640
641 if (password_get(pop3_session->user,
642 pop3_session->ac_prefs->recv_server,
643 "pop3", pop3_get_port(pop3_session),
644 &(pop3_session->pass))) {
645 /* NOP */;
646 } else if ((pop3_session->pass = passwd_store_get_account(
647 pop3_session->ac_prefs->account_id, PWS_ACCOUNT_RECV)) == NULL) {
648 gchar *pass;
649
650 pass = input_dialog_query_password_keep
651 (pop3_session->ac_prefs->recv_server,
652 pop3_session->user,
653 &(pop3_session->ac_prefs->session_passwd));
654
655 if (pass) {
656 pop3_session->pass = pass;
657 }
658 }
659
660 if (inc_dialog->show_dialog)
661 manage_window_focus_out
662 (inc_dialog->dialog->window,
663 NULL, NULL);
664
665 qlist = next;
666 }
667
668 #define SET_PIXMAP_AND_TEXT(pix, str) \
669 { \
670 progress_dialog_list_set(inc_dialog->dialog, \
671 inc_dialog->cur_row, \
672 pix, \
673 NULL, \
674 str); \
675 }
676
677 for (; inc_dialog->queue_list != NULL && !cancelled; inc_dialog->cur_row++) {
678 session = inc_dialog->queue_list->data;
679 pop3_session = POP3_SESSION(session->session);
680 GSList *filtered, *unfiltered;
681
682 if (pop3_session->pass == NULL) {
683 SET_PIXMAP_AND_TEXT(okpix, _("Cancelled"));
684 inc_session_destroy(session);
685 inc_dialog->queue_list =
686 g_list_remove(inc_dialog->queue_list, session);
687 continue;
688 }
689
690 inc_progress_dialog_clear(inc_dialog);
691 progress_dialog_scroll_to_row(inc_dialog->dialog,
692 inc_dialog->cur_row);
693
694 SET_PIXMAP_AND_TEXT(currentpix, _("Retrieving"));
695
696 /* begin POP3 session */
697 inc_state = inc_pop3_session_do(session);
698
699 switch (inc_state) {
700 case INC_SUCCESS:
701 if (pop3_session->cur_total_num > 0)
702 msg = g_strdup_printf(
703 ngettext("Done (%d message (%s) received)",
704 "Done (%d messages (%s) received)",
705 pop3_session->cur_total_num),
706 pop3_session->cur_total_num,
707 to_human_readable((goffset)pop3_session->cur_total_recv_bytes));
708 else
709 msg = g_strdup_printf(_("Done (no new messages)"));
710 SET_PIXMAP_AND_TEXT(okpix, msg);
711 g_free(msg);
712 break;
713 case INC_CONNECT_ERROR:
714 SET_PIXMAP_AND_TEXT(errorpix, _("Connection failed"));
715 break;
716 case INC_AUTH_FAILED:
717 SET_PIXMAP_AND_TEXT(errorpix, _("Auth failed"));
718 if (pop3_session->ac_prefs->session_passwd) {
719 g_free(pop3_session->ac_prefs->session_passwd);
720 pop3_session->ac_prefs->session_passwd = NULL;
721 }
722 break;
723 case INC_LOCKED:
724 SET_PIXMAP_AND_TEXT(errorpix, _("Locked"));
725 break;
726 case INC_ERROR:
727 case INC_NO_SPACE:
728 case INC_IO_ERROR:
729 case INC_SOCKET_ERROR:
730 case INC_EOF:
731 SET_PIXMAP_AND_TEXT(errorpix, _("Error"));
732 break;
733 case INC_TIMEOUT:
734 SET_PIXMAP_AND_TEXT(errorpix, _("Timeout"));
735 break;
736 case INC_CANCEL:
737 SET_PIXMAP_AND_TEXT(okpix, _("Cancelled"));
738 if (!inc_dialog->show_dialog)
739 cancelled = TRUE;
740 break;
741 default:
742 break;
743 }
744
745 if (pop3_session->error_val == PS_AUTHFAIL) {
746 if(!prefs_common.no_recv_err_panel) {
747 if((prefs_common.recv_dialog_mode == RECV_DIALOG_ALWAYS) ||
748 ((prefs_common.recv_dialog_mode == RECV_DIALOG_MANUAL) && focus_window))
749 manage_window_focus_in(inc_dialog->dialog->window, NULL, NULL);
750 }
751 }
752
753 /* CLAWS: perform filtering actions on dropped message */
754 /* CLAWS: get default inbox (perhaps per account) */
755 if (pop3_session->ac_prefs->inbox) {
756 /* CLAWS: get destination folder / mailbox */
757 inbox = folder_find_item_from_identifier(pop3_session->ac_prefs->inbox);
758 if (!inbox)
759 inbox = folder_get_default_inbox();
760 } else
761 inbox = folder_get_default_inbox();
762
763 /* get list of messages in processing */
764 processing = folder_get_default_processing(pop3_session->ac_prefs->account_id);
765 folder_item_scan(processing);
766 msglist = folder_item_get_msg_list(processing);
767
768 /* process messages */
769 folder_item_update_freeze();
770
771 procmsg_msglist_filter(msglist, pop3_session->ac_prefs,
772 &filtered, &unfiltered,
773 pop3_session->ac_prefs->filter_on_recv);
774
775 filtering_move_and_copy_msgs(msglist);
776 if (unfiltered != NULL)
777 folder_item_move_msgs(inbox, unfiltered);
778
779 for(msglist_element = msglist; msglist_element != NULL;
780 msglist_element = msglist_element->next) {
781 procmsg_msginfo_free((MsgInfo**)&(msglist_element->data));
782 }
783 folder_item_update_thaw();
784
785 g_slist_free(msglist);
786 g_slist_free(filtered);
787 g_slist_free(unfiltered);
788
789 statusbar_pop_all();
790
791 new_msgs += pop3_session->cur_total_num;
792
793 pop3_write_uidl_list(pop3_session);
794
795 if (inc_state != INC_SUCCESS && inc_state != INC_CANCEL) {
796 error_num++;
797 if (inc_dialog->show_dialog)
798 manage_window_focus_in
799 (inc_dialog->dialog->window,
800 NULL, NULL);
801 inc_put_error(inc_state, pop3_session);
802 if (inc_dialog->show_dialog)
803 manage_window_focus_out
804 (inc_dialog->dialog->window,
805 NULL, NULL);
806 if (inc_state == INC_NO_SPACE ||
807 inc_state == INC_IO_ERROR)
808 break;
809 }
810 folder_item_free_cache(processing, TRUE);
811
812 inc_session_destroy(session);
813 inc_dialog->queue_list =
814 g_list_remove(inc_dialog->queue_list, session);
815 }
816
817 #undef SET_PIXMAP_AND_TEXT
818
819 if (new_msgs > 0)
820 fin_msg = g_strdup_printf(ngettext("Finished (%d new message)",
821 "Finished (%d new messages)",
822 new_msgs), new_msgs);
823 else
824 fin_msg = g_strdup_printf(_("Finished (no new messages)"));
825
826 progress_dialog_set_label(inc_dialog->dialog, fin_msg);
827
828 while (inc_dialog->queue_list != NULL) {
829 session = inc_dialog->queue_list->data;
830 inc_session_destroy(session);
831 inc_dialog->queue_list =
832 g_list_remove(inc_dialog->queue_list, session);
833 }
834
835 if (prefs_common.close_recv_dialog || !inc_dialog->show_dialog)
836 inc_progress_dialog_destroy(inc_dialog);
837 else {
838 gtk_window_set_title(GTK_WINDOW(inc_dialog->dialog->window),
839 fin_msg);
840 gtk_button_set_label(GTK_BUTTON(inc_dialog->dialog->cancel_btn),
841 GTK_STOCK_CLOSE);
842 }
843
844 g_free(fin_msg);
845
846 return new_msgs;
847 }
848
inc_pop3_session_do(IncSession * session)849 static IncState inc_pop3_session_do(IncSession *session)
850 {
851 Pop3Session *pop3_session = POP3_SESSION(session->session);
852 IncProgressDialog *inc_dialog = (IncProgressDialog *)session->data;
853 PrefsAccount *ac = pop3_session->ac_prefs;
854 gchar *server;
855 gchar *account_name;
856 gushort port;
857 gchar *buf;
858 ProxyInfo *proxy_info = NULL;
859
860 debug_print("getting new messages of account %s...\n",
861 ac->account_name);
862
863 ac->last_pop_login_time = time(NULL);
864
865 buf = g_strdup_printf(_("%s: Retrieving new messages"),
866 ac->recv_server);
867 gtk_window_set_title(GTK_WINDOW(inc_dialog->dialog->window), buf);
868 g_free(buf);
869
870 server = ac->recv_server;
871 account_name = ac->account_name;
872 port = pop3_get_port(pop3_session);
873
874 #ifdef USE_GNUTLS
875 SESSION(pop3_session)->ssl_type = ac->ssl_pop;
876 if (ac->ssl_pop != SSL_NONE)
877 SESSION(pop3_session)->nonblocking =
878 ac->use_nonblocking_ssl;
879 #else
880 if (ac->ssl_pop != SSL_NONE) {
881 if (alertpanel_full(_("Insecure connection"),
882 _("This connection is configured to be secured "
883 "using SSL/TLS, but SSL/TLS is not available "
884 "in this build of Claws Mail. \n\n"
885 "Do you want to continue connecting to this "
886 "server? The communication would not be "
887 "secure."),
888 GTK_STOCK_CANCEL, _("Con_tinue connecting"), NULL,
889 ALERTFOCUS_FIRST, FALSE, NULL, ALERT_WARNING) != G_ALERTALTERNATE)
890 return INC_CANCEL;
891 }
892 #endif
893
894 buf = g_strdup_printf(_("Account '%s': Connecting to POP3 server: %s:%d..."),
895 account_name, server, port);
896 statusbar_print_all("%s", buf);
897 log_message(LOG_PROTOCOL, "%s\n", buf);
898
899 progress_dialog_set_label(inc_dialog->dialog, buf);
900
901 if (ac->use_proxy) {
902 if (ac->use_default_proxy) {
903 proxy_info = (ProxyInfo *)&(prefs_common.proxy_info);
904 if (proxy_info->use_proxy_auth)
905 proxy_info->proxy_pass = passwd_store_get(PWS_CORE, PWS_CORE_PROXY,
906 PWS_CORE_PROXY_PASS);
907 } else {
908 proxy_info = (ProxyInfo *)&(ac->proxy_info);
909 if (proxy_info->use_proxy_auth)
910 proxy_info->proxy_pass = passwd_store_get_account(ac->account_id,
911 PWS_ACCOUNT_PROXY_PASS);
912 }
913 }
914 SESSION(pop3_session)->proxy_info = proxy_info;
915
916 GTK_EVENTS_FLUSH();
917 g_free(buf);
918
919 session_set_timeout(SESSION(pop3_session),
920 prefs_common.io_timeout_secs * 1000);
921
922 if (session_connect(SESSION(pop3_session), server, port) < 0) {
923 if(!prefs_common.no_recv_err_panel) {
924 if((prefs_common.recv_dialog_mode == RECV_DIALOG_ALWAYS) ||
925 ((prefs_common.recv_dialog_mode == RECV_DIALOG_MANUAL) && focus_window)) {
926 manage_window_focus_in(inc_dialog->dialog->window, NULL, NULL);
927 }
928 alertpanel_error(_("Can't connect to POP3 server: %s:%d"),
929 server, port);
930 manage_window_focus_out(inc_dialog->dialog->window, NULL, NULL);
931 } else {
932 log_error(LOG_PROTOCOL, _("Can't connect to POP3 server: %s:%d\n"),
933 server, port);
934 }
935 session->inc_state = INC_CONNECT_ERROR;
936 statusbar_pop_all();
937 return INC_CONNECT_ERROR;
938 }
939
940 while (session_is_running(SESSION(pop3_session)) &&
941 session->inc_state != INC_CANCEL)
942 gtk_main_iteration();
943
944 if (session->inc_state == INC_SUCCESS) {
945 switch (pop3_session->error_val) {
946 case PS_SUCCESS:
947 switch (SESSION(pop3_session)->state) {
948 case SESSION_ERROR:
949 if (pop3_session->state == POP3_READY)
950 session->inc_state = INC_CONNECT_ERROR;
951 else
952 session->inc_state = INC_ERROR;
953 break;
954 case SESSION_EOF:
955 session->inc_state = INC_EOF;
956 break;
957 case SESSION_TIMEOUT:
958 session->inc_state = INC_TIMEOUT;
959 break;
960 default:
961 session->inc_state = INC_SUCCESS;
962 break;
963 }
964 break;
965 case PS_AUTHFAIL:
966 session->inc_state = INC_AUTH_FAILED;
967 break;
968 case PS_IOERR:
969 session->inc_state = INC_IO_ERROR;
970 break;
971 case PS_SOCKET:
972 session->inc_state = INC_SOCKET_ERROR;
973 break;
974 case PS_LOCKBUSY:
975 session->inc_state = INC_LOCKED;
976 break;
977 default:
978 session->inc_state = INC_ERROR;
979 break;
980 }
981 }
982
983 session_disconnect(SESSION(pop3_session));
984 statusbar_pop_all();
985
986 return session->inc_state;
987 }
988
inc_progress_dialog_update(IncProgressDialog * inc_dialog,IncSession * inc_session)989 static void inc_progress_dialog_update(IncProgressDialog *inc_dialog,
990 IncSession *inc_session)
991 {
992 inc_progress_dialog_set_label(inc_dialog, inc_session);
993 inc_progress_dialog_set_progress(inc_dialog, inc_session);
994 }
995
inc_progress_dialog_set_label(IncProgressDialog * inc_dialog,IncSession * inc_session)996 static void inc_progress_dialog_set_label(IncProgressDialog *inc_dialog,
997 IncSession *inc_session)
998 {
999 ProgressDialog *dialog = inc_dialog->dialog;
1000 Pop3Session *session;
1001
1002 cm_return_if_fail(inc_session != NULL);
1003
1004 session = POP3_SESSION(inc_session->session);
1005
1006 switch (session->state) {
1007 case POP3_GREETING:
1008 break;
1009 case POP3_GETAUTH_USER:
1010 case POP3_GETAUTH_PASS:
1011 case POP3_GETAUTH_APOP:
1012 progress_dialog_set_label(dialog, _("Authenticating..."));
1013 statusbar_pop_all();
1014 statusbar_print_all(_("Retrieving messages from %s (%s)..."),
1015 SESSION(session)->server,
1016 session->ac_prefs->account_name);
1017 break;
1018 case POP3_GETRANGE_STAT:
1019 progress_dialog_set_label
1020 (dialog, _("Getting the number of new messages (STAT)..."));
1021 break;
1022 case POP3_GETRANGE_LAST:
1023 progress_dialog_set_label
1024 (dialog, _("Getting the number of new messages (LAST)..."));
1025 break;
1026 case POP3_GETRANGE_UIDL:
1027 progress_dialog_set_label
1028 (dialog, _("Getting the number of new messages (UIDL)..."));
1029 break;
1030 case POP3_GETSIZE_LIST:
1031 progress_dialog_set_label
1032 (dialog, _("Getting the size of messages (LIST)..."));
1033 break;
1034 case POP3_RETR:
1035 case POP3_RETR_RECV:
1036 case POP3_DELETE:
1037 break;
1038 case POP3_LOGOUT:
1039 progress_dialog_set_label(dialog, _("Quitting"));
1040 break;
1041 default:
1042 break;
1043 }
1044 }
1045
inc_progress_dialog_set_progress(IncProgressDialog * inc_dialog,IncSession * inc_session)1046 static void inc_progress_dialog_set_progress(IncProgressDialog *inc_dialog,
1047 IncSession *inc_session)
1048 {
1049 gchar buf[MESSAGEBUFSIZE];
1050 Pop3Session *pop3_session = POP3_SESSION(inc_session->session);
1051 gchar *total_size_str;
1052 gint cur_total;
1053 gint total;
1054
1055 if (!pop3_session->new_msg_exist) return;
1056
1057 cur_total = inc_session->cur_total_bytes;
1058 total = pop3_session->total_bytes;
1059 if (pop3_session->state == POP3_RETR ||
1060 pop3_session->state == POP3_RETR_RECV ||
1061 pop3_session->state == POP3_DELETE) {
1062 Xstrdup_a(total_size_str, to_human_readable((goffset)total), return);
1063 g_snprintf(buf, sizeof(buf),
1064 _("Retrieving message (%d / %d) (%s / %s)"),
1065 pop3_session->cur_msg, pop3_session->count,
1066 to_human_readable((goffset)cur_total), total_size_str);
1067 progress_dialog_set_label(inc_dialog->dialog, buf);
1068 }
1069
1070 progress_dialog_set_fraction
1071 (inc_dialog->dialog, (total == 0) ? 0: (gfloat)cur_total / (gfloat)total);
1072
1073 statusbar_progress_all(pop3_session->cur_msg, pop3_session->count, 1);
1074
1075 if (pop3_session->cur_total_num > 0) {
1076 g_snprintf(buf, sizeof(buf),
1077 ngettext("Retrieving (%d message (%s) received)",
1078 "Retrieving (%d messages (%s) received)",
1079 pop3_session->cur_total_num),
1080 pop3_session->cur_total_num,
1081 to_human_readable
1082 ((goffset)pop3_session->cur_total_recv_bytes));
1083 progress_dialog_list_set_status(inc_dialog->dialog,
1084 inc_dialog->cur_row,
1085 buf);
1086 }
1087 }
1088
inc_progress_dialog_update_periodic(IncProgressDialog * inc_dialog,IncSession * inc_session)1089 static void inc_progress_dialog_update_periodic(IncProgressDialog *inc_dialog,
1090 IncSession *inc_session)
1091 {
1092 GDateTime *tv_cur = g_date_time_new_now_local();
1093 GTimeSpan tv_result;
1094
1095 tv_result = g_date_time_difference(tv_cur, inc_dialog->progress_tv);
1096 g_date_time_unref(tv_cur);
1097 if (tv_result < 0) {
1098 tv_result += G_USEC_PER_SEC;
1099 }
1100
1101 if (tv_result > PROGRESS_UPDATE_INTERVAL) {
1102 inc_progress_dialog_update(inc_dialog, inc_session);
1103 tv_cur = g_date_time_add(inc_dialog->progress_tv, tv_result);
1104 g_date_time_unref(inc_dialog->progress_tv);
1105 inc_dialog->progress_tv = tv_cur;
1106 }
1107 }
1108
inc_recv_data_progressive(Session * session,guint cur_len,guint total_len,gpointer data)1109 static gint inc_recv_data_progressive(Session *session, guint cur_len,
1110 guint total_len, gpointer data)
1111 {
1112 IncSession *inc_session = (IncSession *)data;
1113 Pop3Session *pop3_session = POP3_SESSION(session);
1114 IncProgressDialog *inc_dialog;
1115 gint cur_total;
1116
1117 cm_return_val_if_fail(inc_session != NULL, -1);
1118
1119 if (pop3_session->state != POP3_RETR &&
1120 pop3_session->state != POP3_RETR_RECV &&
1121 pop3_session->state != POP3_DELETE &&
1122 pop3_session->state != POP3_LOGOUT) return 0;
1123
1124 if (!pop3_session->new_msg_exist) return 0;
1125
1126 cur_total = pop3_session->cur_total_bytes + cur_len;
1127 if (cur_total > pop3_session->total_bytes)
1128 cur_total = pop3_session->total_bytes;
1129 inc_session->cur_total_bytes = cur_total;
1130
1131 inc_dialog = (IncProgressDialog *)inc_session->data;
1132 inc_progress_dialog_update_periodic(inc_dialog, inc_session);
1133
1134 return 0;
1135 }
1136
inc_recv_data_finished(Session * session,guint len,gpointer data)1137 static gint inc_recv_data_finished(Session *session, guint len, gpointer data)
1138 {
1139 IncSession *inc_session = (IncSession *)data;
1140 IncProgressDialog *inc_dialog;
1141
1142 cm_return_val_if_fail(inc_session != NULL, -1);
1143
1144 inc_dialog = (IncProgressDialog *)inc_session->data;
1145
1146 inc_recv_data_progressive(session, 0, 0, inc_session);
1147
1148 if (POP3_SESSION(session)->state == POP3_LOGOUT) {
1149 inc_progress_dialog_update(inc_dialog, inc_session);
1150 }
1151
1152 return 0;
1153 }
1154
inc_recv_message(Session * session,const gchar * msg,gpointer data)1155 static gint inc_recv_message(Session *session, const gchar *msg, gpointer data)
1156 {
1157 IncSession *inc_session = (IncSession *)data;
1158 IncProgressDialog *inc_dialog;
1159
1160 cm_return_val_if_fail(inc_session != NULL, -1);
1161
1162 inc_dialog = (IncProgressDialog *)inc_session->data;
1163
1164 switch (POP3_SESSION(session)->state) {
1165 case POP3_GETAUTH_USER:
1166 case POP3_GETAUTH_PASS:
1167 case POP3_GETAUTH_APOP:
1168 case POP3_GETRANGE_STAT:
1169 case POP3_GETRANGE_LAST:
1170 case POP3_GETRANGE_UIDL:
1171 case POP3_GETSIZE_LIST:
1172 inc_progress_dialog_update(inc_dialog, inc_session);
1173 break;
1174 case POP3_RETR:
1175 inc_recv_data_progressive(session, 0, 0, inc_session);
1176 break;
1177 case POP3_LOGOUT:
1178 inc_progress_dialog_update(inc_dialog, inc_session);
1179 break;
1180 default:
1181 break;
1182 }
1183
1184 return 0;
1185 }
1186
inc_drop_message(Pop3Session * session,const gchar * file)1187 static gint inc_drop_message(Pop3Session *session, const gchar *file)
1188 {
1189 FolderItem *inbox;
1190 FolderItem *dropfolder;
1191 IncSession *inc_session = (IncSession *)(SESSION(session)->data);
1192 gint msgnum;
1193
1194 cm_return_val_if_fail(inc_session != NULL, -1);
1195
1196 if (session->ac_prefs->inbox) {
1197 inbox = folder_find_item_from_identifier
1198 (session->ac_prefs->inbox);
1199 if (!inbox)
1200 inbox = folder_get_default_inbox();
1201 } else
1202 inbox = folder_get_default_inbox();
1203 if (!inbox) {
1204 claws_unlink(file);
1205 return -1;
1206 }
1207
1208 /* CLAWS: claws uses a global .processing folder for the filtering. */
1209 dropfolder = folder_get_default_processing(session->ac_prefs->account_id);
1210
1211 /* add msg file to drop folder */
1212 if ((msgnum = folder_item_add_msg(
1213 dropfolder, file, NULL, TRUE)) < 0) {
1214 claws_unlink(file);
1215 return -1;
1216 }
1217
1218 return 0;
1219 }
1220
inc_put_error(IncState istate,Pop3Session * session)1221 static void inc_put_error(IncState istate, Pop3Session *session)
1222 {
1223 gchar *log_msg = NULL;
1224 gchar *err_msg = NULL;
1225 gboolean fatal_error = FALSE;
1226
1227 switch (istate) {
1228 case INC_CONNECT_ERROR:
1229 fatal_error = TRUE;
1230 if (prefs_common.no_recv_err_panel)
1231 break;
1232 err_msg = g_strdup_printf(_("Connection to %s:%d failed."),
1233 SESSION(session)->server,
1234 SESSION(session)->port);
1235 break;
1236 case INC_ERROR:
1237 log_msg = _("Error occurred while processing mail.");
1238 fatal_error = TRUE;
1239 if (prefs_common.no_recv_err_panel)
1240 break;
1241 if (session->error_msg)
1242 err_msg = g_strdup_printf
1243 (_("Error occurred while processing mail:\n%s"),
1244 session->error_msg);
1245 else
1246 err_msg = g_strdup(log_msg);
1247 break;
1248 case INC_NO_SPACE:
1249 log_msg = _("No disk space left.");
1250 err_msg = g_strdup(log_msg);
1251 fatal_error = TRUE;
1252 break;
1253 case INC_IO_ERROR:
1254 log_msg = _("Can't write file.");
1255 err_msg = g_strdup(log_msg);
1256 fatal_error = TRUE;
1257 break;
1258 case INC_SOCKET_ERROR:
1259 log_msg = _("Socket error.");
1260 if (prefs_common.no_recv_err_panel)
1261 break;
1262 err_msg = g_strdup_printf(_("Socket error on connection to %s:%d."),
1263 SESSION(session)->server,
1264 SESSION(session)->port);
1265 break;
1266 case INC_EOF:
1267 log_msg = _("Connection closed by the remote host.");
1268 if (prefs_common.no_recv_err_panel)
1269 break;
1270 err_msg = g_strdup_printf(_("Connection to %s:%d closed by the remote host."),
1271 SESSION(session)->server,
1272 SESSION(session)->port);
1273 break;
1274 case INC_LOCKED:
1275 log_msg = _("Mailbox is locked.");
1276 if (prefs_common.no_recv_err_panel)
1277 break;
1278 if (session->error_msg)
1279 err_msg = g_strdup_printf(_("Mailbox is locked:\n%s"),
1280 session->error_msg);
1281 else
1282 err_msg = g_strdup(log_msg);
1283 break;
1284 case INC_AUTH_FAILED:
1285 log_msg = _("Authentication failed.");
1286 fatal_error = TRUE;
1287 if (prefs_common.no_recv_err_panel)
1288 break;
1289 if (session->error_msg)
1290 err_msg = g_strdup_printf
1291 (_("Authentication failed:\n%s"), session->error_msg);
1292 else
1293 err_msg = g_strdup(log_msg);
1294 break;
1295 case INC_TIMEOUT:
1296 log_msg = _("Session timed out. You may be able to "
1297 "recover by increasing the timeout value in "
1298 "Preferences/Other/Miscellaneous.");
1299 if (prefs_common.no_recv_err_panel)
1300 break;
1301 err_msg = g_strdup_printf(_("Connection to %s:%d timed out."),
1302 SESSION(session)->server,
1303 SESSION(session)->port);
1304 break;
1305 default:
1306 break;
1307 }
1308
1309 if (log_msg) {
1310 if (fatal_error)
1311 log_error(LOG_PROTOCOL, "%s\n", log_msg);
1312 else
1313 log_warning(LOG_PROTOCOL, "%s\n", log_msg);
1314 }
1315 if (prefs_common.no_recv_err_panel && fatal_error)
1316 mainwindow_show_error();
1317
1318 if (err_msg) {
1319 alertpanel_error_log("%s", err_msg);
1320 g_free(err_msg);
1321 }
1322 }
1323
inc_cancel(IncProgressDialog * dialog)1324 static void inc_cancel(IncProgressDialog *dialog)
1325 {
1326 IncSession *session;
1327
1328 cm_return_if_fail(dialog != NULL);
1329
1330 if (dialog->queue_list == NULL) {
1331 inc_progress_dialog_destroy(dialog);
1332 return;
1333 }
1334
1335 session = dialog->queue_list->data;
1336
1337 session->inc_state = INC_CANCEL;
1338
1339 log_message(LOG_PROTOCOL, _("Incorporation cancelled\n"));
1340 }
1341
inc_is_active(void)1342 gboolean inc_is_active(void)
1343 {
1344 return (inc_dialog_list != NULL);
1345 }
1346
inc_cancel_all(void)1347 void inc_cancel_all(void)
1348 {
1349 GList *cur;
1350
1351 for (cur = inc_dialog_list; cur != NULL; cur = cur->next)
1352 inc_cancel((IncProgressDialog *)cur->data);
1353 }
1354
inc_showlog_cb(GtkWidget * widget,gpointer data)1355 static void inc_showlog_cb(GtkWidget *widget, gpointer data)
1356 {
1357 MainWindow *mainwin = mainwindow_get_mainwindow();
1358
1359 log_window_show(mainwin->logwin);
1360 }
1361
inc_cancel_cb(GtkWidget * widget,gpointer data)1362 static void inc_cancel_cb(GtkWidget *widget, gpointer data)
1363 {
1364 inc_cancel((IncProgressDialog *)data);
1365 }
1366
inc_dialog_delete_cb(GtkWidget * widget,GdkEventAny * event,gpointer data)1367 static gint inc_dialog_delete_cb(GtkWidget *widget, GdkEventAny *event,
1368 gpointer data)
1369 {
1370 IncProgressDialog *dialog = (IncProgressDialog *)data;
1371
1372 if (dialog->queue_list == NULL)
1373 inc_progress_dialog_destroy(dialog);
1374
1375 return TRUE;
1376 }
1377
inc_spool_account(PrefsAccount * account)1378 static gint inc_spool_account(PrefsAccount *account)
1379 {
1380 FolderItem *inbox;
1381 gchar *mbox;
1382 gint result;
1383
1384 if (account->local_inbox) {
1385 inbox = folder_find_item_from_identifier(account->local_inbox);
1386 if (!inbox)
1387 inbox = folder_get_default_inbox();
1388 } else
1389 inbox = folder_get_default_inbox();
1390
1391 if (account->local_mbox) {
1392 if (is_file_exist(account->local_mbox))
1393 mbox = g_strdup(account->local_mbox);
1394 else if (is_dir_exist(account->local_mbox))
1395 mbox = g_strconcat(account->local_mbox, G_DIR_SEPARATOR_S,
1396 g_get_user_name(), NULL);
1397 else {
1398 debug_print("%s: local mailbox not found.\n",
1399 account->local_mbox);
1400 return -1;
1401 }
1402 } else {
1403 debug_print("local mailbox not set in account info.\n");
1404 return -1;
1405 }
1406
1407 result = get_spool(inbox, mbox, account);
1408 g_free(mbox);
1409
1410 statusbar_pop_all();
1411
1412 return result;
1413 }
1414
get_spool(FolderItem * dest,const gchar * mbox,PrefsAccount * account)1415 static gint get_spool(FolderItem *dest, const gchar *mbox, PrefsAccount *account)
1416 {
1417 gint msgs, size;
1418 gint lockfd;
1419 gchar tmp_mbox[MAXPATHLEN + 1];
1420
1421 cm_return_val_if_fail(dest != NULL, -1);
1422 cm_return_val_if_fail(mbox != NULL, -1);
1423 cm_return_val_if_fail(account != NULL, -1);
1424
1425 if (!is_file_exist(mbox) || (size = get_file_size(mbox)) == 0) {
1426 debug_print("%s: no messages in local mailbox.\n", mbox);
1427 return 0;
1428 } else if (size < 0)
1429 return -1;
1430
1431 if ((lockfd = lock_mbox(mbox, LOCK_FLOCK)) < 0)
1432 return -1;
1433
1434 g_snprintf(tmp_mbox, sizeof(tmp_mbox), "%s%ctmpmbox.%p",
1435 get_tmp_dir(), G_DIR_SEPARATOR, mbox);
1436
1437 if (copy_mbox(lockfd, tmp_mbox) < 0) {
1438 unlock_mbox(mbox, lockfd, LOCK_FLOCK);
1439 return -1;
1440 }
1441
1442 debug_print("Getting new messages from %s into %s...\n",
1443 mbox, dest->path);
1444
1445 msgs = proc_mbox(dest, tmp_mbox, account->filter_on_recv, account);
1446
1447 claws_unlink(tmp_mbox);
1448 if (msgs >= 0) empty_mbox(mbox);
1449 unlock_mbox(mbox, lockfd, LOCK_FLOCK);
1450
1451 return msgs;
1452 }
1453
inc_lock_real(void)1454 void inc_lock_real(void)
1455 {
1456 inc_lock_count++;
1457 }
1458
inc_unlock_real(void)1459 void inc_unlock_real(void)
1460 {
1461 if (inc_lock_count > 0)
1462 inc_lock_count--;
1463 }
1464
1465 static guint autocheck_timer = 0;
1466 static gpointer autocheck_data = NULL;
1467
inc_notify_cmd(gint new_msgs,gboolean notify)1468 static void inc_notify_cmd(gint new_msgs, gboolean notify)
1469 {
1470 gchar *buf, *numpos, *ret_str;
1471 gssize by_read = 0, by_written = 0;
1472
1473 if (!(new_msgs && notify && prefs_common.newmail_notify_cmd &&
1474 *prefs_common.newmail_notify_cmd))
1475 return;
1476
1477 buf = g_strdup(prefs_common.newmail_notify_cmd);
1478 if ((numpos = strstr(buf, "%d")) != NULL) {
1479 gchar *buf2;
1480
1481 *numpos = '\0';
1482 buf2 = g_strdup_printf("%s%d%s", buf, new_msgs, numpos + 2);
1483 g_free(buf);
1484 buf = buf2;
1485 }
1486
1487 ret_str = g_locale_from_utf8(buf, strlen(buf), &by_read, &by_written,
1488 NULL);
1489 if (ret_str && by_written) {
1490 g_free(buf);
1491 buf = ret_str;
1492 }
1493 debug_print("executing new mail notification command: %s\n", buf);
1494 execute_command_line(buf, TRUE, NULL);
1495
1496 g_free(buf);
1497 }
1498
inc_autocheck_timer_init(MainWindow * mainwin)1499 void inc_autocheck_timer_init(MainWindow *mainwin)
1500 {
1501 autocheck_data = mainwin;
1502 inc_autocheck_timer_set();
1503 }
1504
inc_autocheck_timer_set_interval(guint _interval)1505 static void inc_autocheck_timer_set_interval(guint _interval)
1506 {
1507 guint interval = _interval;
1508
1509 /* Convert the interval to seconds if needed. */
1510 if (_interval % 1000 == 0)
1511 interval /= 1000;
1512
1513 inc_autocheck_timer_remove();
1514 /* last test is to avoid re-enabling auto_check after modifying
1515 the common preferences */
1516 if (prefs_common.autochk_newmail && autocheck_data
1517 && prefs_common.work_offline == FALSE) {
1518 autocheck_timer =
1519 g_timeout_add_seconds(interval, inc_autocheck_func, autocheck_data);
1520 debug_print("added global inc timer %d at %u seconds\n",
1521 autocheck_timer, interval);
1522 }
1523 }
1524
inc_autocheck_timer_set(void)1525 void inc_autocheck_timer_set(void)
1526 {
1527 inc_autocheck_timer_set_interval(prefs_common.autochk_itv * 1000);
1528 }
1529
inc_autocheck_timer_remove(void)1530 void inc_autocheck_timer_remove(void)
1531 {
1532 if (autocheck_timer) {
1533 debug_print("removed global inc timer %d\n", autocheck_timer);
1534 g_source_remove(autocheck_timer);
1535 autocheck_timer = 0;
1536 }
1537 }
1538
inc_autocheck_func(gpointer data)1539 static gint inc_autocheck_func(gpointer data)
1540 {
1541 MainWindow *mainwin = (MainWindow *)data;
1542
1543 if (inc_lock_count) {
1544 debug_print("global inc: autocheck is locked.\n");
1545 inc_autocheck_timer_set_interval(1000);
1546 return FALSE;
1547 }
1548
1549 inc_all_account_mail(mainwin, TRUE, FALSE, prefs_common.newmail_notify_auto);
1550 inc_autocheck_timer_set();
1551
1552 return FALSE;
1553 }
1554
inc_account_autocheck_func(gpointer data)1555 static gboolean inc_account_autocheck_func(gpointer data)
1556 {
1557 PrefsAccount *account = (PrefsAccount *)data;
1558 GList *list = NULL;
1559
1560 cm_return_val_if_fail(account != NULL, FALSE);
1561
1562 debug_print("account %d: inc_account_autocheck_func\n",
1563 account->account_id);
1564
1565 list = g_list_append(list, account);
1566 inc_account_list_mail(mainwindow_get_mainwindow(),
1567 list, TRUE, prefs_common.newmail_notify_auto);
1568 g_list_free(list);
1569
1570 inc_account_autocheck_timer_set_interval(account);
1571
1572 return FALSE;
1573 }
1574
inc_account_autocheck_timer_remove(PrefsAccount * account)1575 void inc_account_autocheck_timer_remove(PrefsAccount *account)
1576 {
1577 cm_return_if_fail(account != NULL);
1578
1579 if (account->autocheck_timer != 0) {
1580 g_source_remove(account->autocheck_timer);
1581 debug_print("INC: account %d: removed inc timer %d\n", account->account_id,
1582 account->autocheck_timer);
1583 account->autocheck_timer = 0;
1584 }
1585 }
1586
inc_account_autocheck_timer_set_interval(PrefsAccount * account)1587 void inc_account_autocheck_timer_set_interval(PrefsAccount *account)
1588 {
1589 cm_return_if_fail(account != NULL);
1590
1591 inc_account_autocheck_timer_remove(account);
1592
1593 if (account->autochk_use_default
1594 || !account->autochk_use_custom
1595 || account->autochk_itv == 0)
1596 return;
1597
1598 account->autocheck_timer = g_timeout_add_seconds(
1599 account->autochk_itv, inc_account_autocheck_func, account);
1600 debug_print("INC: account %d: added inc timer %d at %u seconds\n",
1601 account->account_id, account->autocheck_timer, account->autochk_itv);
1602 }
1603
inc_offline_should_override(gboolean force_ask,const gchar * msg)1604 gboolean inc_offline_should_override(gboolean force_ask, const gchar *msg)
1605 {
1606 gint length = 10; /* seconds */
1607 gint answer = G_ALERTDEFAULT;
1608
1609 #ifdef HAVE_NETWORKMANAGER_SUPPORT
1610 /* If no network connection is available, override is not possible */
1611 if(!networkmanager_is_online(NULL))
1612 return FALSE;
1613 #endif
1614
1615 if (prefs_common.autochk_newmail)
1616 length = prefs_common.autochk_itv; /* seconds */
1617
1618 if (force_ask) {
1619 inc_offline_overridden_no = (time_t)0;
1620 }
1621
1622 if (prefs_common.work_offline) {
1623 gchar *tmp = NULL;
1624
1625 if (time(NULL) - inc_offline_overridden_yes < length * 60) /* seconds */
1626 return TRUE;
1627 else if (time(NULL) - inc_offline_overridden_no < length * 60) /* seconds */
1628 return FALSE;
1629
1630 if (!force_ask) {
1631 gchar *unit = _("seconds");
1632
1633 /* show the offline override time (length) using the must appropriate unit:
1634 the biggest unit possible (hours, minutes, seconds), provided that there
1635 is not inferior unit involved: 1 hour, 150 minutes, 25 minutes, 90 minutes,
1636 30 seconds, 90 seconds. */
1637 if ((length / 3600) > 0) { /* hours? */
1638 if (((length % 3600) % 60) == 0) { /* no seconds left? */
1639 if ((length % 3600) > 0) { /* minutes left? */
1640 length = length / 60;
1641 unit = ngettext("minute", "minutes", length);
1642 } else {
1643 length = length / 3600;
1644 unit = ngettext("hour", "hours", length);
1645 }
1646 } /* else: seconds */
1647 } else {
1648 if ((length / 60) > 0) { /* minutes left? */
1649 if ((length % 60) == 0) {
1650 length = length / 60;
1651 unit = ngettext("minute", "minutes", length);
1652 }
1653 } /* else: seconds */
1654 }
1655 tmp = g_strdup_printf(
1656 _("%s%sYou're working offline. Override for %d %s?"),
1657 msg?msg:"",
1658 msg?"\n\n":"",
1659 length, unit);
1660 } else
1661 tmp = g_strdup_printf(
1662 _("%s%sYou're working offline. Override?"),
1663 msg?msg:"",
1664 msg?"\n\n":"");
1665
1666 answer = alertpanel(_("Offline warning"),
1667 tmp,
1668 GTK_STOCK_NO, GTK_STOCK_YES,
1669 !force_ask? _("On_ly once"):NULL, ALERTFOCUS_SECOND);
1670 g_free(tmp);
1671 if (answer == G_ALERTALTERNATE) {
1672 inc_offline_overridden_yes = time(NULL);
1673 return TRUE;
1674 } else if (answer == G_ALERTDEFAULT) {
1675 if (!force_ask)
1676 inc_offline_overridden_no = time(NULL);
1677 return FALSE;
1678 } else {
1679 inc_reset_offline_override_timers();
1680 return TRUE;
1681 }
1682 }
1683 return TRUE;
1684 }
1685
inc_reset_offline_override_timers()1686 void inc_reset_offline_override_timers()
1687 {
1688 debug_print("resetting offline override timers\n");
1689 inc_offline_overridden_yes = (time_t)0;
1690 inc_offline_overridden_no = (time_t)0;
1691 }
1692