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