summaryrefslogtreecommitdiff
path: root/src/inc.c
diff options
context:
space:
mode:
authorSimeon Simeonov2018-02-26 11:23:00 +0100
committerSimeon Simeonov2018-02-26 11:23:00 +0100
commit0b3cbf57875fd692e4ba0b336fefa4bee1ed00dc (patch)
treeaf916a30553c78ce9d4f2d8658656a175c5b6921 /src/inc.c
Initial commit for sylpheed 3.7.0
Diffstat (limited to 'src/inc.c')
-rw-r--r--src/inc.c1936
1 files changed, 1936 insertions, 0 deletions
diff --git a/src/inc.c b/src/inc.c
new file mode 100644
index 0000000..011a9fa
--- /dev/null
+++ b/src/inc.c
@@ -0,0 +1,1936 @@
1/*
2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2014 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 "notificationwindow.h"
62#include "filter.h"
63#include "folder.h"
64#include "procheader.h"
65#include "plugin.h"
66
67
68typedef struct _IncAccountNewMsgCount
69{
70 PrefsAccount *account;
71 gint new_messages;
72} IncAccountNewMsgCount;
73
74typedef struct _IncMsgSummary
75{
76 gchar *subject;
77 gchar *from;
78} IncMsgSummary;
79
80struct _IncResult
81{
82 GSList *count_list;
83 GSList *msg_summaries;
84};
85
86
87static GList *inc_dialog_list = NULL;
88
89static gboolean inc_is_running = FALSE;
90
91static guint inc_lock_count = 0;
92static gboolean block_notify = FALSE;
93
94static GdkPixbuf *current_pixbuf;
95static GdkPixbuf *error_pixbuf;
96static GdkPixbuf *ok_pixbuf;
97
98
99static void inc_finished (MainWindow *mainwin,
100 IncResult *result);
101static GSList *inc_add_message_count (GSList *list,
102 PrefsAccount *account,
103 gint new_messages);
104static void inc_result_free (IncResult *result,
105 gboolean free_self);
106
107static gint inc_remote_account_mail (MainWindow *mainwin,
108 PrefsAccount *account);
109static gint inc_account_mail_real (MainWindow *mainwin,
110 PrefsAccount *account,
111 IncResult *result);
112
113static IncProgressDialog *inc_progress_dialog_create
114 (gboolean autocheck);
115static void inc_progress_dialog_set_list(IncProgressDialog *inc_dialog);
116static void inc_progress_dialog_destroy (IncProgressDialog *inc_dialog);
117
118static IncSession *inc_session_new (PrefsAccount *account);
119static void inc_session_destroy (IncSession *session);
120static gint inc_start (IncProgressDialog *inc_dialog);
121static IncState inc_pop3_session_do (IncSession *session);
122
123static void inc_progress_dialog_update (IncProgressDialog *inc_dialog,
124 IncSession *inc_session);
125
126static void inc_progress_dialog_set_label
127 (IncProgressDialog *inc_dialog,
128 IncSession *inc_session);
129static void inc_progress_dialog_set_progress
130 (IncProgressDialog *inc_dialog,
131 IncSession *inc_session);
132
133static void inc_update_folderview (IncProgressDialog *inc_dialog,
134 IncSession *inc_session);
135
136static void inc_progress_dialog_update_periodic
137 (IncProgressDialog *inc_dialog,
138 IncSession *inc_session);
139static void inc_update_folderview_periodic
140 (IncProgressDialog *inc_dialog,
141 IncSession *inc_session);
142
143static gint inc_recv_data_progressive (Session *session,
144 guint cur_len,
145 guint total_len,
146 gpointer data);
147static gint inc_recv_data_finished (Session *session,
148 guint len,
149 gpointer data);
150static gint inc_recv_message (Session *session,
151 const gchar *msg,
152 gpointer data);
153static gint inc_drop_message (Pop3Session *session,
154 const gchar *file);
155
156static void inc_put_error (IncSession *session,
157 IncState istate,
158 const gchar *pop3_msg);
159
160static void inc_cancel_cb (GtkWidget *widget,
161 gpointer data);
162static void inc_cancel_all_cb (GtkWidget *widget,
163 gpointer data);
164static gint inc_dialog_delete_cb (GtkWidget *widget,
165 GdkEventAny *event,
166 gpointer data);
167
168static gint inc_spool (void);
169static gint get_spool (FolderItem *dest,
170 const gchar *mbox);
171
172static void inc_autocheck_timer_set_interval (guint interval);
173static gint inc_autocheck_func (gpointer data);
174
175
176/**
177 * inc_finished:
178 * @mainwin: Main window.
179 * @result: Information of incorporation result.
180 * @new_messages: Number of received messages.
181 *
182 * Update the folder view and the summary view after receiving
183 * messages. If @new_messages is 0, this function avoids unneeded
184 * updating.
185 **/
186static void inc_finished(MainWindow *mainwin, IncResult *result)
187{
188 FolderItem *item;
189 gint new_messages = 0;
190 gint other_new = 0;
191 IncAccountNewMsgCount *count;
192 GSList *cur;
193
194 if (result) {
195 for (cur = result->count_list; cur != NULL; cur = cur->next) {
196 count = cur->data;
197 if (count->new_messages > 0)
198 new_messages += count->new_messages;
199 }
200 }
201
202 debug_print("inc_finished: %d new message(s)\n", new_messages);
203
204 if (prefs_common.scan_all_after_inc) {
205 other_new = folderview_check_new(NULL);
206 new_messages += other_new;
207 }
208
209 if (new_messages > 0 && !block_notify) {
210 GString *str;
211 gint c = 0;
212
213 str = g_string_new("");
214 g_string_printf(str, _("Sylpheed: %d new messages"),
215 new_messages);
216 if (result) {
217 for (cur = result->count_list; cur != NULL; cur = cur->next) {
218 count = cur->data;
219 if (count->new_messages > 0) {
220 if (c == 0)
221 g_string_append(str, "\n");
222 c++;
223 g_string_append(str, "\n");
224 if (!count->account)
225 g_string_append_printf(str, _("[Local]: %d"), count->new_messages);
226 else
227 g_string_append_printf(str, "%s: %d", count->account->account_name ? count->account->account_name : "[?]", count->new_messages);
228 }
229 }
230 }
231 debug_print("inc_finished: %s\n", str->str);
232 trayicon_set_tooltip(str->str);
233 trayicon_set_notify(TRUE);
234
235 if (prefs_common.enable_newmsg_notify_window) {
236 gchar buf[1024];
237
238 g_snprintf(buf, sizeof(buf), _("Sylpheed: %d new messages"), new_messages);
239 g_string_truncate(str, 0);
240 if (result) {
241 for (cur = result->msg_summaries; cur != NULL; cur = cur->next) {
242 IncMsgSummary *summary = cur->data;
243 gchar *markup;
244
245 if (str->len > 0)
246 g_string_append_c(str, '\n');
247 markup = g_markup_printf_escaped("<b>%s</b> %s", summary->subject, summary->from);
248 g_string_append(str, markup);
249 g_free(markup);
250 }
251 }
252
253 notification_window_open(buf, str->str, prefs_common.notify_window_period);
254 }
255
256 g_string_free(str, TRUE);
257 }
258
259 syl_plugin_signal_emit("inc-mail-finished", new_messages);
260
261 inc_block_notify(FALSE);
262
263 if (new_messages <= 0 && !prefs_common.scan_all_after_inc) return;
264
265 if (prefs_common.open_inbox_on_inc) {
266 item = cur_account && cur_account->inbox
267 ? folder_find_item_from_identifier(cur_account->inbox)
268 : folder_get_default_inbox();
269 folderview_select(mainwin->folderview, item);
270 } else if (prefs_common.scan_all_after_inc) {
271 item = mainwin->summaryview->folder_item;
272 if (item)
273 folderview_update_item(item, TRUE);
274 }
275
276 /* Notification */
277
278 if (new_messages > 0 &&
279 prefs_common.enable_newmsg_notify_sound &&
280 prefs_common.newmsg_notify_sound) {
281 play_sound(prefs_common.newmsg_notify_sound, TRUE);
282 }
283
284 if (new_messages > 0 &&
285 prefs_common.enable_newmsg_notify &&
286 prefs_common.newmsg_notify_cmd) {
287 gchar buf[1024];
288
289 if (str_find_format_times
290 (prefs_common.newmsg_notify_cmd, 'd') == 1)
291 g_snprintf(buf, sizeof(buf),
292 prefs_common.newmsg_notify_cmd,
293 new_messages);
294 else
295 strncpy2(buf, prefs_common.newmsg_notify_cmd,
296 sizeof(buf));
297 execute_command_line(buf, TRUE);
298 }
299}
300
301static GSList *inc_add_message_count(GSList *list, PrefsAccount *account,
302 gint new_messages)
303{
304 IncAccountNewMsgCount *count;
305
306 count = g_new(IncAccountNewMsgCount, 1);
307 count->account = account;
308 count->new_messages = new_messages;
309
310 return g_slist_append(list, count);
311}
312
313static void inc_result_free(IncResult *result, gboolean free_self)
314{
315 GSList *cur;
316
317 slist_free_strings(result->count_list);
318 g_slist_free(result->count_list);
319 for (cur = result->msg_summaries; cur != NULL; cur = cur->next) {
320 IncMsgSummary *sum = cur->data;
321 g_free(sum->subject);
322 g_free(sum->from);
323 g_free(sum);
324 }
325 g_slist_free(result->msg_summaries);
326
327 if (free_self)
328 g_free(result);
329}
330
331void inc_mail(MainWindow *mainwin)
332{
333 IncResult result = {NULL, NULL};
334 gint new_msgs = 0;
335
336 if (inc_lock_count) return;
337 if (inc_is_active()) return;
338
339 if (!main_window_toggle_online_if_offline(mainwin))
340 return;
341
342 inc_is_running = TRUE;
343
344 inc_autocheck_timer_remove();
345 summary_write_cache(mainwin->summaryview);
346 main_window_lock(mainwin);
347
348 syl_plugin_signal_emit("inc-mail-start", cur_account);
349
350 if (prefs_common.use_extinc && prefs_common.extinc_cmd) {
351 /* external incorporating program */
352 if (execute_command_line(prefs_common.extinc_cmd, FALSE) != 0) {
353 inc_is_running = FALSE;
354 main_window_unlock(mainwin);
355 inc_autocheck_timer_set();
356 return;
357 }
358
359 if (prefs_common.inc_local) {
360 new_msgs = inc_spool();
361 result.count_list = inc_add_message_count(result.count_list, NULL, new_msgs);
362 }
363 } else {
364 if (prefs_common.inc_local) {
365 new_msgs = inc_spool();
366 if (new_msgs < 0)
367 new_msgs = 0;
368 result.count_list = inc_add_message_count(result.count_list, NULL, new_msgs);
369 }
370
371 new_msgs = inc_account_mail_real(mainwin, cur_account, &result);
372 }
373
374 inc_finished(mainwin, &result);
375 inc_result_free(&result, FALSE);
376
377 inc_is_running = FALSE;
378
379 main_window_unlock(mainwin);
380 inc_autocheck_timer_set();
381}
382
383static gint inc_remote_account_mail(MainWindow *mainwin, PrefsAccount *account)
384{
385 FolderItem *item = mainwin->summaryview->folder_item;
386 gint new_msgs = 0;
387 gboolean update_summary = FALSE;
388
389 g_return_val_if_fail(account != NULL, 0);
390 g_return_val_if_fail(account->folder != NULL, 0);
391
392 if (account->protocol == A_IMAP4 &&
393 account->imap_filter_inbox_on_recv) {
394 FolderItem *inbox = FOLDER(account->folder)->inbox;
395 GSList *mlist, *cur;
396 FilterInfo *fltinfo;
397 GSList junk_fltlist = {NULL, NULL};
398 FilterRule *junk_rule;
399 gint n_filtered = 0;
400
401 debug_print("inc_remote_account_mail(): filtering IMAP4 INBOX\n");
402 mlist = folder_item_get_uncached_msg_list(inbox);
403 debug_print("inc_remote_account_mail(): uncached messages: %d\n", g_slist_length(mlist));
404
405 junk_rule = filter_junk_rule_create(account, NULL, TRUE);
406 if (junk_rule)
407 junk_fltlist.data = junk_rule;
408
409 for (cur = mlist; cur != NULL; cur = cur->next) {
410 MsgInfo *msginfo = (MsgInfo *)cur->data;
411 gboolean is_junk = FALSE;
412
413 fltinfo = filter_info_new();
414 fltinfo->account = account;
415 fltinfo->flags = msginfo->flags;
416
417 if (prefs_common.enable_junk &&
418 prefs_common.filter_junk_on_recv &&
419 prefs_common.filter_junk_before && junk_rule) {
420 filter_apply_msginfo
421 (&junk_fltlist, msginfo, fltinfo);
422 if (fltinfo->drop_done)
423 is_junk = TRUE;
424 }
425
426 if (!fltinfo->drop_done) {
427 filter_apply_msginfo(prefs_common.fltlist,
428 msginfo, fltinfo);
429 }
430
431 if (!fltinfo->drop_done &&
432 prefs_common.enable_junk &&
433 prefs_common.filter_junk_on_recv &&
434 !prefs_common.filter_junk_before && junk_rule) {
435 filter_apply_msginfo
436 (&junk_fltlist, msginfo, fltinfo);
437 if (fltinfo->drop_done)
438 is_junk = TRUE;
439 }
440
441 if (msginfo->flags.perm_flags !=
442 fltinfo->flags.perm_flags) {
443 msginfo->flags = fltinfo->flags;
444 inbox->mark_dirty = TRUE;
445 if (fltinfo->actions[FLT_ACTION_MARK])
446 imap_msg_set_perm_flags
447 (msginfo, MSG_MARKED);
448 if (fltinfo->actions[FLT_ACTION_MARK_READ])
449 imap_msg_unset_perm_flags
450 (msginfo, MSG_NEW|MSG_UNREAD);
451 }
452
453 if (fltinfo->actions[FLT_ACTION_MOVE] &&
454 fltinfo->move_dest) {
455 folder_item_move_msg
456 (fltinfo->move_dest, msginfo);
457 if (account->imap_check_inbox_only ||
458 fltinfo->move_dest->folder !=
459 inbox->folder) {
460 if (!is_junk &&
461 fltinfo->move_dest->stype != F_TRASH &&
462 fltinfo->move_dest->stype != F_JUNK &&
463 (MSG_IS_NEW(fltinfo->flags) ||
464 MSG_IS_UNREAD(fltinfo->flags)))
465 ++new_msgs;
466 }
467 } else if (fltinfo->actions[FLT_ACTION_DELETE])
468 folder_item_remove_msg(inbox, msginfo);
469 else if (!is_junk && (MSG_IS_NEW(msginfo->flags) ||
470 MSG_IS_UNREAD(msginfo->flags)))
471 ++new_msgs;
472
473 if (fltinfo->drop_done)
474 ++n_filtered;
475
476 filter_info_free(fltinfo);
477 }
478
479 if (junk_rule)
480 filter_rule_free(junk_rule);
481
482 procmsg_msg_list_free(mlist);
483
484 debug_print("inc_remote_account_mail(): INBOX: %d new, %d filtered\n",
485 new_msgs, n_filtered);
486
487 if (!prefs_common.scan_all_after_inc && item != NULL &&
488 inbox == item)
489 update_summary = TRUE;
490 }
491
492 if (account->protocol == A_IMAP4 && account->imap_check_inbox_only) {
493 FolderItem *inbox = FOLDER(account->folder)->inbox;
494
495 new_msgs += folderview_check_new_item(inbox);
496 if (!prefs_common.scan_all_after_inc && item != NULL &&
497 inbox == item)
498 update_summary = TRUE;
499 } else {
500 new_msgs += folderview_check_new(FOLDER(account->folder));
501 if (!prefs_common.scan_all_after_inc && item != NULL &&
502 FOLDER(account->folder) == item->folder)
503 update_summary = TRUE;
504 }
505
506 if (update_summary)
507 folderview_update_item(item, TRUE);
508 folderview_update_all_updated(FALSE);
509
510 return new_msgs;
511}
512
513static gint inc_account_mail_real(MainWindow *mainwin, PrefsAccount *account,
514 IncResult *result)
515{
516 IncProgressDialog *inc_dialog;
517 IncSession *session;
518
519 g_return_val_if_fail(account != NULL, 0);
520
521 if (account->protocol == A_IMAP4 || account->protocol == A_NNTP)
522 return inc_remote_account_mail(mainwin, account);
523
524 session = inc_session_new(account);
525 if (!session) return 0;
526
527 inc_dialog = inc_progress_dialog_create(FALSE);
528 inc_dialog->queue_list = g_list_append(inc_dialog->queue_list, session);
529 inc_dialog->mainwin = mainwin;
530 inc_dialog->result = result;
531 inc_progress_dialog_set_list(inc_dialog);
532
533 main_window_set_toolbar_sensitive(mainwin);
534 main_window_set_menu_sensitive(mainwin);
535
536 return inc_start(inc_dialog);
537}
538
539gint inc_account_mail(MainWindow *mainwin, PrefsAccount *account)
540{
541 IncResult result = {NULL, NULL};
542 gint new_msgs;
543
544 if (inc_lock_count) return 0;
545 if (inc_is_active()) return 0;
546
547 if (!main_window_toggle_online_if_offline(mainwin))
548 return 0;
549
550 inc_is_running = TRUE;
551
552 inc_autocheck_timer_remove();
553 summary_write_cache(mainwin->summaryview);
554 main_window_lock(mainwin);
555
556 syl_plugin_signal_emit("inc-mail-start", account);
557
558 new_msgs = inc_account_mail_real(mainwin, account, &result);
559
560 inc_finished(mainwin, &result);
561 inc_result_free(&result, FALSE);
562
563 inc_is_running = FALSE;
564
565 main_window_unlock(mainwin);
566 inc_autocheck_timer_set();
567
568 return new_msgs;
569}
570
571void inc_all_account_mail(MainWindow *mainwin, gboolean autocheck)
572{
573 GList *list, *queue_list = NULL;
574 IncProgressDialog *inc_dialog;
575 IncResult result = {NULL, NULL};
576 gint new_msgs = 0;
577
578 if (inc_lock_count) return;
579 if (inc_is_active()) return;
580
581 if (!main_window_toggle_online_if_offline(mainwin))
582 return;
583
584 inc_is_running = TRUE;
585
586 inc_autocheck_timer_remove();
587 summary_write_cache(mainwin->summaryview);
588 main_window_lock(mainwin);
589
590 syl_plugin_signal_emit("inc-mail-start", NULL);
591
592 if (prefs_common.inc_local) {
593 new_msgs = inc_spool();
594 if (new_msgs < 0)
595 new_msgs = 0;
596 result.count_list = inc_add_message_count(result.count_list, NULL, new_msgs);
597 }
598
599 /* check IMAP4 / News folders */
600 for (list = account_get_list(); list != NULL; list = list->next) {
601 PrefsAccount *account = list->data;
602 if ((account->protocol == A_IMAP4 ||
603 account->protocol == A_NNTP) && account->recv_at_getall) {
604 new_msgs = inc_remote_account_mail(mainwin, account);
605 result.count_list = inc_add_message_count(result.count_list, account, new_msgs);
606 }
607 }
608
609 /* check POP3 accounts */
610 for (list = account_get_list(); list != NULL; list = list->next) {
611 IncSession *session;
612 PrefsAccount *account = list->data;
613
614 if (account->recv_at_getall) {
615 session = inc_session_new(account);
616 if (session)
617 queue_list = g_list_append(queue_list, session);
618 }
619 }
620
621 if (queue_list) {
622 inc_dialog = inc_progress_dialog_create(autocheck);
623 inc_dialog->queue_list = queue_list;
624 inc_dialog->mainwin = mainwin;
625 inc_dialog->result = &result;
626 inc_progress_dialog_set_list(inc_dialog);
627
628 main_window_set_toolbar_sensitive(mainwin);
629 main_window_set_menu_sensitive(mainwin);
630
631 inc_start(inc_dialog);
632 }
633
634 inc_finished(mainwin, &result);
635 inc_result_free(&result, FALSE);
636
637 inc_is_running = FALSE;
638
639 main_window_unlock(mainwin);
640 inc_autocheck_timer_set();
641}
642
643gint inc_pop_before_smtp(PrefsAccount *account)
644{
645 MainWindow *mainwin;
646 IncProgressDialog *inc_dialog;
647 IncSession *session;
648
649 if (inc_lock_count) return -1;
650
651 mainwin = main_window_get();
652
653 if (!main_window_toggle_online_if_offline(mainwin))
654 return -1;
655
656 inc_is_running = TRUE;
657
658 inc_autocheck_timer_remove();
659 main_window_lock(mainwin);
660
661 session = inc_session_new(account);
662 if (!session) return -1;
663 POP3_SESSION(session->session)->auth_only = TRUE;
664
665 inc_dialog = inc_progress_dialog_create(FALSE);
666 gtk_window_set_title(GTK_WINDOW(inc_dialog->dialog->window),
667 _("Authenticating with POP3"));
668 inc_dialog->queue_list = g_list_append(inc_dialog->queue_list, session);
669 inc_dialog->mainwin = mainwin;
670 inc_dialog->result = NULL;
671 inc_progress_dialog_set_list(inc_dialog);
672 inc_dialog->show_dialog = TRUE;
673
674 main_window_set_toolbar_sensitive(mainwin);
675 main_window_set_menu_sensitive(mainwin);
676
677 inc_start(inc_dialog);
678
679 inc_is_running = FALSE;
680
681 main_window_unlock(mainwin);
682 inc_autocheck_timer_set();
683
684 return 0;
685}
686
687static IncProgressDialog *inc_progress_dialog_create(gboolean autocheck)
688{
689 IncProgressDialog *dialog;
690 ProgressDialog *progress;
691 GtkWidget *cancel_all_btn;
692
693 dialog = g_new0(IncProgressDialog, 1);
694
695 progress = progress_dialog_create();
696 gtk_window_set_title(GTK_WINDOW(progress->window),
697 _("Retrieving new messages"));
698 cancel_all_btn = gtk_dialog_add_button(GTK_DIALOG(progress->window),
699 _("Cancel _all"),
700 GTK_RESPONSE_NONE);
701 g_signal_connect(G_OBJECT(progress->cancel_btn), "clicked",
702 G_CALLBACK(inc_cancel_cb), dialog);
703 g_signal_connect(G_OBJECT(cancel_all_btn), "clicked",
704 G_CALLBACK(inc_cancel_all_cb), dialog);
705 g_signal_connect(G_OBJECT(progress->window), "delete_event",
706 G_CALLBACK(inc_dialog_delete_cb), dialog);
707 /* manage_window_set_transient(GTK_WINDOW(progress->window)); */
708
709 progress_dialog_set_value(progress, 0.0);
710
711 stock_pixbuf_gdk(progress->treeview, STOCK_PIXMAP_COMPLETE, &ok_pixbuf);
712 stock_pixbuf_gdk(progress->treeview, STOCK_PIXMAP_CONTINUE,
713 &current_pixbuf);
714 stock_pixbuf_gdk(progress->treeview, STOCK_PIXMAP_ERROR, &error_pixbuf);
715
716 if (prefs_common.recv_dialog_mode == RECV_DIALOG_ALWAYS ||
717 (prefs_common.recv_dialog_mode == RECV_DIALOG_MANUAL &&
718 !autocheck)) {
719 dialog->show_dialog = TRUE;
720 gtk_widget_show_now(progress->window);
721 }
722
723 dialog->dialog = progress;
724 g_get_current_time(&dialog->progress_tv);
725 g_get_current_time(&dialog->folder_tv);
726 dialog->queue_list = NULL;
727 dialog->cur_row = 0;
728
729 inc_dialog_list = g_list_append(inc_dialog_list, dialog);
730
731 return dialog;
732}
733
734static void inc_progress_dialog_set_list(IncProgressDialog *inc_dialog)
735{
736 GList *list;
737
738 for (list = inc_dialog->queue_list; list != NULL; list = list->next) {
739 IncSession *session = list->data;
740 Pop3Session *pop3_session = POP3_SESSION(session->session);
741
742 session->data = inc_dialog;
743 progress_dialog_append(inc_dialog->dialog, NULL,
744 pop3_session->ac_prefs->account_name,
745 _("Standby"), "", NULL);
746 }
747}
748
749static void inc_progress_dialog_clear(IncProgressDialog *inc_dialog)
750{
751 progress_dialog_set_value(inc_dialog->dialog, 0.0);
752 progress_dialog_set_label(inc_dialog->dialog, "");
753 main_window_progress_off(inc_dialog->mainwin);
754}
755
756static void inc_progress_dialog_destroy(IncProgressDialog *inc_dialog)
757{
758 g_return_if_fail(inc_dialog != NULL);
759
760 inc_dialog_list = g_list_remove(inc_dialog_list, inc_dialog);
761
762 manage_window_destroy(inc_dialog->dialog->window, NULL);
763
764 main_window_progress_off(inc_dialog->mainwin);
765 progress_dialog_destroy(inc_dialog->dialog);
766
767 g_free(inc_dialog);
768}
769
770static IncSession *inc_session_new(PrefsAccount *account)
771{
772 IncSession *session;
773 FilterRule *rule;
774
775 g_return_val_if_fail(account != NULL, NULL);
776
777 if (account->protocol != A_POP3)
778 return NULL;
779 if (!account->recv_server || !account->userid)
780 return NULL;
781
782 session = g_new0(IncSession, 1);
783
784 session->session = pop3_session_new(account);
785 session->session->data = session;
786 POP3_SESSION(session->session)->drop_message = inc_drop_message;
787 session_set_recv_message_notify(session->session,
788 inc_recv_message, session);
789 session_set_recv_data_progressive_notify(session->session,
790 inc_recv_data_progressive,
791 session);
792 session_set_recv_data_notify(session->session,
793 inc_recv_data_finished, session);
794
795 session->inc_state = INC_SUCCESS;
796
797 session->folder_table = g_hash_table_new(NULL, NULL);
798 session->tmp_folder_table = g_hash_table_new(NULL, NULL);
799
800 rule = filter_junk_rule_create(account, NULL, FALSE);
801 if (rule)
802 session->junk_fltlist = g_slist_append(NULL, rule);
803 else
804 session->junk_fltlist = NULL;
805
806 session->cur_total_bytes = 0;
807 session->new_msgs = 0;
808
809 session->start_num = 0;
810 session->start_recv_bytes = 0;
811
812 session->retr_count = 0;
813
814 return session;
815}
816
817static void inc_session_destroy(IncSession *session)
818{
819 g_return_if_fail(session != NULL);
820
821 session_destroy(session->session);
822 g_hash_table_destroy(session->folder_table);
823 g_hash_table_destroy(session->tmp_folder_table);
824 if (session->junk_fltlist)
825 filter_rule_list_free(session->junk_fltlist);
826 g_free(session);
827}
828
829static void inc_update_folder_foreach(GHashTable *table)
830{
831 procmsg_flush_folder_foreach(table);
832 folderview_update_item_foreach(table, TRUE);
833}
834
835static gint inc_start(IncProgressDialog *inc_dialog)
836{
837 IncSession *session;
838 GList *qlist;
839 Pop3Session *pop3_session;
840 IncState inc_state;
841 gint error_num = 0;
842 gint new_msgs = 0;
843 gchar *msg;
844 gchar *fin_msg;
845
846 qlist = inc_dialog->queue_list;
847 while (qlist != NULL) {
848 GList *next = qlist->next;
849
850 session = qlist->data;
851 if (session->inc_state == INC_CANCEL) {
852 qlist = next;
853 continue;
854 }
855
856 pop3_session = POP3_SESSION(session->session);
857 if (!pop3_session->pass) {
858 gchar *pass;
859
860 if (inc_dialog->show_dialog)
861 manage_window_focus_in
862 (inc_dialog->dialog->window,
863 NULL, NULL);
864
865 pass = input_query_password
866 (pop3_session->ac_prefs->recv_server,
867 pop3_session->user);
868
869 if (inc_dialog->show_dialog)
870 manage_window_focus_out
871 (inc_dialog->dialog->window,
872 NULL, NULL);
873
874 if (pass) {
875 pop3_session->ac_prefs->tmp_pass =
876 g_strdup(pass);
877 pop3_session->pass = pass;
878 }
879 }
880
881 qlist = next;
882 }
883
884#define SET_PIXMAP_AND_TEXT(pixbuf, status, progress) \
885{ \
886 progress_dialog_set_row_pixbuf(inc_dialog->dialog, \
887 inc_dialog->cur_row, pixbuf); \
888 progress_dialog_set_row_status(inc_dialog->dialog, \
889 inc_dialog->cur_row, status); \
890 if (progress) \
891 progress_dialog_set_row_progress(inc_dialog->dialog, \
892 inc_dialog->cur_row, \
893 progress); \
894}
895
896 for (; inc_dialog->queue_list != NULL; inc_dialog->cur_row++) {
897 session = inc_dialog->queue_list->data;
898 pop3_session = POP3_SESSION(session->session);
899
900 if (session->inc_state == INC_CANCEL ||
901 pop3_session->pass == NULL) {
902 SET_PIXMAP_AND_TEXT(ok_pixbuf, _("Cancelled"), NULL);
903 inc_session_destroy(session);
904 inc_dialog->queue_list =
905 g_list_remove(inc_dialog->queue_list, session);
906 continue;
907 }
908
909 inc_progress_dialog_clear(inc_dialog);
910 progress_dialog_scroll_to_row(inc_dialog->dialog,
911 inc_dialog->cur_row);
912
913 SET_PIXMAP_AND_TEXT(current_pixbuf, _("Retrieving"), NULL);
914
915 /* begin POP3 session */
916 inc_state = inc_pop3_session_do(session);
917
918 switch (inc_state) {
919 case INC_SUCCESS:
920 if (pop3_session->cur_total_num > 0)
921 msg = g_strdup_printf
922 (_("%d message(s) (%s) received"),
923 pop3_session->cur_total_num,
924 to_human_readable(pop3_session->cur_total_recv_bytes));
925 else
926 msg = g_strdup_printf(_("no new messages"));
927 SET_PIXMAP_AND_TEXT(ok_pixbuf, _("Done"), msg);
928 g_free(msg);
929 break;
930 case INC_LOOKUP_ERROR:
931 SET_PIXMAP_AND_TEXT(error_pixbuf,
932 _("Server not found"), NULL);
933 break;
934 case INC_CONNECT_ERROR:
935 SET_PIXMAP_AND_TEXT(error_pixbuf,
936 _("Connection failed"), NULL);
937 break;
938 case INC_AUTH_FAILED:
939 SET_PIXMAP_AND_TEXT(error_pixbuf, _("Auth failed"),
940 NULL);
941 break;
942 case INC_LOCKED:
943 SET_PIXMAP_AND_TEXT(error_pixbuf, _("Locked"), NULL);
944 break;
945 case INC_ERROR:
946 case INC_NO_SPACE:
947 case INC_IO_ERROR:
948 case INC_SOCKET_ERROR:
949 case INC_EOF:
950 SET_PIXMAP_AND_TEXT(error_pixbuf, _("Error"), NULL);
951 break;
952 case INC_TIMEOUT:
953 SET_PIXMAP_AND_TEXT(error_pixbuf, _("Timeout"), NULL);
954 break;
955 case INC_CANCEL:
956 SET_PIXMAP_AND_TEXT(ok_pixbuf, _("Cancelled"), NULL);
957 break;
958 default:
959 break;
960 }
961
962 if (inc_dialog->result)
963 inc_dialog->result->count_list = inc_add_message_count(inc_dialog->result->count_list, pop3_session->ac_prefs, session->new_msgs);
964 new_msgs += session->new_msgs;
965
966 if (!prefs_common.scan_all_after_inc) {
967 inc_update_folder_foreach(session->folder_table);
968 }
969
970 if (pop3_session->error_val == PS_AUTHFAIL &&
971 pop3_session->ac_prefs->tmp_pass) {
972 g_free(pop3_session->ac_prefs->tmp_pass);
973 pop3_session->ac_prefs->tmp_pass = NULL;
974 }
975
976 pop3_write_uidl_list(pop3_session);
977
978 if (inc_state != INC_SUCCESS && inc_state != INC_CANCEL) {
979 error_num++;
980 if (inc_dialog->show_dialog)
981 manage_window_focus_in
982 (inc_dialog->dialog->window,
983 NULL, NULL);
984 inc_put_error(session, inc_state,
985 pop3_session->error_msg);
986 if (inc_dialog->show_dialog)
987 manage_window_focus_out
988 (inc_dialog->dialog->window,
989 NULL, NULL);
990 if (inc_state == INC_NO_SPACE ||
991 inc_state == INC_IO_ERROR)
992 break;
993 }
994
995 inc_session_destroy(session);
996 inc_dialog->queue_list =
997 g_list_remove(inc_dialog->queue_list, session);
998 }
999
1000#undef SET_PIXMAP_AND_TEXT
1001
1002 if (new_msgs > 0)
1003 fin_msg = g_strdup_printf(_("Finished (%d new message(s))"),
1004 new_msgs);
1005 else
1006 fin_msg = g_strdup_printf(_("Finished (no new messages)"));
1007
1008 progress_dialog_set_label(inc_dialog->dialog, fin_msg);
1009
1010#if 0
1011 if (error_num && !prefs_common.no_recv_err_panel) {
1012 if (inc_dialog->show_dialog)
1013 manage_window_focus_in(inc_dialog->dialog->window,
1014 NULL, NULL);
1015 alertpanel_error(_("Some errors occurred while getting mail."));
1016 if (inc_dialog->show_dialog)
1017 manage_window_focus_out(inc_dialog->dialog->window,
1018 NULL, NULL);
1019 }
1020#endif
1021
1022 while (inc_dialog->queue_list != NULL) {
1023 session = inc_dialog->queue_list->data;
1024 inc_session_destroy(session);
1025 inc_dialog->queue_list =
1026 g_list_remove(inc_dialog->queue_list, session);
1027 }
1028
1029 if (prefs_common.close_recv_dialog || !inc_dialog->show_dialog)
1030 inc_progress_dialog_destroy(inc_dialog);
1031 else {
1032 gtk_window_set_title(GTK_WINDOW(inc_dialog->dialog->window),
1033 fin_msg);
1034 gtk_button_set_label(GTK_BUTTON(inc_dialog->dialog->cancel_btn),
1035 GTK_STOCK_CLOSE);
1036 }
1037
1038 g_free(fin_msg);
1039
1040 return new_msgs;
1041}
1042
1043static IncState inc_pop3_session_do(IncSession *session)
1044{
1045 Pop3Session *pop3_session = POP3_SESSION(session->session);
1046 IncProgressDialog *inc_dialog = (IncProgressDialog *)session->data;
1047 PrefsAccount *ac = pop3_session->ac_prefs;
1048 SocksInfo *socks_info = NULL;
1049 gchar *buf;
1050
1051 debug_print(_("getting new messages of account %s...\n"),
1052 ac->account_name);
1053
1054 if (pop3_session->auth_only)
1055 buf = g_strdup_printf(_("%s: Authenticating with POP3"),
1056 ac->recv_server);
1057 else
1058 buf = g_strdup_printf(_("%s: Retrieving new messages"),
1059 ac->recv_server);
1060 gtk_window_set_title(GTK_WINDOW(inc_dialog->dialog->window), buf);
1061 g_free(buf);
1062
1063 buf = g_strdup_printf(_("Connecting to POP3 server: %s..."),
1064 ac->recv_server);
1065 log_message("%s\n", buf);
1066 progress_dialog_set_label(inc_dialog->dialog, buf);
1067 g_free(buf);
1068
1069 session_set_timeout(SESSION(pop3_session),
1070 prefs_common.io_timeout_secs * 1000);
1071
1072 if (ac->use_socks && ac->use_socks_for_recv) {
1073 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);
1074 }
1075
1076 GTK_EVENTS_FLUSH();
1077
1078 if (session_connect_full(SESSION(pop3_session),
1079 SESSION(pop3_session)->server,
1080 SESSION(pop3_session)->port, socks_info) < 0) {
1081 log_warning(_("Can't connect to POP3 server: %s:%d\n"),
1082 SESSION(pop3_session)->server,
1083 SESSION(pop3_session)->port);
1084 session->inc_state = INC_CONNECT_ERROR;
1085 if (session_get_error(SESSION(pop3_session)) == SESSION_ERROR_LOOKUP)
1086 session->inc_state = INC_LOOKUP_ERROR;
1087 statusbar_pop_all();
1088 return session->inc_state;
1089 }
1090
1091 while (session_is_connected(SESSION(pop3_session)) &&
1092 session->inc_state != INC_CANCEL) {
1093 gtk_main_iteration();
1094 }
1095 log_window_flush();
1096
1097 debug_print("inc_state: %d\n", session->inc_state);
1098 debug_print("pop3_session.error_val: %d\n", pop3_session->error_val);
1099 debug_print("pop3_session.error_msg: %s\n", pop3_session->error_msg ? pop3_session->error_msg : "(empty)");
1100
1101 if (session->inc_state == INC_SUCCESS) {
1102 switch (pop3_session->error_val) {
1103 case PS_SUCCESS:
1104 switch (SESSION(pop3_session)->state) {
1105 case SESSION_ERROR:
1106 if (pop3_session->state == POP3_READY)
1107 session->inc_state = INC_CONNECT_ERROR;
1108 else
1109 session->inc_state = INC_ERROR;
1110 if (session_get_error(SESSION(pop3_session)) == SESSION_ERROR_LOOKUP)
1111 session->inc_state = INC_LOOKUP_ERROR;
1112 break;
1113 case SESSION_EOF:
1114 session->inc_state = INC_EOF;
1115 break;
1116 case SESSION_TIMEOUT:
1117 session->inc_state = INC_TIMEOUT;
1118 break;
1119 default:
1120 session->inc_state = INC_SUCCESS;
1121 break;
1122 }
1123 break;
1124 case PS_AUTHFAIL:
1125 session->inc_state = INC_AUTH_FAILED;
1126 break;
1127 case PS_IOERR:
1128 session->inc_state = INC_IO_ERROR;
1129 break;
1130 case PS_SOCKET:
1131 session->inc_state = INC_SOCKET_ERROR;
1132 break;
1133 case PS_LOCKBUSY:
1134 session->inc_state = INC_LOCKED;
1135 break;
1136 default:
1137 session->inc_state = INC_ERROR;
1138 break;
1139 }
1140 }
1141
1142 session_disconnect(SESSION(pop3_session));
1143 statusbar_pop_all();
1144
1145 return session->inc_state;
1146}
1147
1148static void inc_progress_dialog_update(IncProgressDialog *inc_dialog,
1149 IncSession *inc_session)
1150{
1151 inc_progress_dialog_set_label(inc_dialog, inc_session);
1152 inc_progress_dialog_set_progress(inc_dialog, inc_session);
1153}
1154
1155static void inc_progress_dialog_set_label(IncProgressDialog *inc_dialog,
1156 IncSession *inc_session)
1157{
1158 ProgressDialog *dialog = inc_dialog->dialog;
1159 Pop3Session *session;
1160
1161 g_return_if_fail(inc_session != NULL);
1162
1163 session = POP3_SESSION(inc_session->session);
1164
1165 switch (session->state) {
1166 case POP3_GREETING:
1167 break;
1168 case POP3_GETAUTH_USER:
1169 case POP3_GETAUTH_PASS:
1170 case POP3_GETAUTH_APOP:
1171 progress_dialog_set_label(dialog, _("Authenticating..."));
1172 statusbar_print_all(_("Retrieving messages from %s..."),
1173 SESSION(session)->server);
1174 break;
1175 case POP3_GETRANGE_STAT:
1176 progress_dialog_set_label
1177 (dialog, _("Getting the number of new messages (STAT)..."));
1178 break;
1179 case POP3_GETRANGE_LAST:
1180 progress_dialog_set_label
1181 (dialog, _("Getting the number of new messages (LAST)..."));
1182 break;
1183 case POP3_GETRANGE_UIDL:
1184 progress_dialog_set_label
1185 (dialog, _("Getting the number of new messages (UIDL)..."));
1186 break;
1187 case POP3_GETSIZE_LIST:
1188 progress_dialog_set_label
1189 (dialog, _("Getting the size of messages (LIST)..."));
1190 break;
1191 case POP3_RETR:
1192 case POP3_RETR_RECV:
1193 break;
1194 case POP3_DELETE:
1195#if 0
1196 if (session->msg[session->cur_msg].recv_time <
1197 session->current_time) {
1198 gchar buf[BUFFSIZE];
1199 g_snprintf(buf, sizeof(buf), _("Deleting message %d"),
1200 session->cur_msg);
1201 progress_dialog_set_label(dialog, buf);
1202 }
1203#endif
1204 break;
1205 case POP3_LOGOUT:
1206 progress_dialog_set_label(dialog, _("Quitting"));
1207 break;
1208 default:
1209 break;
1210 }
1211}
1212
1213static void inc_progress_dialog_set_progress(IncProgressDialog *inc_dialog,
1214 IncSession *inc_session)
1215{
1216 gchar buf[BUFFSIZE];
1217 Pop3Session *pop3_session = POP3_SESSION(inc_session->session);
1218 gint64 cur_total;
1219 gint64 total;
1220 gint cur_num;
1221 gint total_num_to_recv;
1222
1223 if (!pop3_session->new_msg_exist) return;
1224
1225 if (inc_session->retr_count == 0) {
1226 cur_num = total_num_to_recv = 0;
1227 cur_total = total = 0;
1228 } else {
1229 cur_num = pop3_session->cur_msg - inc_session->start_num + 1;
1230 total_num_to_recv = pop3_session->count - inc_session->start_num + 1;
1231 cur_total = inc_session->cur_total_bytes - inc_session->start_recv_bytes;
1232 total = pop3_session->total_bytes - inc_session->start_recv_bytes;
1233 }
1234
1235 if ((pop3_session->state == POP3_RETR ||
1236 pop3_session->state == POP3_RETR_RECV ||
1237 pop3_session->state == POP3_DELETE) && total_num_to_recv > 0) {
1238 gchar total_size_str[16];
1239
1240 to_human_readable_buf(total_size_str, sizeof(total_size_str),
1241 total);
1242 g_snprintf(buf, sizeof(buf),
1243 _("Retrieving message (%d / %d) (%s / %s)"),
1244 cur_num, total_num_to_recv,
1245 to_human_readable(cur_total), total_size_str);
1246 progress_dialog_set_label(inc_dialog->dialog, buf);
1247 }
1248
1249 if (total > 0)
1250 progress_dialog_set_percentage
1251 (inc_dialog->dialog, (gfloat)cur_total / (gfloat)total);
1252
1253 gtk_progress_set_show_text
1254 (GTK_PROGRESS(inc_dialog->mainwin->progressbar), TRUE);
1255 if (total_num_to_recv > 0)
1256 g_snprintf(buf, sizeof(buf), "%d / %d", cur_num, total_num_to_recv);
1257 else
1258 buf[0] = '\0';
1259 gtk_progress_set_format_string
1260 (GTK_PROGRESS(inc_dialog->mainwin->progressbar), buf);
1261 if (total > 0)
1262 gtk_progress_bar_update
1263 (GTK_PROGRESS_BAR(inc_dialog->mainwin->progressbar),
1264 (gfloat)cur_total / (gfloat)total);
1265
1266 if (pop3_session->cur_total_num > 0) {
1267 g_snprintf(buf, sizeof(buf),
1268 _("%d message(s) (%s) received"),
1269 pop3_session->cur_total_num,
1270 to_human_readable(pop3_session->cur_total_recv_bytes));
1271 progress_dialog_set_row_progress(inc_dialog->dialog,
1272 inc_dialog->cur_row, buf);
1273 }
1274}
1275
1276static gboolean hash_remove_func(gpointer key, gpointer value, gpointer data)
1277{
1278 return TRUE;
1279}
1280
1281static void inc_update_folderview(IncProgressDialog *inc_dialog,
1282 IncSession *inc_session)
1283{
1284 MainWindow *mainwin;
1285
1286 if (g_hash_table_size(inc_session->tmp_folder_table) > 0) {
1287 folderview_update_item_foreach(inc_session->tmp_folder_table,
1288 FALSE);
1289 g_hash_table_foreach_remove(inc_session->tmp_folder_table,
1290 hash_remove_func, NULL);
1291 }
1292
1293 mainwin = main_window_get();
1294 summary_show_queued_msgs(mainwin->summaryview);
1295}
1296
1297static void inc_progress_dialog_update_periodic(IncProgressDialog *inc_dialog,
1298 IncSession *inc_session)
1299{
1300 GTimeVal tv_cur;
1301 GTimeVal tv_result;
1302 gint msec;
1303
1304 g_get_current_time(&tv_cur);
1305
1306 tv_result.tv_sec = tv_cur.tv_sec - inc_dialog->progress_tv.tv_sec;
1307 tv_result.tv_usec = tv_cur.tv_usec - inc_dialog->progress_tv.tv_usec;
1308 if (tv_result.tv_usec < 0) {
1309 tv_result.tv_sec--;
1310 tv_result.tv_usec += G_USEC_PER_SEC;
1311 }
1312
1313 msec = tv_result.tv_sec * 1000 + tv_result.tv_usec / 1000;
1314 if (msec > PROGRESS_UPDATE_INTERVAL) {
1315 inc_progress_dialog_update(inc_dialog, inc_session);
1316 inc_dialog->progress_tv.tv_sec = tv_cur.tv_sec;
1317 inc_dialog->progress_tv.tv_usec = tv_cur.tv_usec;
1318 }
1319}
1320
1321static void inc_update_folderview_periodic(IncProgressDialog *inc_dialog,
1322 IncSession *inc_session)
1323{
1324 GTimeVal tv_cur;
1325 GTimeVal tv_result;
1326 gint msec;
1327
1328 g_get_current_time(&tv_cur);
1329
1330 tv_result.tv_sec = tv_cur.tv_sec - inc_dialog->folder_tv.tv_sec;
1331 tv_result.tv_usec = tv_cur.tv_usec - inc_dialog->folder_tv.tv_usec;
1332 if (tv_result.tv_usec < 0) {
1333 tv_result.tv_sec--;
1334 tv_result.tv_usec += G_USEC_PER_SEC;
1335 }
1336
1337 msec = tv_result.tv_sec * 1000 + tv_result.tv_usec / 1000;
1338 if (msec > FOLDER_UPDATE_INTERVAL) {
1339 inc_update_folderview(inc_dialog, inc_session);
1340 inc_dialog->folder_tv.tv_sec = tv_cur.tv_sec;
1341 inc_dialog->folder_tv.tv_usec = tv_cur.tv_usec;
1342 }
1343}
1344
1345static gint inc_recv_data_progressive(Session *session, guint cur_len,
1346 guint total_len, gpointer data)
1347{
1348 IncSession *inc_session = (IncSession *)data;
1349 Pop3Session *pop3_session = POP3_SESSION(session);
1350 IncProgressDialog *inc_dialog;
1351 gint64 cur_total;
1352
1353 g_return_val_if_fail(inc_session != NULL, -1);
1354
1355 if (pop3_session->state != POP3_RETR &&
1356 pop3_session->state != POP3_RETR_RECV &&
1357 pop3_session->state != POP3_DELETE &&
1358 pop3_session->state != POP3_LOGOUT) return 0;
1359
1360 if (!pop3_session->new_msg_exist) return 0;
1361
1362 gdk_threads_enter();
1363
1364 cur_total = pop3_session->cur_total_bytes + cur_len;
1365 if (cur_total > pop3_session->total_bytes)
1366 cur_total = pop3_session->total_bytes;
1367 inc_session->cur_total_bytes = cur_total;
1368
1369 inc_dialog = (IncProgressDialog *)inc_session->data;
1370 inc_progress_dialog_update_periodic(inc_dialog, inc_session);
1371 inc_update_folderview_periodic(inc_dialog, inc_session);
1372
1373 gdk_threads_leave();
1374 return 0;
1375}
1376
1377static gint inc_recv_data_finished(Session *session, guint len, gpointer data)
1378{
1379 IncSession *inc_session = (IncSession *)data;
1380 IncProgressDialog *inc_dialog;
1381
1382 g_return_val_if_fail(inc_session != NULL, -1);
1383
1384 inc_dialog = (IncProgressDialog *)inc_session->data;
1385
1386 inc_recv_data_progressive(session, 0, 0, inc_session);
1387
1388 gdk_threads_enter();
1389
1390 if (POP3_SESSION(session)->state == POP3_LOGOUT) {
1391 inc_progress_dialog_update(inc_dialog, inc_session);
1392 inc_update_folderview(inc_dialog, inc_session);
1393 }
1394
1395 gdk_threads_leave();
1396 return 0;
1397}
1398
1399static gint inc_recv_message(Session *session, const gchar *msg, gpointer data)
1400{
1401 IncSession *inc_session = (IncSession *)data;
1402 IncProgressDialog *inc_dialog;
1403 Pop3Session *pop3_session = POP3_SESSION(session);
1404
1405 g_return_val_if_fail(inc_session != NULL, -1);
1406
1407 inc_dialog = (IncProgressDialog *)inc_session->data;
1408
1409 switch (POP3_SESSION(session)->state) {
1410 case POP3_GETAUTH_USER:
1411 case POP3_GETAUTH_PASS:
1412 case POP3_GETAUTH_APOP:
1413 case POP3_GETRANGE_STAT:
1414 case POP3_GETRANGE_LAST:
1415 case POP3_GETRANGE_UIDL:
1416 case POP3_GETSIZE_LIST:
1417 gdk_threads_enter();
1418 inc_progress_dialog_update(inc_dialog, inc_session);
1419 gdk_threads_leave();
1420 break;
1421 case POP3_RETR_RECV:
1422 if (inc_session->retr_count == 0) {
1423 inc_session->start_num = pop3_session->cur_msg;
1424 inc_session->start_recv_bytes = pop3_session->cur_total_bytes;
1425 inc_session->cur_total_bytes = pop3_session->cur_total_bytes;
1426#if 0
1427 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);
1428 g_print("pop: total_bytes = %lld cur_total_bytes = %lld\n", pop3_session->total_bytes, pop3_session->cur_total_bytes);
1429 g_print("pop: count = %d cur_msg = %d\n", pop3_session->count, pop3_session->cur_msg);
1430#endif
1431 inc_session->retr_count++;
1432 gdk_threads_enter();
1433 inc_progress_dialog_update(inc_dialog, inc_session);
1434 gdk_threads_leave();
1435 } else {
1436 inc_session->retr_count++;
1437 inc_recv_data_progressive(session, 0, 0, inc_session);
1438 }
1439 break;
1440 case POP3_LOGOUT:
1441 gdk_threads_enter();
1442 inc_progress_dialog_update(inc_dialog, inc_session);
1443 inc_update_folderview(inc_dialog, inc_session);
1444 gdk_threads_leave();
1445 break;
1446 default:
1447 break;
1448 }
1449
1450 return 0;
1451}
1452
1453/**
1454 * inc_drop_message:
1455 * @session: Current Pop3Session.
1456 * @file: Received message file.
1457 *
1458 * Callback function to drop received message into local mailbox.
1459 *
1460 * Return value: DROP_OK if succeeded. DROP_ERROR if error occurred.
1461 * DROP_DONT_RECEIVE if the message should be skipped.
1462 * DROP_DELETE if the message should be deleted.
1463 **/
1464static gint inc_drop_message(Pop3Session *session, const gchar *file)
1465{
1466 FolderItem *inbox;
1467 GSList *cur;
1468 MsgInfo *msginfo;
1469 FilterInfo *fltinfo;
1470 IncSession *inc_session = (IncSession *)(SESSION(session)->data);
1471 gint val;
1472 gboolean is_junk = FALSE;
1473 gboolean is_counted = FALSE;
1474 IncProgressDialog *inc_dialog;
1475
1476 g_return_val_if_fail(inc_session != NULL, DROP_ERROR);
1477
1478 gdk_threads_enter();
1479
1480 inc_dialog = (IncProgressDialog *)inc_session->data;
1481
1482 if (session->ac_prefs->inbox) {
1483 inbox = folder_find_item_from_identifier
1484 (session->ac_prefs->inbox);
1485 if (!inbox)
1486 inbox = folder_get_default_inbox();
1487 } else
1488 inbox = folder_get_default_inbox();
1489 if (!inbox) {
1490 gdk_threads_leave();
1491 return DROP_ERROR;
1492 }
1493
1494 fltinfo = filter_info_new();
1495 fltinfo->account = session->ac_prefs;
1496 fltinfo->flags.perm_flags = MSG_NEW|MSG_UNREAD;
1497 fltinfo->flags.tmp_flags = MSG_RECEIVED;
1498
1499 msginfo = procheader_parse_file(file, fltinfo->flags, FALSE);
1500 if (!msginfo) {
1501 g_warning("inc_drop_message: procheader_parse_file failed");
1502 filter_info_free(fltinfo);
1503 gdk_threads_leave();
1504 return DROP_ERROR;
1505 }
1506 fltinfo->flags = msginfo->flags;
1507 msginfo->file_path = g_strdup(file);
1508
1509 if (prefs_common.enable_junk &&
1510 prefs_common.filter_junk_on_recv &&
1511 prefs_common.filter_junk_before &&
1512 inc_session->junk_fltlist) {
1513 filter_apply_msginfo(inc_session->junk_fltlist, msginfo,
1514 fltinfo);
1515 if (fltinfo->drop_done)
1516 is_junk = TRUE;
1517 else if (fltinfo->error == FLT_ERROR_EXEC_FAILED ||
1518 fltinfo->last_exec_exit_status >= 3) {
1519 g_warning("inc_drop_message: junk filter command returned %d",
1520 fltinfo->last_exec_exit_status);
1521 alertpanel_error
1522 (_("Execution of the junk filter command failed.\n"
1523 "Please check the junk mail control setting."));
1524 procmsg_msginfo_free(msginfo);
1525 filter_info_free(fltinfo);
1526 inc_session->inc_state = INC_ERROR;
1527 gdk_threads_leave();
1528 return DROP_ERROR;
1529 }
1530 }
1531
1532 if (!fltinfo->drop_done && session->ac_prefs->filter_on_recv)
1533 filter_apply_msginfo(prefs_common.fltlist, msginfo, fltinfo);
1534
1535 if (!fltinfo->drop_done) {
1536 if (prefs_common.enable_junk &&
1537 prefs_common.filter_junk_on_recv &&
1538 !prefs_common.filter_junk_before &&
1539 inc_session->junk_fltlist) {
1540 filter_apply_msginfo(inc_session->junk_fltlist,
1541 msginfo, fltinfo);
1542 if (fltinfo->drop_done)
1543 is_junk = TRUE;
1544 else if (fltinfo->error == FLT_ERROR_EXEC_FAILED ||
1545 fltinfo->last_exec_exit_status >= 3) {
1546 g_warning("inc_drop_message: junk filter command returned %d",
1547 fltinfo->last_exec_exit_status);
1548 alertpanel_error
1549 (_("Execution of the junk filter command failed.\n"
1550 "Please check the junk mail control setting."));
1551 procmsg_msginfo_free(msginfo);
1552 filter_info_free(fltinfo);
1553 inc_session->inc_state = INC_ERROR;
1554 gdk_threads_leave();
1555 return DROP_ERROR;
1556 }
1557 }
1558 }
1559
1560 if (!fltinfo->drop_done) {
1561 msginfo->flags = fltinfo->flags;
1562 if (folder_item_add_msg_msginfo(inbox, msginfo, FALSE) < 0) {
1563 procmsg_msginfo_free(msginfo);
1564 filter_info_free(fltinfo);
1565 gdk_threads_leave();
1566 return DROP_ERROR;
1567 }
1568 fltinfo->dest_list = g_slist_append(fltinfo->dest_list, inbox);
1569 }
1570
1571 for (cur = fltinfo->dest_list; cur != NULL; cur = cur->next) {
1572 FolderItem *drop_folder = (FolderItem *)cur->data;
1573
1574 val = GPOINTER_TO_INT(g_hash_table_lookup
1575 (inc_session->folder_table, drop_folder));
1576 if (val == 0)
1577 g_hash_table_insert(inc_session->folder_table,
1578 drop_folder, GINT_TO_POINTER(1));
1579 g_hash_table_insert(inc_session->tmp_folder_table, drop_folder,
1580 GINT_TO_POINTER(1));
1581
1582 if (drop_folder->stype != F_TRASH &&
1583 drop_folder->stype != F_JUNK)
1584 is_counted = TRUE;
1585 }
1586
1587 if (fltinfo->actions[FLT_ACTION_NOT_RECEIVE] == TRUE)
1588 val = DROP_DONT_RECEIVE;
1589 else if (fltinfo->actions[FLT_ACTION_DELETE] == TRUE)
1590 val = DROP_DELETE;
1591 else {
1592 val = DROP_OK;
1593 if (!is_junk && is_counted &&
1594 fltinfo->actions[FLT_ACTION_MARK_READ] == FALSE) {
1595 inc_session->new_msgs++;
1596
1597 if (inc_dialog->result &&
1598 msginfo->subject && msginfo->fromname &&
1599 g_slist_length(inc_dialog->result->msg_summaries) < 5) {
1600 IncMsgSummary *summary;
1601 summary = g_new(IncMsgSummary, 1);
1602 summary->subject = g_strdup(msginfo->subject);
1603 summary->from = g_strdup(msginfo->fromname);
1604 inc_dialog->result->msg_summaries = g_slist_append(inc_dialog->result->msg_summaries, summary);
1605 }
1606 }
1607 }
1608
1609 procmsg_msginfo_free(msginfo);
1610 filter_info_free(fltinfo);
1611
1612 gdk_threads_leave();
1613 return val;
1614}
1615
1616static void inc_put_error(IncSession *session, IncState istate, const gchar *pop3_msg)
1617{
1618 gchar *log_msg = NULL;
1619 gchar *err_msg = NULL;
1620 gboolean fatal_error = FALSE;
1621
1622 switch (istate) {
1623 case INC_LOOKUP_ERROR:
1624 log_msg = _("Server not found.");
1625 if (prefs_common.no_recv_err_panel)
1626 break;
1627 err_msg = g_strdup_printf
1628 (_("Server %s not found."), session->session->server);
1629 break;
1630 case INC_CONNECT_ERROR:
1631 log_msg = _("Connection failed.");
1632 if (prefs_common.no_recv_err_panel)
1633 break;
1634 err_msg = g_strdup_printf
1635 (_("Connection to %s:%d failed."),
1636 session->session->server, session->session->port);
1637 break;
1638 case INC_ERROR:
1639 log_msg = _("Error occurred while processing mail.");
1640 if (prefs_common.no_recv_err_panel)
1641 break;
1642 if (pop3_msg)
1643 err_msg = g_strdup_printf
1644 (_("Error occurred while processing mail:\n%s"),
1645 pop3_msg);
1646 else
1647 err_msg = g_strdup(log_msg);
1648 break;
1649 case INC_NO_SPACE:
1650 log_msg = _("No disk space left.");
1651 err_msg = g_strdup(log_msg);
1652 fatal_error = TRUE;
1653 break;
1654 case INC_IO_ERROR:
1655 log_msg = _("Can't write file.");
1656 err_msg = g_strdup(log_msg);
1657 fatal_error = TRUE;
1658 break;
1659 case INC_SOCKET_ERROR:
1660 log_msg = _("Socket error.");
1661 if (prefs_common.no_recv_err_panel)
1662 break;
1663 err_msg = g_strdup(log_msg);
1664 break;
1665 case INC_EOF:
1666 log_msg = _("Connection closed by the remote host.");
1667 if (prefs_common.no_recv_err_panel)
1668 break;
1669 err_msg = g_strdup(log_msg);
1670 break;
1671 case INC_LOCKED:
1672 log_msg = _("Mailbox is locked.");
1673 if (prefs_common.no_recv_err_panel)
1674 break;
1675 if (pop3_msg)
1676 err_msg = g_strdup_printf(_("Mailbox is locked:\n%s"),
1677 pop3_msg);
1678 else
1679 err_msg = g_strdup(log_msg);
1680 break;
1681 case INC_AUTH_FAILED:
1682 log_msg = _("Authentication failed.");
1683 if (prefs_common.no_recv_err_panel)
1684 break;
1685 if (pop3_msg)
1686 err_msg = g_strdup_printf
1687 (_("Authentication failed:\n%s"), pop3_msg);
1688 else
1689 err_msg = g_strdup(log_msg);
1690 break;
1691 case INC_TIMEOUT:
1692 log_msg = _("Session timed out.");
1693 if (prefs_common.no_recv_err_panel)
1694 break;
1695 err_msg = g_strdup(log_msg);
1696 break;
1697 default:
1698 break;
1699 }
1700
1701 if (log_msg) {
1702 if (fatal_error)
1703 log_error("%s\n", log_msg);
1704 else
1705 log_warning("%s\n", log_msg);
1706 }
1707 if (err_msg) {
1708 alertpanel_error("%s", err_msg);
1709 g_free(err_msg);
1710 }
1711}
1712
1713static void inc_cancel(IncProgressDialog *dialog, gboolean cancel_all)
1714{
1715 IncSession *session;
1716 GList *list;
1717
1718 g_return_if_fail(dialog != NULL);
1719
1720 if (dialog->queue_list == NULL) {
1721 inc_progress_dialog_destroy(dialog);
1722 return;
1723 }
1724
1725 for (list = dialog->queue_list; list != NULL; list = list->next) {
1726 session = list->data;
1727 session->inc_state = INC_CANCEL;
1728 session_disconnect(session->session);
1729 if (!cancel_all)
1730 break;
1731 }
1732
1733 log_message(_("Incorporation cancelled\n"));
1734}
1735
1736gboolean inc_is_active(void)
1737{
1738 GList *cur;
1739
1740 if (inc_is_running)
1741 return TRUE;
1742
1743 if (inc_dialog_list == NULL)
1744 return FALSE;
1745
1746 for (cur = inc_dialog_list; cur != NULL; cur = cur->next) {
1747 IncProgressDialog *dialog = cur->data;
1748 if (dialog->queue_list)
1749 return TRUE;
1750 }
1751
1752 return FALSE;
1753}
1754
1755void inc_block_notify(gboolean block)
1756{
1757 if (!block)
1758 block_notify = FALSE;
1759 else if (inc_is_active())
1760 block_notify = TRUE;
1761}
1762
1763void inc_cancel_all(void)
1764{
1765 GList *cur;
1766
1767 for (cur = inc_dialog_list; cur != NULL; cur = cur->next)
1768 inc_cancel((IncProgressDialog *)cur->data, TRUE);
1769}
1770
1771static void inc_cancel_cb(GtkWidget *widget, gpointer data)
1772{
1773 inc_cancel((IncProgressDialog *)data, FALSE);
1774}
1775
1776static void inc_cancel_all_cb(GtkWidget *widget, gpointer data)
1777{
1778 inc_cancel((IncProgressDialog *)data, TRUE);
1779}
1780
1781static gint inc_dialog_delete_cb(GtkWidget *widget, GdkEventAny *event,
1782 gpointer data)
1783{
1784 IncProgressDialog *dialog = (IncProgressDialog *)data;
1785
1786 if (dialog->queue_list == NULL)
1787 inc_progress_dialog_destroy(dialog);
1788 else
1789 inc_cancel(dialog, TRUE);
1790
1791 return TRUE;
1792}
1793
1794static gint inc_spool(void)
1795{
1796 gchar *spool_path;
1797 gchar *mbox;
1798 gint msgs;
1799
1800 spool_path = prefs_common.spool_path
1801 ? prefs_common.spool_path : DEFAULT_SPOOL_PATH;
1802 if (is_file_exist(spool_path))
1803 mbox = g_strdup(spool_path);
1804 else if (is_dir_exist(spool_path))
1805 mbox = g_strconcat(spool_path, G_DIR_SEPARATOR_S,
1806 g_get_user_name(), NULL);
1807 else {
1808 debug_print("%s: local mailbox not found.\n", spool_path);
1809 return -1;
1810 }
1811
1812 msgs = get_spool(folder_get_default_inbox(), mbox);
1813 g_free(mbox);
1814
1815 return msgs;
1816}
1817
1818static gint get_spool(FolderItem *dest, const gchar *mbox)
1819{
1820 gint msgs, size;
1821 gint lockfd;
1822 LockType locktype = LOCK_FLOCK;
1823 gchar tmp_mbox[MAXPATHLEN + 1];
1824 GHashTable *folder_table = NULL;
1825
1826 g_return_val_if_fail(dest != NULL, -1);
1827 g_return_val_if_fail(mbox != NULL, -1);
1828
1829 if (!is_file_exist(mbox) || (size = get_file_size(mbox)) == 0) {
1830 debug_print("%s: no messages in local mailbox.\n", mbox);
1831 return 0;
1832 } else if (size < 0)
1833 return -1;
1834
1835 if ((lockfd = lock_mbox(mbox, locktype)) < 0) {
1836 locktype = LOCK_FILE;
1837 if ((lockfd = lock_mbox(mbox, locktype)) < 0)
1838 return -1;
1839 }
1840
1841 g_snprintf(tmp_mbox, sizeof(tmp_mbox), "%s%ctmpmbox.%p",
1842 get_tmp_dir(), G_DIR_SEPARATOR, mbox);
1843
1844 if (copy_mbox(mbox, tmp_mbox) < 0) {
1845 unlock_mbox(mbox, lockfd, locktype);
1846 return -1;
1847 }
1848
1849 debug_print(_("Getting new messages from %s into %s...\n"),
1850 mbox, dest->path);
1851
1852 folder_table = g_hash_table_new(NULL, NULL);
1853
1854 msgs = proc_mbox_full(dest, tmp_mbox, folder_table,
1855 prefs_common.filter_on_inc,
1856 prefs_common.enable_junk &&
1857 prefs_common.filter_junk_on_recv);
1858
1859 g_unlink(tmp_mbox);
1860 if (msgs >= 0) empty_mbox(mbox);
1861 unlock_mbox(mbox, lockfd, locktype);
1862
1863 if (!prefs_common.scan_all_after_inc) {
1864 inc_update_folder_foreach(folder_table);
1865 }
1866
1867 g_hash_table_destroy(folder_table);
1868
1869 return msgs;
1870}
1871
1872void inc_lock(void)
1873{
1874 inc_lock_count++;
1875}
1876
1877void inc_unlock(void)
1878{
1879 if (inc_lock_count > 0)
1880 inc_lock_count--;
1881}
1882
1883static guint autocheck_timer = 0;
1884static gpointer autocheck_data = NULL;
1885
1886void inc_autocheck_timer_init(MainWindow *mainwin)
1887{
1888 autocheck_data = mainwin;
1889 inc_autocheck_timer_set();
1890}
1891
1892static void inc_autocheck_timer_set_interval(guint interval)
1893{
1894 inc_autocheck_timer_remove();
1895
1896 if (prefs_common.autochk_newmail && autocheck_data) {
1897 autocheck_timer = g_timeout_add_full
1898 (G_PRIORITY_LOW, interval, inc_autocheck_func,
1899 autocheck_data, NULL);
1900 debug_print("added timer = %d\n", autocheck_timer);
1901 }
1902}
1903
1904void inc_autocheck_timer_set(void)
1905{
1906 inc_autocheck_timer_set_interval(prefs_common.autochk_itv * 60000);
1907}
1908
1909void inc_autocheck_timer_remove(void)
1910{
1911 if (autocheck_timer) {
1912 debug_print("removed timer = %d\n", autocheck_timer);
1913 g_source_remove(autocheck_timer);
1914 autocheck_timer = 0;
1915 }
1916}
1917
1918static gint inc_autocheck_func(gpointer data)
1919{
1920 MainWindow *mainwin = (MainWindow *)data;
1921
1922 gdk_threads_enter();
1923
1924 if (inc_lock_count) {
1925 debug_print("autocheck is locked.\n");
1926 inc_autocheck_timer_set_interval(1000);
1927 gdk_threads_leave();
1928 return FALSE;
1929 }
1930
1931 inc_all_account_mail(mainwin, TRUE);
1932
1933 gdk_threads_leave();
1934
1935 return FALSE;
1936}