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