Statistics
| Revision:

root / src / inc.c @ 3194

History | View | Annotate | Download (48.4 KB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2012 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 <gtk/gtkdialog.h>
33
#include <gtk/gtkstock.h>
34
#include <stdio.h>
35
#include <unistd.h>
36
#include <string.h>
37

    
38
#include "main.h"
39
#include "inc.h"
40
#include "mainwindow.h"
41
#include "folderview.h"
42
#include "summaryview.h"
43
#include "prefs_common.h"
44
#include "prefs_account.h"
45
#include "account.h"
46
#include "procmsg.h"
47
#include "socket.h"
48
#include "socks.h"
49
#include "pop.h"
50
#include "recv.h"
51
#include "mbox.h"
52
#include "imap.h"
53
#include "utils.h"
54
#include "gtkutils.h"
55
#include "statusbar.h"
56
#include "manage_window.h"
57
#include "stock_pixmap.h"
58
#include "progressdialog.h"
59
#include "alertpanel.h"
60
#include "trayicon.h"
61
#include "filter.h"
62
#include "folder.h"
63
#include "procheader.h"
64
#include "plugin.h"
65

    
66

    
67
typedef struct _IncAccountNewMsgCount
68
{
69
        PrefsAccount *account;
70
        gint new_messages;
71
} IncAccountNewMsgCount;
72

    
73

    
74
static GList *inc_dialog_list = NULL;
75

    
76
static gboolean inc_is_running = FALSE;
77

    
78
static guint inc_lock_count = 0;
79
static gboolean block_notify = FALSE;
80

    
81
static GdkPixbuf *current_pixbuf;
82
static GdkPixbuf *error_pixbuf;
83
static GdkPixbuf *ok_pixbuf;
84

    
85

    
86
static void inc_finished                (MainWindow                *mainwin,
87
                                         GSList                        *msg_counts);
88
static GSList *inc_add_message_count        (GSList                        *list,
89
                                         PrefsAccount                *account,
90
                                         gint                         new_messages);
91

    
92
static gint inc_remote_account_mail        (MainWindow                *mainwin,
93
                                         PrefsAccount                *account);
94
static gint inc_account_mail_real        (MainWindow                *mainwin,
95
                                         PrefsAccount                *account);
96

    
97
static IncProgressDialog *inc_progress_dialog_create
98
                                        (gboolean                 autocheck);
99
static void inc_progress_dialog_set_list(IncProgressDialog        *inc_dialog);
100
static void inc_progress_dialog_destroy        (IncProgressDialog        *inc_dialog);
101

    
102
static IncSession *inc_session_new        (PrefsAccount                *account);
103
static void inc_session_destroy                (IncSession                *session);
104
static gint inc_start                        (IncProgressDialog        *inc_dialog,
105
                                         GSList                       **count_list);
106
static IncState inc_pop3_session_do        (IncSession                *session);
107

    
108
static void inc_progress_dialog_update        (IncProgressDialog        *inc_dialog,
109
                                         IncSession                *inc_session);
110

    
111
static void inc_progress_dialog_set_label
112
                                        (IncProgressDialog        *inc_dialog,
113
                                         IncSession                *inc_session);
114
static void inc_progress_dialog_set_progress
115
                                        (IncProgressDialog        *inc_dialog,
116
                                         IncSession                *inc_session);
117

    
118
static void inc_update_folderview        (IncProgressDialog        *inc_dialog,
119
                                         IncSession                *inc_session);
120

    
121
static void inc_progress_dialog_update_periodic
122
                                        (IncProgressDialog        *inc_dialog,
123
                                         IncSession                *inc_session);
124
static void inc_update_folderview_periodic
125
                                        (IncProgressDialog        *inc_dialog,
126
                                         IncSession                *inc_session);
127

    
128
static gint inc_recv_data_progressive        (Session        *session,
129
                                         guint                 cur_len,
130
                                         guint                 total_len,
131
                                         gpointer         data);
132
static gint inc_recv_data_finished        (Session        *session,
133
                                         guint                 len,
134
                                         gpointer         data);
135
static gint inc_recv_message                (Session        *session,
136
                                         const gchar        *msg,
137
                                         gpointer         data);
138
static gint inc_drop_message                (Pop3Session        *session,
139
                                         const gchar        *file);
140

    
141
static void inc_put_error                (IncSession        *session,
142
                                         IncState         istate,
143
                                         const gchar        *pop3_msg);
144

    
145
static void inc_cancel_cb                (GtkWidget        *widget,
146
                                         gpointer         data);
147
static void inc_cancel_all_cb                (GtkWidget        *widget,
148
                                         gpointer         data);
149
static gint inc_dialog_delete_cb        (GtkWidget        *widget,
150
                                         GdkEventAny        *event,
151
                                         gpointer         data);
152

    
153
static gint inc_spool                        (void);
154
static gint get_spool                        (FolderItem        *dest,
155
                                         const gchar        *mbox);
156

    
157
static void inc_autocheck_timer_set_interval        (guint                 interval);
158
static gint inc_autocheck_func                        (gpointer         data);
159

    
160

    
161
/**
162
 * inc_finished:
163
 * @mainwin: Main window.
164
 * @msg_counts: GSList of Number of received messages for each account.
165
 * @new_messages: Number of received messages.
166
 * 
167
 * Update the folder view and the summary view after receiving
168
 * messages.  If @new_messages is 0, this function avoids unneeded
169
 * updating.
170
 **/
171
static void inc_finished(MainWindow *mainwin, GSList *msg_counts)
172
{
173
        FolderItem *item;
174
        gint new_messages = 0;
175
        gint other_new = 0;
176
        IncAccountNewMsgCount *count;
177
        GSList *cur;
178

    
179
        for (cur = msg_counts; cur != NULL; cur = cur->next) {
180
                count = cur->data;
181
                if (count->new_messages > 0)
182
                        new_messages += count->new_messages;
183
        }
184

    
185
        debug_print("inc_finished: %d new message(s)\n", new_messages);
186

    
187
        if (prefs_common.scan_all_after_inc) {
188
                other_new = folderview_check_new(NULL);
189
                new_messages += other_new;
190
        }
191

    
192
        if (new_messages > 0 && !block_notify) {
193
                GString *str;
194
                gint c = 0;
195

    
196
                str = g_string_new("");
197
                g_string_printf(str, _("Sylpheed: %d new messages"),
198
                                new_messages);
199
                if (msg_counts) {
200
                        for (cur = msg_counts; cur != NULL; cur = cur->next) {
201
                                count = cur->data;
202
                                if (count->new_messages > 0) {
203
                                        if (c == 0)
204
                                                g_string_append(str, "\n");
205
                                        c++;
206
                                        g_string_append(str, "\n");
207
                                        if (!count->account)
208
                                                g_string_append_printf(str, _("[Local]: %d"), count->new_messages);
209
                                        else
210
                                                g_string_append_printf(str, "%s: %d", count->account->account_name ? count->account->account_name : "[?]", count->new_messages);
211
                                }
212
                        }
213
                }
214
                debug_print("inc_finished: %s\n", str->str);
215
                trayicon_set_tooltip(str->str);
216
                trayicon_set_notify(TRUE);
217
                g_string_free(str, TRUE);
218
        }
219

    
220
        syl_plugin_signal_emit("inc-mail-finished", new_messages);
221

    
222
        inc_block_notify(FALSE);
223

    
224
        if (new_messages <= 0 && !prefs_common.scan_all_after_inc) return;
225

    
226
        if (prefs_common.open_inbox_on_inc) {
227
                item = cur_account && cur_account->inbox
228
                        ? folder_find_item_from_identifier(cur_account->inbox)
229
                        : folder_get_default_inbox();
230
                folderview_select(mainwin->folderview, item);
231
        } else if (prefs_common.scan_all_after_inc) {
232
                item = mainwin->summaryview->folder_item;
233
                if (item)
234
                        folderview_update_item(item, TRUE);
235
        }
236

    
237
        /* Notification */
238

    
239
        if (new_messages > 0 &&
240
            prefs_common.enable_newmsg_notify_sound &&
241
            prefs_common.newmsg_notify_sound) {
242
                play_sound(prefs_common.newmsg_notify_sound, TRUE);
243
        }
244

    
245
        if (new_messages > 0 &&
246
            prefs_common.enable_newmsg_notify &&
247
            prefs_common.newmsg_notify_cmd) {
248
                gchar buf[1024];
249

    
250
                if (str_find_format_times
251
                        (prefs_common.newmsg_notify_cmd, 'd') == 1)
252
                        g_snprintf(buf, sizeof(buf),
253
                                   prefs_common.newmsg_notify_cmd,
254
                                   new_messages);
255
                else
256
                        strncpy2(buf, prefs_common.newmsg_notify_cmd,
257
                                 sizeof(buf));
258
                execute_command_line(buf, TRUE);
259
        }
260
}
261

    
262
static GSList *inc_add_message_count(GSList *list, PrefsAccount *account,
263
                                     gint new_messages)
264
{
265
        IncAccountNewMsgCount *count;
266

    
267
        count = g_new(IncAccountNewMsgCount, 1);
268
        count->account = account;
269
        count->new_messages = new_messages;
270

    
271
        return g_slist_append(list, count);
272
}
273

    
274
void inc_mail(MainWindow *mainwin)
275
{
276
        gint new_msgs = 0;
277
        GSList *list = NULL;
278

    
279
        if (inc_lock_count) return;
280
        if (inc_is_active()) return;
281

    
282
        if (!main_window_toggle_online_if_offline(mainwin))
283
                return;
284

    
285
        inc_is_running = TRUE;
286

    
287
        inc_autocheck_timer_remove();
288
        summary_write_cache(mainwin->summaryview);
289
        main_window_lock(mainwin);
290

    
291
        syl_plugin_signal_emit("inc-mail-start", cur_account);
292

    
293
        if (prefs_common.use_extinc && prefs_common.extinc_cmd) {
294
                /* external incorporating program */
295
                if (execute_command_line(prefs_common.extinc_cmd, FALSE) != 0) {
296
                        inc_is_running = FALSE;
297
                        main_window_unlock(mainwin);
298
                        inc_autocheck_timer_set();
299
                        return;
300
                }
301

    
302
                if (prefs_common.inc_local) {
303
                        new_msgs = inc_spool();
304
                        list = inc_add_message_count(list, NULL, new_msgs);
305
                }
306
        } else {
307
                if (prefs_common.inc_local) {
308
                        new_msgs = inc_spool();
309
                        if (new_msgs < 0)
310
                                new_msgs = 0;
311
                        list = inc_add_message_count(list, NULL, new_msgs);
312
                }
313

    
314
                new_msgs = inc_account_mail_real(mainwin, cur_account);
315
                list = inc_add_message_count(list, cur_account, new_msgs);
316
        }
317

    
318
        inc_finished(mainwin, list);
319
        slist_free_strings(list);
320
        g_slist_free(list);
321

    
322
        inc_is_running = FALSE;
323

    
324
        main_window_unlock(mainwin);
325
        inc_autocheck_timer_set();
326
}
327

    
328
static gint inc_remote_account_mail(MainWindow *mainwin, PrefsAccount *account)
329
{
330
        FolderItem *item = mainwin->summaryview->folder_item;
331
        gint new_msgs = 0;
332
        gboolean update_summary = FALSE;
333

    
334
        g_return_val_if_fail(account != NULL, 0);
335
        g_return_val_if_fail(account->folder != NULL, 0);
336

    
337
        if (account->protocol == A_IMAP4 &&
338
            account->imap_filter_inbox_on_recv) {
339
                FolderItem *inbox = FOLDER(account->folder)->inbox;
340
                GSList *mlist, *cur;
341
                FilterInfo *fltinfo;
342
                GSList junk_fltlist = {NULL, NULL};
343
                FilterRule *junk_rule;
344
                gint n_filtered = 0;
345

    
346
                debug_print("inc_remote_account_mail(): filtering IMAP4 INBOX\n");
347
                mlist = folder_item_get_uncached_msg_list(inbox);
348
                debug_print("inc_remote_account_mail(): uncached messages: %d\n", g_slist_length(mlist));
349

    
350
                junk_rule = filter_junk_rule_create(account, NULL, TRUE);
351
                if (junk_rule)
352
                        junk_fltlist.data = junk_rule;
353

    
354
                for (cur = mlist; cur != NULL; cur = cur->next) {
355
                        MsgInfo *msginfo = (MsgInfo *)cur->data;
356
                        gboolean is_junk = FALSE;
357

    
358
                        fltinfo = filter_info_new();
359
                        fltinfo->account = account;
360
                        fltinfo->flags = msginfo->flags;
361

    
362
                        if (prefs_common.enable_junk &&
363
                            prefs_common.filter_junk_on_recv &&
364
                            prefs_common.filter_junk_before && junk_rule) {
365
                                filter_apply_msginfo
366
                                        (&junk_fltlist, msginfo, fltinfo);
367
                                if (fltinfo->drop_done)
368
                                        is_junk = TRUE;
369
                        }
370

    
371
                        if (!fltinfo->drop_done) {
372
                                filter_apply_msginfo(prefs_common.fltlist,
373
                                                     msginfo, fltinfo);
374
                        }
375

    
376
                        if (!fltinfo->drop_done &&
377
                            prefs_common.enable_junk &&
378
                            prefs_common.filter_junk_on_recv &&
379
                            !prefs_common.filter_junk_before && junk_rule) {
380
                                filter_apply_msginfo
381
                                        (&junk_fltlist, msginfo, fltinfo);
382
                                if (fltinfo->drop_done)
383
                                        is_junk = TRUE;
384
                        }
385

    
386
                        if (msginfo->flags.perm_flags !=
387
                            fltinfo->flags.perm_flags) {
388
                                msginfo->flags = fltinfo->flags;
389
                                inbox->mark_dirty = TRUE;
390
                                if (fltinfo->actions[FLT_ACTION_MARK])
391
                                        imap_msg_set_perm_flags
392
                                                (msginfo, MSG_MARKED);
393
                                if (fltinfo->actions[FLT_ACTION_MARK_READ])
394
                                        imap_msg_unset_perm_flags
395
                                                (msginfo, MSG_NEW|MSG_UNREAD);
396
                        }
397

    
398
                        if (fltinfo->actions[FLT_ACTION_MOVE] &&
399
                            fltinfo->move_dest) {
400
                                folder_item_move_msg
401
                                        (fltinfo->move_dest, msginfo);
402
                                if (account->imap_check_inbox_only ||
403
                                    fltinfo->move_dest->folder !=
404
                                    inbox->folder) {
405
                                        if (!is_junk &&
406
                                            fltinfo->move_dest->stype != F_TRASH &&
407
                                            fltinfo->move_dest->stype != F_JUNK &&
408
                                            (MSG_IS_NEW(fltinfo->flags) ||
409
                                             MSG_IS_UNREAD(fltinfo->flags)))
410
                                                ++new_msgs;
411
                                }
412
                        } else if (fltinfo->actions[FLT_ACTION_DELETE])
413
                                folder_item_remove_msg(inbox, msginfo);
414
                        else if (!is_junk && (MSG_IS_NEW(msginfo->flags) ||
415
                                              MSG_IS_UNREAD(msginfo->flags)))
416
                                ++new_msgs;
417

    
418
                        if (fltinfo->drop_done)
419
                                ++n_filtered;
420

    
421
                        filter_info_free(fltinfo);
422
                }
423

    
424
                if (junk_rule)
425
                        filter_rule_free(junk_rule);
426

    
427
                procmsg_msg_list_free(mlist);
428

    
429
                debug_print("inc_remote_account_mail(): INBOX: %d new, %d filtered\n",
430
                            new_msgs, n_filtered);
431

    
432
                if (!prefs_common.scan_all_after_inc && item != NULL &&
433
                    inbox == item)
434
                        update_summary = TRUE;
435
        }
436

    
437
        if (account->protocol == A_IMAP4 && account->imap_check_inbox_only) {
438
                FolderItem *inbox = FOLDER(account->folder)->inbox;
439

    
440
                new_msgs += folderview_check_new_item(inbox);
441
                if (!prefs_common.scan_all_after_inc && item != NULL &&
442
                    inbox == item)
443
                        update_summary = TRUE;
444
        } else {
445
                new_msgs += folderview_check_new(FOLDER(account->folder));
446
                if (!prefs_common.scan_all_after_inc && item != NULL &&
447
                    FOLDER(account->folder) == item->folder)
448
                        update_summary = TRUE;
449
        }
450

    
451
        if (update_summary)
452
                folderview_update_item(item, TRUE);
453
        folderview_update_all_updated(FALSE);
454

    
455
        return new_msgs;
456
}
457

    
458
static gint inc_account_mail_real(MainWindow *mainwin, PrefsAccount *account)
459
{
460
        IncProgressDialog *inc_dialog;
461
        IncSession *session;
462

    
463
        g_return_val_if_fail(account != NULL, 0);
464

    
465
        if (account->protocol == A_IMAP4 || account->protocol == A_NNTP)
466
                return inc_remote_account_mail(mainwin, account);
467

    
468
        session = inc_session_new(account);
469
        if (!session) return 0;
470

    
471
        inc_dialog = inc_progress_dialog_create(FALSE);
472
        inc_dialog->queue_list = g_list_append(inc_dialog->queue_list, session);
473
        inc_dialog->mainwin = mainwin;
474
        inc_progress_dialog_set_list(inc_dialog);
475

    
476
        main_window_set_toolbar_sensitive(mainwin);
477
        main_window_set_menu_sensitive(mainwin);
478

    
479
        return inc_start(inc_dialog, NULL);
480
}
481

    
482
gint inc_account_mail(MainWindow *mainwin, PrefsAccount *account)
483
{
484
        gint new_msgs;
485
        GSList *list;
486

    
487
        if (inc_lock_count) return 0;
488
        if (inc_is_active()) return 0;
489

    
490
        if (!main_window_toggle_online_if_offline(mainwin))
491
                return 0;
492

    
493
        inc_is_running = TRUE;
494

    
495
        inc_autocheck_timer_remove();
496
        summary_write_cache(mainwin->summaryview);
497
        main_window_lock(mainwin);
498

    
499
        syl_plugin_signal_emit("inc-mail-start", account);
500

    
501
        new_msgs = inc_account_mail_real(mainwin, account);
502

    
503
        list = inc_add_message_count(NULL, account, new_msgs);
504
        inc_finished(mainwin, list);
505
        slist_free_strings(list);
506
        g_slist_free(list);
507

    
508
        inc_is_running = FALSE;
509

    
510
        main_window_unlock(mainwin);
511
        inc_autocheck_timer_set();
512

    
513
        return new_msgs;
514
}
515

    
516
void inc_all_account_mail(MainWindow *mainwin, gboolean autocheck)
517
{
518
        GList *list, *queue_list = NULL;
519
        IncProgressDialog *inc_dialog;
520
        GSList *count_list = NULL;
521
        gint new_msgs = 0;
522

    
523
        if (inc_lock_count) return;
524
        if (inc_is_active()) return;
525

    
526
        if (!main_window_toggle_online_if_offline(mainwin))
527
                return;
528

    
529
        inc_is_running = TRUE;
530

    
531
        inc_autocheck_timer_remove();
532
        summary_write_cache(mainwin->summaryview);
533
        main_window_lock(mainwin);
534

    
535
        syl_plugin_signal_emit("inc-mail-start", NULL);
536

    
537
        if (prefs_common.inc_local) {
538
                new_msgs = inc_spool();
539
                if (new_msgs < 0)
540
                        new_msgs = 0;
541
                count_list = inc_add_message_count(count_list, NULL, new_msgs);
542
        }
543

    
544
        /* check IMAP4 / News folders */
545
        for (list = account_get_list(); list != NULL; list = list->next) {
546
                PrefsAccount *account = list->data;
547
                if ((account->protocol == A_IMAP4 ||
548
                     account->protocol == A_NNTP) && account->recv_at_getall) {
549
                        new_msgs = inc_remote_account_mail(mainwin, account);
550
                        count_list = inc_add_message_count(count_list, account, new_msgs);
551
                }
552
        }
553

    
554
        /* check POP3 accounts */
555
        for (list = account_get_list(); list != NULL; list = list->next) {
556
                IncSession *session;
557
                PrefsAccount *account = list->data;
558

    
559
                if (account->recv_at_getall) {
560
                        session = inc_session_new(account);
561
                        if (session)
562
                                queue_list = g_list_append(queue_list, session);
563
                }
564
        }
565

    
566
        if (queue_list) {
567
                inc_dialog = inc_progress_dialog_create(autocheck);
568
                inc_dialog->queue_list = queue_list;
569
                inc_dialog->mainwin = mainwin;
570
                inc_progress_dialog_set_list(inc_dialog);
571

    
572
                main_window_set_toolbar_sensitive(mainwin);
573
                main_window_set_menu_sensitive(mainwin);
574

    
575
                inc_start(inc_dialog, &count_list);
576
        }
577

    
578
        inc_finished(mainwin, count_list);
579
        slist_free_strings(count_list);
580
        g_slist_free(count_list);
581

    
582
        inc_is_running = FALSE;
583

    
584
        main_window_unlock(mainwin);
585
        inc_autocheck_timer_set();
586
}
587

    
588
gint inc_pop_before_smtp(PrefsAccount *account)
589
{
590
        MainWindow *mainwin;
591
        IncProgressDialog *inc_dialog;
592
        IncSession *session;
593

    
594
        if (inc_lock_count) return -1;
595

    
596
        mainwin = main_window_get();
597

    
598
        if (!main_window_toggle_online_if_offline(mainwin))
599
                return -1;
600

    
601
        inc_is_running = TRUE;
602

    
603
        inc_autocheck_timer_remove();
604
        main_window_lock(mainwin);
605

    
606
        session = inc_session_new(account);
607
        if (!session) return -1;
608
        POP3_SESSION(session->session)->auth_only = TRUE;
609

    
610
        inc_dialog = inc_progress_dialog_create(FALSE);
611
        gtk_window_set_title(GTK_WINDOW(inc_dialog->dialog->window),
612
                             _("Authenticating with POP3"));
613
        inc_dialog->queue_list = g_list_append(inc_dialog->queue_list, session);
614
        inc_dialog->mainwin = mainwin;
615
        inc_progress_dialog_set_list(inc_dialog);
616
        inc_dialog->show_dialog = TRUE;
617

    
618
        main_window_set_toolbar_sensitive(mainwin);
619
        main_window_set_menu_sensitive(mainwin);
620

    
621
        inc_start(inc_dialog, NULL);
622

    
623
        inc_is_running = FALSE;
624

    
625
        main_window_unlock(mainwin);
626
        inc_autocheck_timer_set();
627

    
628
        return 0;
629
}
630

    
631
static IncProgressDialog *inc_progress_dialog_create(gboolean autocheck)
632
{
633
        IncProgressDialog *dialog;
634
        ProgressDialog *progress;
635
        GtkWidget *cancel_all_btn;
636

    
637
        dialog = g_new0(IncProgressDialog, 1);
638

    
639
        progress = progress_dialog_create();
640
        gtk_window_set_title(GTK_WINDOW(progress->window),
641
                             _("Retrieving new messages"));
642
        cancel_all_btn = gtk_dialog_add_button(GTK_DIALOG(progress->window),
643
                                               _("Cancel _all"),
644
                                               GTK_RESPONSE_NONE);
645
        g_signal_connect(G_OBJECT(progress->cancel_btn), "clicked",
646
                         G_CALLBACK(inc_cancel_cb), dialog);
647
        g_signal_connect(G_OBJECT(cancel_all_btn), "clicked",
648
                         G_CALLBACK(inc_cancel_all_cb), dialog);
649
        g_signal_connect(G_OBJECT(progress->window), "delete_event",
650
                         G_CALLBACK(inc_dialog_delete_cb), dialog);
651
        /* manage_window_set_transient(GTK_WINDOW(progress->window)); */
652

    
653
        progress_dialog_set_value(progress, 0.0);
654

    
655
        stock_pixbuf_gdk(progress->treeview, STOCK_PIXMAP_COMPLETE, &ok_pixbuf);
656
        stock_pixbuf_gdk(progress->treeview, STOCK_PIXMAP_CONTINUE,
657
                         &current_pixbuf);
658
        stock_pixbuf_gdk(progress->treeview, STOCK_PIXMAP_ERROR, &error_pixbuf);
659

    
660
        if (prefs_common.recv_dialog_mode == RECV_DIALOG_ALWAYS ||
661
            (prefs_common.recv_dialog_mode == RECV_DIALOG_MANUAL &&
662
             !autocheck)) {
663
                dialog->show_dialog = TRUE;
664
                gtk_widget_show_now(progress->window);
665
        }
666

    
667
        dialog->dialog = progress;
668
        g_get_current_time(&dialog->progress_tv);
669
        g_get_current_time(&dialog->folder_tv);
670
        dialog->queue_list = NULL;
671
        dialog->cur_row = 0;
672

    
673
        inc_dialog_list = g_list_append(inc_dialog_list, dialog);
674

    
675
        return dialog;
676
}
677

    
678
static void inc_progress_dialog_set_list(IncProgressDialog *inc_dialog)
679
{
680
        GList *list;
681

    
682
        for (list = inc_dialog->queue_list; list != NULL; list = list->next) {
683
                IncSession *session = list->data;
684
                Pop3Session *pop3_session = POP3_SESSION(session->session);
685

    
686
                session->data = inc_dialog;
687
                progress_dialog_append(inc_dialog->dialog, NULL,
688
                                       pop3_session->ac_prefs->account_name,
689
                                       _("Standby"), "", NULL);
690
        }
691
}
692

    
693
static void inc_progress_dialog_clear(IncProgressDialog *inc_dialog)
694
{
695
        progress_dialog_set_value(inc_dialog->dialog, 0.0);
696
        progress_dialog_set_label(inc_dialog->dialog, "");
697
        main_window_progress_off(inc_dialog->mainwin);
698
}
699

    
700
static void inc_progress_dialog_destroy(IncProgressDialog *inc_dialog)
701
{
702
        g_return_if_fail(inc_dialog != NULL);
703

    
704
        inc_dialog_list = g_list_remove(inc_dialog_list, inc_dialog);
705

    
706
        manage_window_destroy(inc_dialog->dialog->window, NULL);
707

    
708
        main_window_progress_off(inc_dialog->mainwin);
709
        progress_dialog_destroy(inc_dialog->dialog);
710

    
711
        g_free(inc_dialog);
712
}
713

    
714
static IncSession *inc_session_new(PrefsAccount *account)
715
{
716
        IncSession *session;
717
        FilterRule *rule;
718

    
719
        g_return_val_if_fail(account != NULL, NULL);
720

    
721
        if (account->protocol != A_POP3)
722
                return NULL;
723
        if (!account->recv_server || !account->userid)
724
                return NULL;
725

    
726
        session = g_new0(IncSession, 1);
727

    
728
        session->session = pop3_session_new(account);
729
        session->session->data = session;
730
        POP3_SESSION(session->session)->drop_message = inc_drop_message;
731
        session_set_recv_message_notify(session->session,
732
                                        inc_recv_message, session);
733
        session_set_recv_data_progressive_notify(session->session,
734
                                                 inc_recv_data_progressive,
735
                                                 session);
736
        session_set_recv_data_notify(session->session,
737
                                     inc_recv_data_finished, session);
738

    
739
        session->inc_state = INC_SUCCESS;
740

    
741
        session->folder_table = g_hash_table_new(NULL, NULL);
742
        session->tmp_folder_table = g_hash_table_new(NULL, NULL);
743

    
744
        rule = filter_junk_rule_create(account, NULL, FALSE);
745
        if (rule)
746
                session->junk_fltlist = g_slist_append(NULL, rule);
747
        else
748
                session->junk_fltlist = NULL;
749

    
750
        session->cur_total_bytes = 0;
751
        session->new_msgs = 0;
752

    
753
        session->start_num = 0;
754
        session->start_recv_bytes = 0;
755

    
756
        session->retr_count = 0;
757

    
758
        return session;
759
}
760

    
761
static void inc_session_destroy(IncSession *session)
762
{
763
        g_return_if_fail(session != NULL);
764

    
765
        session_destroy(session->session);
766
        g_hash_table_destroy(session->folder_table);
767
        g_hash_table_destroy(session->tmp_folder_table);
768
        if (session->junk_fltlist)
769
                filter_rule_list_free(session->junk_fltlist);
770
        g_free(session);
771
}
772

    
773
static void inc_update_folder_foreach(GHashTable *table)
774
{
775
        procmsg_flush_folder_foreach(table);
776
        folderview_update_item_foreach(table, TRUE);
777
}
778

    
779
static gint inc_start(IncProgressDialog *inc_dialog, GSList **count_list)
780
{
781
        IncSession *session;
782
        GList *qlist;
783
        Pop3Session *pop3_session;
784
        IncState inc_state;
785
        gint error_num = 0;
786
        gint new_msgs = 0;
787
        gchar *msg;
788
        gchar *fin_msg;
789

    
790
        qlist = inc_dialog->queue_list;
791
        while (qlist != NULL) {
792
                GList *next = qlist->next;
793

    
794
                session = qlist->data;
795
                if (session->inc_state == INC_CANCEL) {
796
                        qlist = next;
797
                        continue;
798
                }
799

    
800
                pop3_session = POP3_SESSION(session->session); 
801
                if (!pop3_session->pass) {
802
                        gchar *pass;
803

    
804
                        if (inc_dialog->show_dialog)
805
                                manage_window_focus_in
806
                                        (inc_dialog->dialog->window,
807
                                         NULL, NULL);
808

    
809
                        pass = input_query_password
810
                                (pop3_session->ac_prefs->recv_server,
811
                                 pop3_session->user);
812

    
813
                        if (inc_dialog->show_dialog)
814
                                manage_window_focus_out
815
                                        (inc_dialog->dialog->window,
816
                                         NULL, NULL);
817

    
818
                        if (pass) {
819
                                pop3_session->ac_prefs->tmp_pass =
820
                                        g_strdup(pass);
821
                                pop3_session->pass = pass;
822
                        }
823
                }
824

    
825
                qlist = next;
826
        }
827

    
828
#define SET_PIXMAP_AND_TEXT(pixbuf, status, progress)                        \
829
{                                                                        \
830
        progress_dialog_set_row_pixbuf(inc_dialog->dialog,                \
831
                                       inc_dialog->cur_row, pixbuf);        \
832
        progress_dialog_set_row_status(inc_dialog->dialog,                \
833
                                       inc_dialog->cur_row, status);        \
834
        if (progress)                                                        \
835
                progress_dialog_set_row_progress(inc_dialog->dialog,        \
836
                                                 inc_dialog->cur_row,        \
837
                                                 progress);                \
838
}
839

    
840
        for (; inc_dialog->queue_list != NULL; inc_dialog->cur_row++) {
841
                session = inc_dialog->queue_list->data;
842
                pop3_session = POP3_SESSION(session->session);
843

    
844
                if (session->inc_state == INC_CANCEL ||
845
                    pop3_session->pass == NULL) {
846
                        SET_PIXMAP_AND_TEXT(ok_pixbuf, _("Cancelled"), NULL);
847
                        inc_session_destroy(session);
848
                        inc_dialog->queue_list =
849
                                g_list_remove(inc_dialog->queue_list, session);
850
                        continue;
851
                }
852

    
853
                inc_progress_dialog_clear(inc_dialog);
854
                progress_dialog_scroll_to_row(inc_dialog->dialog,
855
                                              inc_dialog->cur_row);
856

    
857
                SET_PIXMAP_AND_TEXT(current_pixbuf, _("Retrieving"), NULL);
858

    
859
                /* begin POP3 session */
860
                inc_state = inc_pop3_session_do(session);
861

    
862
                switch (inc_state) {
863
                case INC_SUCCESS:
864
                        if (pop3_session->cur_total_num > 0)
865
                                msg = g_strdup_printf
866
                                        (_("%d message(s) (%s) received"),
867
                                         pop3_session->cur_total_num,
868
                                         to_human_readable(pop3_session->cur_total_recv_bytes));
869
                        else
870
                                msg = g_strdup_printf(_("no new messages"));
871
                        SET_PIXMAP_AND_TEXT(ok_pixbuf, _("Done"), msg);
872
                        g_free(msg);
873
                        break;
874
                case INC_LOOKUP_ERROR:
875
                        SET_PIXMAP_AND_TEXT(error_pixbuf,
876
                                            _("Server not found"), NULL);
877
                        break;
878
                case INC_CONNECT_ERROR:
879
                        SET_PIXMAP_AND_TEXT(error_pixbuf,
880
                                            _("Connection failed"), NULL);
881
                        break;
882
                case INC_AUTH_FAILED:
883
                        SET_PIXMAP_AND_TEXT(error_pixbuf, _("Auth failed"),
884
                                            NULL);
885
                        break;
886
                case INC_LOCKED:
887
                        SET_PIXMAP_AND_TEXT(error_pixbuf, _("Locked"), NULL);
888
                        break;
889
                case INC_ERROR:
890
                case INC_NO_SPACE:
891
                case INC_IO_ERROR:
892
                case INC_SOCKET_ERROR:
893
                case INC_EOF:
894
                        SET_PIXMAP_AND_TEXT(error_pixbuf, _("Error"), NULL);
895
                        break;
896
                case INC_TIMEOUT:
897
                        SET_PIXMAP_AND_TEXT(error_pixbuf, _("Timeout"), NULL);
898
                        break;
899
                case INC_CANCEL:
900
                        SET_PIXMAP_AND_TEXT(ok_pixbuf, _("Cancelled"), NULL);
901
                        break;
902
                default:
903
                        break;
904
                }
905

    
906
                if (count_list)
907
                        *count_list = inc_add_message_count(*count_list, pop3_session->ac_prefs, session->new_msgs);
908
                new_msgs += session->new_msgs;
909

    
910
                if (!prefs_common.scan_all_after_inc) {
911
                        inc_update_folder_foreach(session->folder_table);
912
                }
913

    
914
                if (pop3_session->error_val == PS_AUTHFAIL &&
915
                    pop3_session->ac_prefs->tmp_pass) {
916
                        g_free(pop3_session->ac_prefs->tmp_pass);
917
                        pop3_session->ac_prefs->tmp_pass = NULL;
918
                }
919

    
920
                pop3_write_uidl_list(pop3_session);
921

    
922
                if (inc_state != INC_SUCCESS && inc_state != INC_CANCEL) {
923
                        error_num++;
924
                        if (inc_dialog->show_dialog)
925
                                manage_window_focus_in
926
                                        (inc_dialog->dialog->window,
927
                                         NULL, NULL);
928
                        inc_put_error(session, inc_state,
929
                                      pop3_session->error_msg);
930
                        if (inc_dialog->show_dialog)
931
                                manage_window_focus_out
932
                                        (inc_dialog->dialog->window,
933
                                         NULL, NULL);
934
                        if (inc_state == INC_NO_SPACE ||
935
                            inc_state == INC_IO_ERROR)
936
                                break;
937
                }
938

    
939
                inc_session_destroy(session);
940
                inc_dialog->queue_list =
941
                        g_list_remove(inc_dialog->queue_list, session);
942
        }
943

    
944
#undef SET_PIXMAP_AND_TEXT
945

    
946
        if (new_msgs > 0)
947
                fin_msg = g_strdup_printf(_("Finished (%d new message(s))"),
948
                                          new_msgs);
949
        else
950
                fin_msg = g_strdup_printf(_("Finished (no new messages)"));
951

    
952
        progress_dialog_set_label(inc_dialog->dialog, fin_msg);
953

    
954
#if 0
955
        if (error_num && !prefs_common.no_recv_err_panel) {
956
                if (inc_dialog->show_dialog)
957
                        manage_window_focus_in(inc_dialog->dialog->window,
958
                                               NULL, NULL);
959
                alertpanel_error(_("Some errors occurred while getting mail."));
960
                if (inc_dialog->show_dialog)
961
                        manage_window_focus_out(inc_dialog->dialog->window,
962
                                                NULL, NULL);
963
        }
964
#endif
965

    
966
        while (inc_dialog->queue_list != NULL) {
967
                session = inc_dialog->queue_list->data;
968
                inc_session_destroy(session);
969
                inc_dialog->queue_list =
970
                        g_list_remove(inc_dialog->queue_list, session);
971
        }
972

    
973
        if (prefs_common.close_recv_dialog || !inc_dialog->show_dialog)
974
                inc_progress_dialog_destroy(inc_dialog);
975
        else {
976
                gtk_window_set_title(GTK_WINDOW(inc_dialog->dialog->window),
977
                                     fin_msg);
978
                gtk_button_set_label(GTK_BUTTON(inc_dialog->dialog->cancel_btn),
979
                                     GTK_STOCK_CLOSE);
980
        }
981

    
982
        g_free(fin_msg);
983

    
984
        return new_msgs;
985
}
986

    
987
static IncState inc_pop3_session_do(IncSession *session)
988
{
989
        Pop3Session *pop3_session = POP3_SESSION(session->session);
990
        IncProgressDialog *inc_dialog = (IncProgressDialog *)session->data;
991
        PrefsAccount *ac = pop3_session->ac_prefs;
992
        SocksInfo *socks_info = NULL;
993
        gchar *buf;
994

    
995
        debug_print(_("getting new messages of account %s...\n"),
996
                    ac->account_name);
997

    
998
        if (pop3_session->auth_only)
999
                buf = g_strdup_printf(_("%s: Authenticating with POP3"),
1000
                                      ac->recv_server);
1001
        else
1002
                buf = g_strdup_printf(_("%s: Retrieving new messages"),
1003
                                      ac->recv_server);
1004
        gtk_window_set_title(GTK_WINDOW(inc_dialog->dialog->window), buf);
1005
        g_free(buf);
1006

    
1007
        buf = g_strdup_printf(_("Connecting to POP3 server: %s..."),
1008
                              ac->recv_server);
1009
        log_message("%s\n", buf);
1010
        progress_dialog_set_label(inc_dialog->dialog, buf);
1011
        g_free(buf);
1012

    
1013
        session_set_timeout(SESSION(pop3_session),
1014
                            prefs_common.io_timeout_secs * 1000);
1015

    
1016
        if (ac->use_socks && ac->use_socks_for_recv) {
1017
                socks_info = socks_info_new(ac->socks_type, ac->proxy_host, ac->proxy_port, ac->use_proxy_auth ? ac->proxy_name : NULL, ac->use_proxy_auth ? ac->proxy_pass : NULL);
1018
        }
1019

    
1020
        GTK_EVENTS_FLUSH();
1021

    
1022
        if (session_connect_full(SESSION(pop3_session),
1023
                                 SESSION(pop3_session)->server,
1024
                                 SESSION(pop3_session)->port, socks_info) < 0) {
1025
                log_warning(_("Can't connect to POP3 server: %s:%d\n"),
1026
                            SESSION(pop3_session)->server,
1027
                            SESSION(pop3_session)->port);
1028
                session->inc_state = INC_CONNECT_ERROR;
1029
                if (session_get_error(SESSION(pop3_session)) == SESSION_ERROR_LOOKUP)
1030
                        session->inc_state = INC_LOOKUP_ERROR;
1031
                statusbar_pop_all();
1032
                return session->inc_state;
1033
        }
1034

    
1035
        while (session_is_connected(SESSION(pop3_session)) &&
1036
               session->inc_state != INC_CANCEL) {
1037
                gtk_main_iteration();
1038
        }
1039
        log_window_flush();
1040

    
1041
        debug_print("inc_state: %d\n", session->inc_state);
1042
        debug_print("pop3_session.error_val: %d\n", pop3_session->error_val);
1043
        debug_print("pop3_session.error_msg: %s\n", pop3_session->error_msg ? pop3_session->error_msg : "(empty)");
1044

    
1045
        if (session->inc_state == INC_SUCCESS) {
1046
                switch (pop3_session->error_val) {
1047
                case PS_SUCCESS:
1048
                        switch (SESSION(pop3_session)->state) {
1049
                        case SESSION_ERROR:
1050
                                if (pop3_session->state == POP3_READY)
1051
                                        session->inc_state = INC_CONNECT_ERROR;
1052
                                else
1053
                                        session->inc_state = INC_ERROR;
1054
                                if (session_get_error(SESSION(pop3_session)) == SESSION_ERROR_LOOKUP)
1055
                                        session->inc_state = INC_LOOKUP_ERROR;
1056
                                break;
1057
                        case SESSION_EOF:
1058
                                session->inc_state = INC_EOF;
1059
                                break;
1060
                        case SESSION_TIMEOUT:
1061
                                session->inc_state = INC_TIMEOUT;
1062
                                break;
1063
                        default:
1064
                                session->inc_state = INC_SUCCESS;
1065
                                break;
1066
                        }
1067
                        break;
1068
                case PS_AUTHFAIL:
1069
                        session->inc_state = INC_AUTH_FAILED;
1070
                        break;
1071
                case PS_IOERR:
1072
                        session->inc_state = INC_IO_ERROR;
1073
                        break;
1074
                case PS_SOCKET:
1075
                        session->inc_state = INC_SOCKET_ERROR;
1076
                        break;
1077
                case PS_LOCKBUSY:
1078
                        session->inc_state = INC_LOCKED;
1079
                        break;
1080
                default:
1081
                        session->inc_state = INC_ERROR;
1082
                        break;
1083
                }
1084
        }
1085

    
1086
        session_disconnect(SESSION(pop3_session));
1087
        statusbar_pop_all();
1088

    
1089
        return session->inc_state;
1090
}
1091

    
1092
static void inc_progress_dialog_update(IncProgressDialog *inc_dialog,
1093
                                       IncSession *inc_session)
1094
{
1095
        inc_progress_dialog_set_label(inc_dialog, inc_session);
1096
        inc_progress_dialog_set_progress(inc_dialog, inc_session);
1097
}
1098

    
1099
static void inc_progress_dialog_set_label(IncProgressDialog *inc_dialog,
1100
                                          IncSession *inc_session)
1101
{
1102
        ProgressDialog *dialog = inc_dialog->dialog;
1103
        Pop3Session *session;
1104

    
1105
        g_return_if_fail(inc_session != NULL);
1106

    
1107
        session = POP3_SESSION(inc_session->session);
1108

    
1109
        switch (session->state) {
1110
        case POP3_GREETING:
1111
                break;
1112
        case POP3_GETAUTH_USER:
1113
        case POP3_GETAUTH_PASS:
1114
        case POP3_GETAUTH_APOP:
1115
                progress_dialog_set_label(dialog, _("Authenticating..."));
1116
                statusbar_print_all(_("Retrieving messages from %s..."),
1117
                                    SESSION(session)->server);
1118
                break;
1119
        case POP3_GETRANGE_STAT:
1120
                progress_dialog_set_label
1121
                        (dialog, _("Getting the number of new messages (STAT)..."));
1122
                break;
1123
        case POP3_GETRANGE_LAST:
1124
                progress_dialog_set_label
1125
                        (dialog, _("Getting the number of new messages (LAST)..."));
1126
                break;
1127
        case POP3_GETRANGE_UIDL:
1128
                progress_dialog_set_label
1129
                        (dialog, _("Getting the number of new messages (UIDL)..."));
1130
                break;
1131
        case POP3_GETSIZE_LIST:
1132
                progress_dialog_set_label
1133
                        (dialog, _("Getting the size of messages (LIST)..."));
1134
                break;
1135
        case POP3_RETR:
1136
        case POP3_RETR_RECV:
1137
                break;
1138
        case POP3_DELETE:
1139
#if 0
1140
                if (session->msg[session->cur_msg].recv_time <
1141
                        session->current_time) {
1142
                        gchar buf[BUFFSIZE];
1143
                        g_snprintf(buf, sizeof(buf), _("Deleting message %d"),
1144
                                   session->cur_msg);
1145
                        progress_dialog_set_label(dialog, buf);
1146
                }
1147
#endif
1148
                break;
1149
        case POP3_LOGOUT:
1150
                progress_dialog_set_label(dialog, _("Quitting"));
1151
                break;
1152
        default:
1153
                break;
1154
        }
1155
}
1156

    
1157
static void inc_progress_dialog_set_progress(IncProgressDialog *inc_dialog,
1158
                                             IncSession *inc_session)
1159
{
1160
        gchar buf[BUFFSIZE];
1161
        Pop3Session *pop3_session = POP3_SESSION(inc_session->session);
1162
        gint64 cur_total;
1163
        gint64 total;
1164
        gint cur_num;
1165
        gint total_num_to_recv;
1166

    
1167
        if (!pop3_session->new_msg_exist) return;
1168

    
1169
        if (inc_session->retr_count == 0) {
1170
                cur_num = total_num_to_recv = 0;
1171
                cur_total = total = 0;
1172
        } else {
1173
                cur_num = pop3_session->cur_msg - inc_session->start_num + 1;
1174
                total_num_to_recv = pop3_session->count - inc_session->start_num + 1;
1175
                cur_total = inc_session->cur_total_bytes - inc_session->start_recv_bytes;
1176
                total = pop3_session->total_bytes - inc_session->start_recv_bytes;
1177
        }
1178

    
1179
        if ((pop3_session->state == POP3_RETR ||
1180
             pop3_session->state == POP3_RETR_RECV ||
1181
             pop3_session->state == POP3_DELETE) && total_num_to_recv > 0) {
1182
                gchar total_size_str[16];
1183

    
1184
                to_human_readable_buf(total_size_str, sizeof(total_size_str),
1185
                                      total);
1186
                g_snprintf(buf, sizeof(buf),
1187
                           _("Retrieving message (%d / %d) (%s / %s)"),
1188
                           cur_num, total_num_to_recv,
1189
                           to_human_readable(cur_total), total_size_str);
1190
                progress_dialog_set_label(inc_dialog->dialog, buf);
1191
        }
1192

    
1193
        if (total > 0)
1194
                progress_dialog_set_percentage
1195
                        (inc_dialog->dialog, (gfloat)cur_total / (gfloat)total);
1196

    
1197
        gtk_progress_set_show_text
1198
                (GTK_PROGRESS(inc_dialog->mainwin->progressbar), TRUE);
1199
        if (total_num_to_recv > 0)
1200
                g_snprintf(buf, sizeof(buf), "%d / %d", cur_num, total_num_to_recv);
1201
        else
1202
                buf[0] = '\0';
1203
        gtk_progress_set_format_string
1204
                (GTK_PROGRESS(inc_dialog->mainwin->progressbar), buf);
1205
        if (total > 0)
1206
                gtk_progress_bar_update
1207
                        (GTK_PROGRESS_BAR(inc_dialog->mainwin->progressbar),
1208
                         (gfloat)cur_total / (gfloat)total);
1209

    
1210
        if (pop3_session->cur_total_num > 0) {
1211
                g_snprintf(buf, sizeof(buf),
1212
                           _("%d message(s) (%s) received"),
1213
                           pop3_session->cur_total_num,
1214
                           to_human_readable(pop3_session->cur_total_recv_bytes));
1215
                progress_dialog_set_row_progress(inc_dialog->dialog,
1216
                                                 inc_dialog->cur_row, buf);
1217
        }
1218
}
1219

    
1220
static gboolean hash_remove_func(gpointer key, gpointer value, gpointer data)
1221
{
1222
        return TRUE;
1223
}
1224

    
1225
static void inc_update_folderview(IncProgressDialog *inc_dialog,
1226
                                  IncSession *inc_session)
1227
{
1228
        MainWindow *mainwin;
1229

    
1230
        if (g_hash_table_size(inc_session->tmp_folder_table) > 0) {
1231
                folderview_update_item_foreach(inc_session->tmp_folder_table,
1232
                                               FALSE);
1233
                g_hash_table_foreach_remove(inc_session->tmp_folder_table,
1234
                                            hash_remove_func, NULL);
1235
        }
1236

    
1237
        mainwin = main_window_get();
1238
        summary_show_queued_msgs(mainwin->summaryview);
1239
}
1240

    
1241
static void inc_progress_dialog_update_periodic(IncProgressDialog *inc_dialog,
1242
                                                IncSession *inc_session)
1243
{
1244
        GTimeVal tv_cur;
1245
        GTimeVal tv_result;
1246
        gint msec;
1247

    
1248
        g_get_current_time(&tv_cur);
1249

    
1250
        tv_result.tv_sec = tv_cur.tv_sec - inc_dialog->progress_tv.tv_sec;
1251
        tv_result.tv_usec = tv_cur.tv_usec - inc_dialog->progress_tv.tv_usec;
1252
        if (tv_result.tv_usec < 0) {
1253
                tv_result.tv_sec--;
1254
                tv_result.tv_usec += G_USEC_PER_SEC;
1255
        }
1256

    
1257
        msec = tv_result.tv_sec * 1000 + tv_result.tv_usec / 1000;
1258
        if (msec > PROGRESS_UPDATE_INTERVAL) {
1259
                inc_progress_dialog_update(inc_dialog, inc_session);
1260
                inc_dialog->progress_tv.tv_sec = tv_cur.tv_sec;
1261
                inc_dialog->progress_tv.tv_usec = tv_cur.tv_usec;
1262
        }
1263
}
1264

    
1265
static void inc_update_folderview_periodic(IncProgressDialog *inc_dialog,
1266
                                           IncSession *inc_session)
1267
{
1268
        GTimeVal tv_cur;
1269
        GTimeVal tv_result;
1270
        gint msec;
1271

    
1272
        g_get_current_time(&tv_cur);
1273

    
1274
        tv_result.tv_sec = tv_cur.tv_sec - inc_dialog->folder_tv.tv_sec;
1275
        tv_result.tv_usec = tv_cur.tv_usec - inc_dialog->folder_tv.tv_usec;
1276
        if (tv_result.tv_usec < 0) {
1277
                tv_result.tv_sec--;
1278
                tv_result.tv_usec += G_USEC_PER_SEC;
1279
        }
1280

    
1281
        msec = tv_result.tv_sec * 1000 + tv_result.tv_usec / 1000;
1282
        if (msec > FOLDER_UPDATE_INTERVAL) {
1283
                inc_update_folderview(inc_dialog, inc_session);
1284
                inc_dialog->folder_tv.tv_sec = tv_cur.tv_sec;
1285
                inc_dialog->folder_tv.tv_usec = tv_cur.tv_usec;
1286
        }
1287
}
1288

    
1289
static gint inc_recv_data_progressive(Session *session, guint cur_len,
1290
                                      guint total_len, gpointer data)
1291
{
1292
        IncSession *inc_session = (IncSession *)data;
1293
        Pop3Session *pop3_session = POP3_SESSION(session);
1294
        IncProgressDialog *inc_dialog;
1295
        gint64 cur_total;
1296

    
1297
        g_return_val_if_fail(inc_session != NULL, -1);
1298

    
1299
        if (pop3_session->state != POP3_RETR &&
1300
            pop3_session->state != POP3_RETR_RECV &&
1301
            pop3_session->state != POP3_DELETE &&
1302
            pop3_session->state != POP3_LOGOUT) return 0;
1303

    
1304
        if (!pop3_session->new_msg_exist) return 0;
1305

    
1306
        gdk_threads_enter();
1307

    
1308
        cur_total = pop3_session->cur_total_bytes + cur_len;
1309
        if (cur_total > pop3_session->total_bytes)
1310
                cur_total = pop3_session->total_bytes;
1311
        inc_session->cur_total_bytes = cur_total;
1312

    
1313
        inc_dialog = (IncProgressDialog *)inc_session->data;
1314
        inc_progress_dialog_update_periodic(inc_dialog, inc_session);
1315
        inc_update_folderview_periodic(inc_dialog, inc_session);
1316

    
1317
        gdk_threads_leave();
1318
        return 0;
1319
}
1320

    
1321
static gint inc_recv_data_finished(Session *session, guint len, gpointer data)
1322
{
1323
        IncSession *inc_session = (IncSession *)data;
1324
        IncProgressDialog *inc_dialog;
1325

    
1326
        g_return_val_if_fail(inc_session != NULL, -1);
1327

    
1328
        inc_dialog = (IncProgressDialog *)inc_session->data;
1329

    
1330
        inc_recv_data_progressive(session, 0, 0, inc_session);
1331

    
1332
        gdk_threads_enter();
1333

    
1334
        if (POP3_SESSION(session)->state == POP3_LOGOUT) {
1335
                inc_progress_dialog_update(inc_dialog, inc_session);
1336
                inc_update_folderview(inc_dialog, inc_session);
1337
        }
1338

    
1339
        gdk_threads_leave();
1340
        return 0;
1341
}
1342

    
1343
static gint inc_recv_message(Session *session, const gchar *msg, gpointer data)
1344
{
1345
        IncSession *inc_session = (IncSession *)data;
1346
        IncProgressDialog *inc_dialog;
1347
        Pop3Session *pop3_session = POP3_SESSION(session);
1348

    
1349
        g_return_val_if_fail(inc_session != NULL, -1);
1350

    
1351
        inc_dialog = (IncProgressDialog *)inc_session->data;
1352

    
1353
        switch (POP3_SESSION(session)->state) {
1354
        case POP3_GETAUTH_USER:
1355
        case POP3_GETAUTH_PASS:
1356
        case POP3_GETAUTH_APOP:
1357
        case POP3_GETRANGE_STAT:
1358
        case POP3_GETRANGE_LAST:
1359
        case POP3_GETRANGE_UIDL:
1360
        case POP3_GETSIZE_LIST:
1361
                gdk_threads_enter();
1362
                inc_progress_dialog_update(inc_dialog, inc_session);
1363
                gdk_threads_leave();
1364
                break;
1365
        case POP3_RETR_RECV:
1366
                if (inc_session->retr_count == 0) {
1367
                        inc_session->start_num = pop3_session->cur_msg;
1368
                        inc_session->start_recv_bytes = pop3_session->cur_total_bytes;
1369
                        inc_session->cur_total_bytes = pop3_session->cur_total_bytes;
1370
#if 0
1371
                        g_print("total_bytes_to_recv = %lld total_num_to_recv = %d\n", pop3_session->total_bytes - inc_session->start_recv_bytes, pop3_session->count - inc_session->start_num + 1);
1372
                        g_print("pop: total_bytes = %lld cur_total_bytes = %lld\n", pop3_session->total_bytes, pop3_session->cur_total_bytes);
1373
                        g_print("pop: count = %d cur_msg = %d\n", pop3_session->count, pop3_session->cur_msg);
1374
#endif
1375
                        inc_session->retr_count++;
1376
                        gdk_threads_enter();
1377
                        inc_progress_dialog_update(inc_dialog, inc_session);
1378
                        gdk_threads_leave();
1379
                } else {
1380
                        inc_session->retr_count++;
1381
                        inc_recv_data_progressive(session, 0, 0, inc_session);
1382
                }
1383
                break;
1384
        case POP3_LOGOUT:
1385
                gdk_threads_enter();
1386
                inc_progress_dialog_update(inc_dialog, inc_session);
1387
                inc_update_folderview(inc_dialog, inc_session);
1388
                gdk_threads_leave();
1389
                break;
1390
        default:
1391
                break;
1392
        }
1393

    
1394
        return 0;
1395
}
1396

    
1397
static gint inc_drop_message(Pop3Session *session, const gchar *file)
1398
{
1399
        FolderItem *inbox;
1400
        GSList *cur;
1401
        MsgInfo *msginfo;
1402
        FilterInfo *fltinfo;
1403
        IncSession *inc_session = (IncSession *)(SESSION(session)->data);
1404
        gint val;
1405
        gboolean is_junk = FALSE;
1406
        gboolean is_counted = FALSE;
1407

    
1408
        g_return_val_if_fail(inc_session != NULL, DROP_ERROR);
1409

    
1410
        gdk_threads_enter();
1411

    
1412
        if (session->ac_prefs->inbox) {
1413
                inbox = folder_find_item_from_identifier
1414
                        (session->ac_prefs->inbox);
1415
                if (!inbox)
1416
                        inbox = folder_get_default_inbox();
1417
        } else
1418
                inbox = folder_get_default_inbox();
1419
        if (!inbox) {
1420
                gdk_threads_leave();
1421
                return DROP_ERROR;
1422
        }
1423

    
1424
        fltinfo = filter_info_new();
1425
        fltinfo->account = session->ac_prefs;
1426
        fltinfo->flags.perm_flags = MSG_NEW|MSG_UNREAD;
1427
        fltinfo->flags.tmp_flags = MSG_RECEIVED;
1428

    
1429
        msginfo = procheader_parse_file(file, fltinfo->flags, FALSE);
1430
        if (!msginfo) {
1431
                g_warning("inc_drop_message: procheader_parse_file failed");
1432
                filter_info_free(fltinfo);
1433
                gdk_threads_leave();
1434
                return DROP_ERROR;
1435
        }
1436
        fltinfo->flags = msginfo->flags;
1437
        msginfo->file_path = g_strdup(file);
1438

    
1439
        if (prefs_common.enable_junk &&
1440
            prefs_common.filter_junk_on_recv &&
1441
            prefs_common.filter_junk_before &&
1442
            inc_session->junk_fltlist) {
1443
                filter_apply_msginfo(inc_session->junk_fltlist, msginfo,
1444
                                     fltinfo);
1445
                if (fltinfo->drop_done)
1446
                        is_junk = TRUE;
1447
                else if (fltinfo->error == FLT_ERROR_EXEC_FAILED ||
1448
                         fltinfo->last_exec_exit_status >= 3) {
1449
                        g_warning("inc_drop_message: junk filter command returned %d",
1450
                                  fltinfo->last_exec_exit_status);
1451
                        alertpanel_error
1452
                                (_("Execution of the junk filter command failed.\n"
1453
                                   "Please check the junk mail control setting."));
1454
                        procmsg_msginfo_free(msginfo);
1455
                        filter_info_free(fltinfo);
1456
                        inc_session->inc_state = INC_ERROR;
1457
                        gdk_threads_leave();
1458
                        return DROP_ERROR;
1459
                }
1460
        }
1461

    
1462
        if (!fltinfo->drop_done && session->ac_prefs->filter_on_recv)
1463
                filter_apply_msginfo(prefs_common.fltlist, msginfo, fltinfo);
1464

    
1465
        if (!fltinfo->drop_done) {
1466
                if (prefs_common.enable_junk &&
1467
                    prefs_common.filter_junk_on_recv &&
1468
                    !prefs_common.filter_junk_before &&
1469
                    inc_session->junk_fltlist) {
1470
                        filter_apply_msginfo(inc_session->junk_fltlist,
1471
                                             msginfo, fltinfo);
1472
                        if (fltinfo->drop_done)
1473
                                is_junk = TRUE;
1474
                        else if (fltinfo->error == FLT_ERROR_EXEC_FAILED ||
1475
                                 fltinfo->last_exec_exit_status >= 3) {
1476
                                g_warning("inc_drop_message: junk filter command returned %d",
1477
                                          fltinfo->last_exec_exit_status);
1478
                                alertpanel_error
1479
                                        (_("Execution of the junk filter command failed.\n"
1480
                                           "Please check the junk mail control setting."));
1481
                                procmsg_msginfo_free(msginfo);
1482
                                filter_info_free(fltinfo);
1483
                                inc_session->inc_state = INC_ERROR;
1484
                                gdk_threads_leave();
1485
                                return DROP_ERROR;
1486
                        }
1487
                }
1488
        }
1489

    
1490
        if (!fltinfo->drop_done) {
1491
                msginfo->flags = fltinfo->flags;
1492
                if (folder_item_add_msg_msginfo(inbox, msginfo, FALSE) < 0) {
1493
                        procmsg_msginfo_free(msginfo);
1494
                        filter_info_free(fltinfo);
1495
                        gdk_threads_leave();
1496
                        return DROP_ERROR;
1497
                }
1498
                fltinfo->dest_list = g_slist_append(fltinfo->dest_list, inbox);
1499
        }
1500

    
1501
        for (cur = fltinfo->dest_list; cur != NULL; cur = cur->next) {
1502
                FolderItem *drop_folder = (FolderItem *)cur->data;
1503

    
1504
                val = GPOINTER_TO_INT(g_hash_table_lookup
1505
                                      (inc_session->folder_table, drop_folder));
1506
                if (val == 0)
1507
                        g_hash_table_insert(inc_session->folder_table,
1508
                                            drop_folder, GINT_TO_POINTER(1));
1509
                g_hash_table_insert(inc_session->tmp_folder_table, drop_folder,
1510
                                    GINT_TO_POINTER(1));
1511

    
1512
                if (drop_folder->stype != F_TRASH &&
1513
                    drop_folder->stype != F_JUNK)
1514
                        is_counted = TRUE;
1515
        }
1516

    
1517
        if (fltinfo->actions[FLT_ACTION_NOT_RECEIVE] == TRUE)
1518
                val = DROP_DONT_RECEIVE;
1519
        else if (fltinfo->actions[FLT_ACTION_DELETE] == TRUE)
1520
                val = DROP_DELETE;
1521
        else {
1522
                val = DROP_OK;
1523
                if (!is_junk && is_counted &&
1524
                    fltinfo->actions[FLT_ACTION_MARK_READ] == FALSE)
1525
                        inc_session->new_msgs++;
1526
        }
1527

    
1528
        procmsg_msginfo_free(msginfo);
1529
        filter_info_free(fltinfo);
1530

    
1531
        gdk_threads_leave();
1532
        return val;
1533
}
1534

    
1535
static void inc_put_error(IncSession *session, IncState istate, const gchar *pop3_msg)
1536
{
1537
        gchar *log_msg = NULL;
1538
        gchar *err_msg = NULL;
1539
        gboolean fatal_error = FALSE;
1540

    
1541
        switch (istate) {
1542
        case INC_LOOKUP_ERROR:
1543
                log_msg = _("Server not found.");
1544
                if (prefs_common.no_recv_err_panel)
1545
                        break;
1546
                err_msg = g_strdup_printf
1547
                        (_("Server %s not found."), session->session->server);
1548
                break;
1549
        case INC_CONNECT_ERROR:
1550
                log_msg = _("Connection failed.");
1551
                if (prefs_common.no_recv_err_panel)
1552
                        break;
1553
                err_msg = g_strdup_printf
1554
                        (_("Connection to %s:%d failed."),
1555
                         session->session->server, session->session->port);
1556
                break;
1557
        case INC_ERROR:
1558
                log_msg = _("Error occurred while processing mail.");
1559
                if (prefs_common.no_recv_err_panel)
1560
                        break;
1561
                if (pop3_msg)
1562
                        err_msg = g_strdup_printf
1563
                                (_("Error occurred while processing mail:\n%s"),
1564
                                 pop3_msg);
1565
                else
1566
                        err_msg = g_strdup(log_msg);
1567
                break;
1568
        case INC_NO_SPACE:
1569
                log_msg = _("No disk space left.");
1570
                err_msg = g_strdup(log_msg);
1571
                fatal_error = TRUE;
1572
                break;
1573
        case INC_IO_ERROR:
1574
                log_msg = _("Can't write file.");
1575
                err_msg = g_strdup(log_msg);
1576
                fatal_error = TRUE;
1577
                break;
1578
        case INC_SOCKET_ERROR:
1579
                log_msg = _("Socket error.");
1580
                if (prefs_common.no_recv_err_panel)
1581
                        break;
1582
                err_msg = g_strdup(log_msg);
1583
                break;
1584
        case INC_EOF:
1585
                log_msg = _("Connection closed by the remote host.");
1586
                if (prefs_common.no_recv_err_panel)
1587
                        break;
1588
                err_msg = g_strdup(log_msg);
1589
                break;
1590
        case INC_LOCKED:
1591
                log_msg = _("Mailbox is locked.");
1592
                if (prefs_common.no_recv_err_panel)
1593
                        break;
1594
                if (pop3_msg)
1595
                        err_msg = g_strdup_printf(_("Mailbox is locked:\n%s"),
1596
                                                  pop3_msg);
1597
                else
1598
                        err_msg = g_strdup(log_msg);
1599
                break;
1600
        case INC_AUTH_FAILED:
1601
                log_msg = _("Authentication failed.");
1602
                if (prefs_common.no_recv_err_panel)
1603
                        break;
1604
                if (pop3_msg)
1605
                        err_msg = g_strdup_printf
1606
                                (_("Authentication failed:\n%s"), pop3_msg);
1607
                else
1608
                        err_msg = g_strdup(log_msg);
1609
                break;
1610
        case INC_TIMEOUT:
1611
                log_msg = _("Session timed out.");
1612
                if (prefs_common.no_recv_err_panel)
1613
                        break;
1614
                err_msg = g_strdup(log_msg);
1615
                break;
1616
        default:
1617
                break;
1618
        }
1619

    
1620
        if (log_msg) {
1621
                if (fatal_error)
1622
                        log_error("%s\n", log_msg);
1623
                else
1624
                        log_warning("%s\n", log_msg);
1625
        }
1626
        if (err_msg) {
1627
                alertpanel_error("%s", err_msg);
1628
                g_free(err_msg);
1629
        }
1630
}
1631

    
1632
static void inc_cancel(IncProgressDialog *dialog, gboolean cancel_all)
1633
{
1634
        IncSession *session;
1635
        GList *list;
1636

    
1637
        g_return_if_fail(dialog != NULL);
1638

    
1639
        if (dialog->queue_list == NULL) {
1640
                inc_progress_dialog_destroy(dialog);
1641
                return;
1642
        }
1643

    
1644
        for (list = dialog->queue_list; list != NULL; list = list->next) {
1645
                session = list->data;
1646
                session->inc_state = INC_CANCEL;
1647
                session_disconnect(session->session);
1648
                if (!cancel_all)
1649
                        break;
1650
        }
1651

    
1652
        log_message(_("Incorporation cancelled\n"));
1653
}
1654

    
1655
gboolean inc_is_active(void)
1656
{
1657
        GList *cur;
1658

    
1659
        if (inc_is_running)
1660
                return TRUE;
1661

    
1662
        if (inc_dialog_list == NULL)
1663
                return FALSE;
1664

    
1665
        for (cur = inc_dialog_list; cur != NULL; cur = cur->next) {
1666
                IncProgressDialog *dialog = cur->data;
1667
                if (dialog->queue_list)
1668
                        return TRUE;
1669
        }
1670

    
1671
        return FALSE;
1672
}
1673

    
1674
void inc_block_notify(gboolean block)
1675
{
1676
        if (!block)
1677
                block_notify = FALSE;
1678
        else if (inc_is_active())
1679
                block_notify = TRUE;
1680
}
1681

    
1682
void inc_cancel_all(void)
1683
{
1684
        GList *cur;
1685

    
1686
        for (cur = inc_dialog_list; cur != NULL; cur = cur->next)
1687
                inc_cancel((IncProgressDialog *)cur->data, TRUE);
1688
}
1689

    
1690
static void inc_cancel_cb(GtkWidget *widget, gpointer data)
1691
{
1692
        inc_cancel((IncProgressDialog *)data, FALSE);
1693
}
1694

    
1695
static void inc_cancel_all_cb(GtkWidget *widget, gpointer data)
1696
{
1697
        inc_cancel((IncProgressDialog *)data, TRUE);
1698
}
1699

    
1700
static gint inc_dialog_delete_cb(GtkWidget *widget, GdkEventAny *event,
1701
                                 gpointer data)
1702
{
1703
        IncProgressDialog *dialog = (IncProgressDialog *)data;
1704

    
1705
        if (dialog->queue_list == NULL)
1706
                inc_progress_dialog_destroy(dialog);
1707
        else
1708
                inc_cancel(dialog, TRUE);
1709

    
1710
        return TRUE;
1711
}
1712

    
1713
static gint inc_spool(void)
1714
{
1715
        gchar *spool_path;
1716
        gchar *mbox;
1717
        gint msgs;
1718

    
1719
        spool_path = prefs_common.spool_path
1720
                ? prefs_common.spool_path : DEFAULT_SPOOL_PATH;
1721
        if (is_file_exist(spool_path))
1722
                mbox = g_strdup(spool_path);
1723
        else if (is_dir_exist(spool_path))
1724
                mbox = g_strconcat(spool_path, G_DIR_SEPARATOR_S,
1725
                                   g_get_user_name(), NULL);
1726
        else {
1727
                debug_print("%s: local mailbox not found.\n", spool_path);
1728
                return -1;
1729
        }
1730

    
1731
        msgs = get_spool(folder_get_default_inbox(), mbox);
1732
        g_free(mbox);
1733

    
1734
        return msgs;
1735
}
1736

    
1737
static gint get_spool(FolderItem *dest, const gchar *mbox)
1738
{
1739
        gint msgs, size;
1740
        gint lockfd;
1741
        gchar tmp_mbox[MAXPATHLEN + 1];
1742
        GHashTable *folder_table = NULL;
1743

    
1744
        g_return_val_if_fail(dest != NULL, -1);
1745
        g_return_val_if_fail(mbox != NULL, -1);
1746

    
1747
        if (!is_file_exist(mbox) || (size = get_file_size(mbox)) == 0) {
1748
                debug_print("%s: no messages in local mailbox.\n", mbox);
1749
                return 0;
1750
        } else if (size < 0)
1751
                return -1;
1752

    
1753
        if ((lockfd = lock_mbox(mbox, LOCK_FLOCK)) < 0)
1754
                return -1;
1755

    
1756
        g_snprintf(tmp_mbox, sizeof(tmp_mbox), "%s%ctmpmbox.%p",
1757
                   get_tmp_dir(), G_DIR_SEPARATOR, mbox);
1758

    
1759
        if (copy_mbox(mbox, tmp_mbox) < 0) {
1760
                unlock_mbox(mbox, lockfd, LOCK_FLOCK);
1761
                return -1;
1762
        }
1763

    
1764
        debug_print(_("Getting new messages from %s into %s...\n"),
1765
                    mbox, dest->path);
1766

    
1767
        folder_table = g_hash_table_new(NULL, NULL);
1768

    
1769
        msgs = proc_mbox_full(dest, tmp_mbox, folder_table,
1770
                              prefs_common.filter_on_inc,
1771
                              prefs_common.enable_junk &&
1772
                              prefs_common.filter_junk_on_recv);
1773

    
1774
        g_unlink(tmp_mbox);
1775
        if (msgs >= 0) empty_mbox(mbox);
1776
        unlock_mbox(mbox, lockfd, LOCK_FLOCK);
1777

    
1778
        if (!prefs_common.scan_all_after_inc) {
1779
                inc_update_folder_foreach(folder_table);
1780
        }
1781

    
1782
        g_hash_table_destroy(folder_table);
1783

    
1784
        return msgs;
1785
}
1786

    
1787
void inc_lock(void)
1788
{
1789
        inc_lock_count++;
1790
}
1791

    
1792
void inc_unlock(void)
1793
{
1794
        if (inc_lock_count > 0)
1795
                inc_lock_count--;
1796
}
1797

    
1798
static guint autocheck_timer = 0;
1799
static gpointer autocheck_data = NULL;
1800

    
1801
void inc_autocheck_timer_init(MainWindow *mainwin)
1802
{
1803
        autocheck_data = mainwin;
1804
        inc_autocheck_timer_set();
1805
}
1806

    
1807
static void inc_autocheck_timer_set_interval(guint interval)
1808
{
1809
        inc_autocheck_timer_remove();
1810

    
1811
        if (prefs_common.autochk_newmail && autocheck_data) {
1812
                autocheck_timer = g_timeout_add_full
1813
                        (G_PRIORITY_LOW, interval, inc_autocheck_func,
1814
                         autocheck_data, NULL);
1815
                debug_print("added timer = %d\n", autocheck_timer);
1816
        }
1817
}
1818

    
1819
void inc_autocheck_timer_set(void)
1820
{
1821
        inc_autocheck_timer_set_interval(prefs_common.autochk_itv * 60000);
1822
}
1823

    
1824
void inc_autocheck_timer_remove(void)
1825
{
1826
        if (autocheck_timer) {
1827
                debug_print("removed timer = %d\n", autocheck_timer);
1828
                g_source_remove(autocheck_timer);
1829
                autocheck_timer = 0;
1830
        }
1831
}
1832

    
1833
static gint inc_autocheck_func(gpointer data)
1834
{
1835
        MainWindow *mainwin = (MainWindow *)data;
1836

    
1837
        gdk_threads_enter();
1838

    
1839
        if (inc_lock_count) {
1840
                debug_print("autocheck is locked.\n");
1841
                inc_autocheck_timer_set_interval(1000);
1842
                gdk_threads_leave();
1843
                return FALSE;
1844
        }
1845

    
1846
        inc_all_account_mail(mainwin, TRUE);
1847

    
1848
        gdk_threads_leave();
1849

    
1850
        return FALSE;
1851
}