bc328fb80f3e6c68f608d66e9a0cc6ca970ecb5c
[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..."),
863                                     SESSION(session)->server);
864                 break;
865         case POP3_GETRANGE_STAT:
866                 progress_dialog_set_label
867                         (dialog, _("Getting the number of new messages (STAT)..."));
868                 break;
869         case POP3_GETRANGE_LAST:
870                 progress_dialog_set_label
871                         (dialog, _("Getting the number of new messages (LAST)..."));
872                 break;
873         case POP3_GETRANGE_UIDL:
874                 progress_dialog_set_label
875                         (dialog, _("Getting the number of new messages (UIDL)..."));
876                 break;
877         case POP3_GETSIZE_LIST:
878                 progress_dialog_set_label
879                         (dialog, _("Getting the size of messages (LIST)..."));
880                 break;
881         case POP3_RETR:
882         case POP3_RETR_RECV:
883                 break;
884         case POP3_DELETE:
885                 if (session->msg[session->cur_msg].recv_time <
886                         session->current_time) {
887                         g_snprintf(buf, sizeof(buf), _("Deleting message %d"),
888                                    session->cur_msg);
889                         progress_dialog_set_label(dialog, buf);
890                 }
891                 break;
892         case POP3_LOGOUT:
893                 progress_dialog_set_label(dialog, _("Quitting"));
894                 break;
895         default:
896                 break;
897         }
898 }
899
900 static void inc_progress_dialog_set_progress(IncProgressDialog *inc_dialog,
901                                              IncSession *inc_session)
902 {
903         gchar buf[MSGBUFSIZE];
904         Pop3Session *pop3_session = POP3_SESSION(inc_session->session);
905         gchar *total_size_str;
906         gint cur_total;
907         gint total;
908
909         if (!pop3_session->new_msg_exist) return;
910
911         cur_total = inc_session->cur_total_bytes;
912         total = pop3_session->total_bytes;
913         if (pop3_session->state == POP3_RETR ||
914             pop3_session->state == POP3_RETR_RECV) {
915                 Xstrdup_a(total_size_str, to_human_readable(total), return);
916                 g_snprintf(buf, sizeof(buf),
917                            _("Retrieving message (%d / %d) (%s / %s)"),
918                            pop3_session->cur_msg, pop3_session->count,
919                            to_human_readable(cur_total), total_size_str);
920                 progress_dialog_set_label(inc_dialog->dialog, buf);
921         }
922
923         progress_dialog_set_percentage
924                 (inc_dialog->dialog,(gfloat)cur_total / (gfloat)total);
925
926         gtk_progress_set_show_text
927                 (GTK_PROGRESS(inc_dialog->mainwin->progressbar), TRUE);
928         g_snprintf(buf, sizeof(buf), "%d / %d",
929                    pop3_session->cur_msg, pop3_session->count);
930         gtk_progress_set_format_string
931                 (GTK_PROGRESS(inc_dialog->mainwin->progressbar), buf);
932         gtk_progress_bar_update
933                 (GTK_PROGRESS_BAR(inc_dialog->mainwin->progressbar),
934                  (gfloat)cur_total / (gfloat)total);
935
936         if (pop3_session->cur_total_num > 0) {
937                 g_snprintf(buf, sizeof(buf),
938                            _("Retrieving (%d message(s) (%s) received)"),
939                            pop3_session->cur_total_num,
940                            to_human_readable
941                            (pop3_session->cur_total_recv_bytes));
942                 gtk_clist_set_text(GTK_CLIST(inc_dialog->dialog->clist),
943                                    inc_dialog->cur_row, 2, buf);
944         }
945 }
946
947 static gboolean hash_remove_func(gpointer key, gpointer value, gpointer data)
948 {
949         return TRUE;
950 }
951
952 static gint inc_progress_timer_func(gpointer data)
953 {
954         IncSession *inc_session = (IncSession *)data;
955         IncProgressDialog *inc_dialog;
956
957         inc_dialog = (IncProgressDialog *)inc_session->data;
958
959         inc_progress_dialog_update(inc_dialog, inc_session);
960
961         return TRUE;
962 }
963
964 static gint inc_folder_timer_func(gpointer data)
965 {
966         IncSession *inc_session = (IncSession *)data;
967         IncProgressDialog *inc_dialog;
968
969         inc_dialog = (IncProgressDialog *)inc_session->data;
970
971         if (g_hash_table_size(inc_session->tmp_folder_table) > 0) {
972                 folderview_update_item_foreach(inc_session->tmp_folder_table,
973                                                FALSE);
974                 g_hash_table_foreach_remove(inc_session->tmp_folder_table,
975                                             hash_remove_func, NULL);
976         }
977
978         return TRUE;
979 }
980
981 static gint inc_recv_data_progressive(Session *session, guint cur_len,
982                                       guint total_len, gpointer data)
983 {
984         IncSession *inc_session = (IncSession *)data;
985         Pop3Session *pop3_session = POP3_SESSION(session);
986         gint cur_total;
987
988         g_return_val_if_fail(inc_session != NULL, -1);
989
990         if (pop3_session->state != POP3_RETR &&
991             pop3_session->state != POP3_RETR_RECV &&
992             pop3_session->state != POP3_DELETE &&
993             pop3_session->state != POP3_LOGOUT) return 0;
994
995         if (!pop3_session->new_msg_exist) return 0;
996
997         cur_total = pop3_session->cur_total_bytes + cur_len;
998         if (cur_total > pop3_session->total_bytes)
999                 cur_total = pop3_session->total_bytes;
1000         inc_session->cur_total_bytes = cur_total;
1001
1002         return 0;
1003 }
1004
1005 static gint inc_recv_data_finished(Session *session, guint len, gpointer data)
1006 {
1007         IncSession *inc_session = (IncSession *)data;
1008         IncProgressDialog *inc_dialog;
1009
1010         g_return_val_if_fail(inc_session != NULL, -1);
1011
1012         inc_dialog = (IncProgressDialog *)inc_session->data;
1013         inc_recv_data_progressive(session, 0, 0, inc_session);
1014
1015         if (POP3_SESSION(session)->state == POP3_RETR) {
1016                 if (inc_dialog->progress_timer_id == 0) {
1017                         inc_timer_start(inc_dialog, inc_session);
1018                         inc_progress_dialog_update(inc_dialog, inc_session);
1019                 }
1020         } else if (POP3_SESSION(session)->state == POP3_LOGOUT) {
1021                 inc_progress_dialog_update(inc_dialog, inc_session);
1022                 if (inc_dialog->progress_timer_id) {
1023                         inc_folder_timer_func(data);
1024                         inc_timer_stop(inc_dialog);
1025                 }
1026         }
1027
1028         return 0;
1029 }
1030
1031 static gint inc_recv_message(Session *session, const gchar *msg, gpointer data)
1032 {
1033         IncSession *inc_session = (IncSession *)data;
1034         IncProgressDialog *inc_dialog;
1035
1036         g_return_val_if_fail(inc_session != NULL, -1);
1037
1038         inc_dialog = (IncProgressDialog *)inc_session->data;
1039
1040         switch (POP3_SESSION(session)->state) {
1041         case POP3_GETAUTH_USER:
1042         case POP3_GETAUTH_PASS:
1043         case POP3_GETAUTH_APOP:
1044         case POP3_GETRANGE_STAT:
1045         case POP3_GETRANGE_LAST:
1046         case POP3_GETRANGE_UIDL:
1047         case POP3_GETSIZE_LIST:
1048                 inc_progress_dialog_update(inc_dialog, inc_session);
1049                 break;
1050         case POP3_RETR:
1051                 inc_recv_data_progressive(session, 0, 0, inc_session);
1052                 if (inc_dialog->progress_timer_id == 0) {
1053                         inc_timer_start(inc_dialog, inc_session);
1054                         inc_progress_dialog_update(inc_dialog, inc_session);
1055                 }
1056                 break;
1057         case POP3_LOGOUT:
1058                 inc_progress_dialog_update(inc_dialog, inc_session);
1059                 if (inc_dialog->progress_timer_id) {
1060                         inc_folder_timer_func(data);
1061                         inc_timer_stop(inc_dialog);
1062                 }
1063                 break;
1064         default:
1065                 break;
1066         }
1067
1068         return 0;
1069 }
1070
1071 static gint inc_drop_message(Pop3Session *session, const gchar *file)
1072 {
1073         FolderItem *inbox;
1074         FolderItem *dropfolder;
1075         IncSession *inc_session = (IncSession *)(SESSION(session)->data);
1076         IncProgressDialog *inc_dialog;
1077         gint msgnum;
1078         gint val;
1079
1080         g_return_val_if_fail(inc_session != NULL, -1);
1081
1082         if (session->ac_prefs->inbox) {
1083                 inbox = folder_find_item_from_identifier
1084                         (session->ac_prefs->inbox);
1085                 if (!inbox)
1086                         inbox = folder_get_default_inbox();
1087         } else
1088                 inbox = folder_get_default_inbox();
1089         if (!inbox) {
1090                 unlink(file);
1091                 return -1;
1092         }
1093
1094         /* CLAWS: claws uses a global .processing folder for the filtering. */
1095         dropfolder = folder_get_default_processing();
1096
1097         /* add msg file to drop folder */
1098         if ((msgnum = folder_item_add_msg(dropfolder, file, NULL, TRUE)) < 0) {
1099                 unlink(file);
1100                 return -1;
1101         }
1102
1103         inc_dialog = (IncProgressDialog *)inc_session->data;
1104
1105         return 0;
1106 }
1107
1108 static void inc_put_error(IncState istate, const gchar *msg)
1109 {
1110         gchar *log_msg = NULL;
1111         gchar *err_msg = NULL;
1112         gboolean fatal_error = FALSE;
1113
1114         switch (istate) {
1115         case INC_CONNECT_ERROR:
1116                 log_msg = _("Connection failed.");
1117                 if (prefs_common.no_recv_err_panel)
1118                         break;
1119                 err_msg = g_strdup(log_msg);
1120                 break;
1121         case INC_ERROR:
1122                 log_msg = _("Error occurred while processing mail.");
1123                 if (prefs_common.no_recv_err_panel)
1124                         break;
1125                 if (msg)
1126                         err_msg = g_strdup_printf
1127                                 (_("Error occurred while processing mail:\n%s"),
1128                                  msg);
1129                 else
1130                         err_msg = g_strdup(log_msg);
1131                 break;
1132         case INC_NO_SPACE:
1133                 log_msg = _("No disk space left.");
1134                 err_msg = g_strdup(log_msg);
1135                 fatal_error = TRUE;
1136                 break;
1137         case INC_IO_ERROR:
1138                 log_msg = _("Can't write file.");
1139                 err_msg = g_strdup(log_msg);
1140                 fatal_error = TRUE;
1141                 break;
1142         case INC_SOCKET_ERROR:
1143                 log_msg = _("Socket error.");
1144                 if (prefs_common.no_recv_err_panel)
1145                         break;
1146                 err_msg = g_strdup(log_msg);
1147                 break;
1148         case INC_EOF:
1149                 log_msg = _("Connection closed by the remote host.");
1150                 if (prefs_common.no_recv_err_panel)
1151                         break;
1152                 err_msg = g_strdup(log_msg);
1153                 break;
1154         case INC_LOCKED:
1155                 log_msg = _("Mailbox is locked.");
1156                 if (prefs_common.no_recv_err_panel)
1157                         break;
1158                 if (msg)
1159                         err_msg = g_strdup_printf(_("Mailbox is locked:\n%s"),
1160                                                   msg);
1161                 else
1162                         err_msg = g_strdup(log_msg);
1163                 break;
1164         case INC_AUTH_FAILED:
1165                 log_msg = _("Authentication failed.");
1166                 if (prefs_common.no_recv_err_panel)
1167                         break;
1168                 if (msg)
1169                         err_msg = g_strdup_printf
1170                                 (_("Authentication failed:\n%s"), msg);
1171                 else
1172                         err_msg = g_strdup(log_msg);
1173                 break;
1174         default:
1175                 break;
1176         }
1177
1178         if (log_msg) {
1179                 if (fatal_error)
1180                         log_error("%s\n", log_msg);
1181                 else
1182                         log_warning("%s\n", log_msg);
1183         }
1184         if (err_msg) {
1185                 alertpanel_error_log(err_msg);
1186                 g_free(err_msg);
1187         }
1188 }
1189
1190 static void inc_cancel(IncProgressDialog *dialog)
1191 {
1192         IncSession *session;
1193
1194         g_return_if_fail(dialog != NULL);
1195
1196         if (dialog->queue_list == NULL) {
1197                 inc_progress_dialog_destroy(dialog);
1198                 return;
1199         }
1200
1201         session = dialog->queue_list->data;
1202
1203         session->inc_state = INC_CANCEL;
1204
1205         log_message("Incorporation cancelled\n");
1206 }
1207
1208 gboolean inc_is_active(void)
1209 {
1210         return (inc_dialog_list != NULL);
1211 }
1212
1213 void inc_cancel_all(void)
1214 {
1215         GList *cur;
1216
1217         for (cur = inc_dialog_list; cur != NULL; cur = cur->next)
1218                 inc_cancel((IncProgressDialog *)cur->data);
1219 }
1220
1221 static void inc_cancel_cb(GtkWidget *widget, gpointer data)
1222 {
1223         inc_cancel((IncProgressDialog *)data);
1224 }
1225
1226 static gint inc_dialog_delete_cb(GtkWidget *widget, GdkEventAny *event,
1227                                  gpointer data)
1228 {
1229         IncProgressDialog *dialog = (IncProgressDialog *)data;
1230
1231         if (dialog->queue_list == NULL)
1232                 inc_progress_dialog_destroy(dialog);
1233
1234         return TRUE;
1235 }
1236
1237 static gint inc_spool_account(PrefsAccount *account)
1238 {
1239         FolderItem *inbox;
1240         gchar *mbox, *logname;
1241         gint result;
1242
1243         logname = g_get_user_name();
1244
1245         if (account->inbox) {
1246                 inbox = folder_find_item_from_path(account->inbox);
1247                 if (!inbox)
1248                         inbox = folder_get_default_inbox();
1249         } else
1250                 inbox = folder_get_default_inbox();
1251
1252         if (is_file_exist(account->local_mbox))
1253                 mbox = g_strdup(account->local_mbox);
1254         else 
1255                 mbox = g_strconcat(account->local_mbox,
1256                                    G_DIR_SEPARATOR_S, logname, NULL);
1257         
1258         result = get_spool(inbox, mbox);
1259         g_free(mbox);
1260         
1261         statusbar_pop_all();
1262         
1263         return result;
1264 }
1265
1266 static gint inc_all_spool(void)
1267 {
1268         GList *list = NULL;
1269         gint new_msgs = 0;
1270         gint account_new_msgs = 0;
1271
1272         list = account_get_list();
1273         if (!list) return 0;
1274
1275         for (; list != NULL; list = list->next) {
1276                 PrefsAccount *account = list->data;
1277
1278                 if ((account->protocol == A_LOCAL) &&
1279                     (account->recv_at_getall)) {
1280                         account_new_msgs = inc_spool_account(account);
1281                         if (account_new_msgs > 0)
1282                                 new_msgs += account_new_msgs;
1283                 }
1284         }
1285
1286         return new_msgs;
1287 }
1288
1289 static gint get_spool(FolderItem *dest, const gchar *mbox)
1290 {
1291         gint msgs, size;
1292         gint lockfd;
1293         gchar tmp_mbox[MAXPATHLEN + 1];
1294
1295         g_return_val_if_fail(dest != NULL, -1);
1296         g_return_val_if_fail(mbox != NULL, -1);
1297
1298         if (!is_file_exist(mbox) || (size = get_file_size(mbox)) == 0) {
1299                 debug_print("no messages in local mailbox.\n");
1300                 return 0;
1301         } else if (size < 0)
1302                 return -1;
1303
1304         if ((lockfd = lock_mbox(mbox, LOCK_FLOCK)) < 0)
1305                 return -1;
1306
1307         g_snprintf(tmp_mbox, sizeof(tmp_mbox), "%s%ctmpmbox.%08x",
1308                    get_tmp_dir(), G_DIR_SEPARATOR, (gint)mbox);
1309
1310         if (copy_mbox(mbox, tmp_mbox) < 0) {
1311                 unlock_mbox(mbox, lockfd, LOCK_FLOCK);
1312                 return -1;
1313         }
1314
1315         debug_print("Getting new messages from %s into %s...\n",
1316                     mbox, dest->path);
1317
1318         msgs = proc_mbox(dest, tmp_mbox, TRUE);
1319
1320         unlink(tmp_mbox);
1321         if (msgs >= 0) empty_mbox(mbox);
1322         unlock_mbox(mbox, lockfd, LOCK_FLOCK);
1323
1324         return msgs;
1325 }
1326
1327 void inc_lock(void)
1328 {
1329         inc_lock_count++;
1330 }
1331
1332 void inc_unlock(void)
1333 {
1334         if (inc_lock_count > 0)
1335                 inc_lock_count--;
1336 }
1337
1338 static guint autocheck_timer = 0;
1339 static gpointer autocheck_data = NULL;
1340
1341 static void inc_notify_cmd(gint new_msgs, gboolean notify)
1342 {
1343
1344         gchar *buf;
1345
1346         if (!(new_msgs && notify && prefs_common.newmail_notify_cmd &&
1347             *prefs_common.newmail_notify_cmd))
1348                      return;
1349         if ((buf = strchr(prefs_common.newmail_notify_cmd, '%')) &&
1350                 buf[1] == 'd' && !strchr(&buf[1], '%'))
1351                 buf = g_strdup_printf(prefs_common.newmail_notify_cmd, 
1352                                       new_msgs);
1353         else
1354                 buf = g_strdup(prefs_common.newmail_notify_cmd);
1355
1356         execute_command_line(buf, TRUE);
1357
1358         g_free(buf);
1359 }
1360  
1361 void inc_autocheck_timer_init(MainWindow *mainwin)
1362 {
1363         autocheck_data = mainwin;
1364         inc_autocheck_timer_set();
1365 }
1366
1367 static void inc_autocheck_timer_set_interval(guint interval)
1368 {
1369         inc_autocheck_timer_remove();
1370         /* last test is to avoid re-enabling auto_check after modifying 
1371            the common preferences */
1372         if (prefs_common.autochk_newmail && autocheck_data
1373             && prefs_common.work_offline == FALSE) {
1374                 autocheck_timer = gtk_timeout_add
1375                         (interval, inc_autocheck_func, autocheck_data);
1376                 debug_print("added timer = %d\n", autocheck_timer);
1377         }
1378 }
1379
1380 void inc_autocheck_timer_set(void)
1381 {
1382         inc_autocheck_timer_set_interval(prefs_common.autochk_itv * 60000);
1383 }
1384
1385 void inc_autocheck_timer_remove(void)
1386 {
1387         if (autocheck_timer) {
1388                 debug_print("removed timer = %d\n", autocheck_timer);
1389                 gtk_timeout_remove(autocheck_timer);
1390                 autocheck_timer = 0;
1391         }
1392 }
1393
1394 static gint inc_autocheck_func(gpointer data)
1395 {
1396         MainWindow *mainwin = (MainWindow *)data;
1397
1398         if (inc_lock_count) {
1399                 debug_print("autocheck is locked.\n");
1400                 inc_autocheck_timer_set_interval(1000);
1401                 return FALSE;
1402         }
1403
1404         inc_all_account_mail(mainwin, TRUE, prefs_common.newmail_notify_auto);
1405
1406         return FALSE;
1407 }