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