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