2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2001 Hiroyuki Yamamoto
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.
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.
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.
27 #include <gtk/gtkmain.h>
28 #include <gtk/gtkwindow.h>
29 #include <gtk/gtksignal.h>
33 #include <sys/types.h>
42 #include "mainwindow.h"
43 #include "folderview.h"
44 #include "summaryview.h"
45 #include "prefs_common.h"
46 #include "prefs_account.h"
55 #include "statusbar.h"
56 #include "manage_window.h"
57 #include "progressdialog.h"
58 #include "inputdialog.h"
59 #include "alertpanel.h"
61 #include "automaton.h"
63 #include "filtering.h"
65 #include "pixmaps/continue.xpm"
66 #include "pixmaps/complete.xpm"
67 #include "pixmaps/error.xpm"
69 GdkPixmap
*currentxpm
;
70 GdkBitmap
*currentxpmmask
;
72 GdkBitmap
*errorxpmmask
;
76 #define MSGBUFSIZE 8192
78 static void inc_finished (MainWindow
*mainwin
,
79 gboolean new_messages
);
80 static gint
inc_account_mail (PrefsAccount
*account
,
83 static IncProgressDialog
*inc_progress_dialog_create (void);
84 static void inc_progress_dialog_destroy (IncProgressDialog
*inc_dialog
);
86 static IncSession
*inc_session_new (PrefsAccount
*account
);
87 static void inc_session_destroy (IncSession
*session
);
88 static Pop3State
*inc_pop3_state_new (PrefsAccount
*account
);
89 static void inc_pop3_state_destroy (Pop3State
*state
);
90 static gint
inc_start (IncProgressDialog
*inc_dialog
);
91 static IncState
inc_pop3_session_do (IncSession
*session
);
92 static gint
pop3_automaton_terminate (SockInfo
*source
,
95 static GHashTable
*inc_get_uidl_table (PrefsAccount
*ac_prefs
);
96 static void inc_write_uidl_list (Pop3State
*state
);
99 static gint
connection_check_cb (Automaton
*atm
);
102 static void inc_pop3_recv_func (SockInfo
*sock
,
107 static void inc_put_error (IncState istate
);
109 static void inc_cancel (GtkWidget
*widget
,
112 static gint
inc_spool (void);
113 static gint
get_spool (FolderItem
*dest
,
116 static void inc_all_spool(void);
118 static gint
inc_autocheck_func (gpointer data
);
122 * @mainwin: Main window.
123 * @new_messages: TRUE if some messages have been received.
125 * Update the folder view and the summary view after receiving
126 * messages. If @new_messages is FALSE, this function avoids unneeded
129 static void inc_finished(MainWindow
*mainwin
, gboolean new_messages
)
133 if (prefs_common
.scan_all_after_inc
)
134 folderview_update_all_node();
135 /* XXX: major problems right here. if we change marks after
136 * incorporation of mail, folderview_select() rewrites it
137 * right under our nose. folderview_select() eventually
138 * calls summary_show(), which rewrites the cache twice:
139 * one for the previously selected FolderItem*, and one
140 * for the newly selected FolderItem*
142 * since filtering also allows changing mark files,
143 * i've solved this by using a global variable (in
144 * SummmaryView*). a better solution is to use the folder
145 * hash table, and see whether the newly and currently
146 * selected FolderItem* where updated by the filtering. */
148 mainwin
->summaryview
->filtering_happened
= TRUE
;
150 /* XXX: filtering_happened is reset by summary_show() */
152 if (!new_messages
&& !prefs_common
.scan_all_after_inc
) return;
154 if (prefs_common
.open_inbox_on_inc
) {
155 item
= cur_account
&& cur_account
->inbox
156 ? folder_find_item_from_path(cur_account
->inbox
)
157 : folder_get_default_inbox();
158 folderview_unselect(mainwin
->folderview
);
159 folderview_select(mainwin
->folderview
, item
);
161 item
= mainwin
->summaryview
->folder_item
;
162 folderview_unselect(mainwin
->folderview
);
163 folderview_select(mainwin
->folderview
, item
);
167 void inc_mail(MainWindow
*mainwin
)
171 inc_autocheck_timer_remove();
172 summary_write_cache(mainwin
->summaryview
);
173 main_window_lock(mainwin
);
175 if (prefs_common
.use_extinc
&& prefs_common
.extinc_path
) {
178 /* external incorporating program */
179 if ((pid
= fork()) < 0) {
181 main_window_unlock(mainwin
);
182 inc_autocheck_timer_set();
187 execlp(prefs_common
.extinc_path
,
188 g_basename(prefs_common
.extinc_path
),
191 /* this will be called when failed */
196 /* wait until child process is terminated */
197 waitpid(pid
, NULL
, 0);
199 if (prefs_common
.inc_local
)
200 new_msgs
= inc_spool();
202 if (prefs_common
.inc_local
)
203 new_msgs
= inc_spool();
205 new_msgs
+= inc_account_mail(cur_account
, mainwin
);
208 inc_finished(mainwin
, new_msgs
> 0);
209 main_window_unlock(mainwin
);
210 inc_autocheck_timer_set();
213 static gint
inc_account_mail(PrefsAccount
*account
, MainWindow
*mainwin
)
215 IncProgressDialog
*inc_dialog
;
219 session
= inc_session_new(account
);
220 if (!session
) return 0;
222 inc_dialog
= inc_progress_dialog_create();
223 inc_dialog
->queue_list
= g_list_append(inc_dialog
->queue_list
, session
);
224 inc_dialog
->mainwin
= mainwin
;
225 session
->data
= inc_dialog
;
228 text
[1] = account
->account_name
;
229 text
[2] = _("Standby");
230 gtk_clist_append(GTK_CLIST(inc_dialog
->dialog
->clist
), text
);
232 return inc_start(inc_dialog
);
235 void inc_all_account_mail(MainWindow
*mainwin
)
237 GList
*list
, *queue_list
= NULL
;
238 IncProgressDialog
*inc_dialog
;
241 inc_autocheck_timer_remove();
242 summary_write_cache(mainwin
->summaryview
);
243 main_window_lock(mainwin
);
245 if (prefs_common
.inc_local
)
246 new_msgs
= inc_spool();
248 list
= account_get_list();
250 inc_finished(mainwin
, new_msgs
> 0);
251 main_window_unlock(mainwin
);
252 inc_autocheck_timer_set();
256 for (; list
!= NULL
; list
= list
->next
) {
258 PrefsAccount
*account
= list
->data
;
260 if (account
->recv_at_getall
) {
261 session
= inc_session_new(account
);
263 queue_list
= g_list_append(queue_list
, session
);
268 inc_finished(mainwin
, new_msgs
> 0);
269 main_window_unlock(mainwin
);
270 inc_autocheck_timer_set();
274 inc_dialog
= inc_progress_dialog_create();
275 inc_dialog
->queue_list
= queue_list
;
276 inc_dialog
->mainwin
= mainwin
;
277 for (list
= queue_list
; list
!= NULL
; list
= list
->next
) {
278 IncSession
*session
= list
->data
;
281 session
->data
= inc_dialog
;
284 text
[1] = session
->pop3_state
->ac_prefs
->account_name
;
285 text
[2] = _("Standby");
286 gtk_clist_append(GTK_CLIST(inc_dialog
->dialog
->clist
), text
);
289 new_msgs
+= inc_start(inc_dialog
);
291 inc_finished(mainwin
, new_msgs
> 0);
292 main_window_unlock(mainwin
);
293 inc_autocheck_timer_set();
296 static IncProgressDialog
*inc_progress_dialog_create(void)
298 IncProgressDialog
*dialog
;
299 ProgressDialog
*progress
;
301 dialog
= g_new0(IncProgressDialog
, 1);
303 progress
= progress_dialog_create();
304 gtk_window_set_title(GTK_WINDOW(progress
->window
),
305 _("Retrieving new messages"));
306 gtk_signal_connect(GTK_OBJECT(progress
->cancel_btn
), "clicked",
307 GTK_SIGNAL_FUNC(inc_cancel
), dialog
);
308 gtk_signal_connect(GTK_OBJECT(progress
->window
), "delete_event",
309 GTK_SIGNAL_FUNC(gtk_true
), NULL
);
311 progress_dialog_set_value(progress
, 0.0);
313 PIXMAP_CREATE(progress
->clist
, okxpm
, okxpmmask
, complete_xpm
);
314 PIXMAP_CREATE(progress
->clist
,
315 currentxpm
, currentxpmmask
, continue_xpm
);
316 PIXMAP_CREATE(progress
->clist
, errorxpm
, errorxpmmask
, error_xpm
);
318 if (prefs_common
.recv_dialog_mode
== RECV_DIALOG_ALWAYS
||
319 (prefs_common
.recv_dialog_mode
== RECV_DIALOG_ACTIVE
&&
320 manage_window_get_focus_window())) {
321 dialog
->show_dialog
= TRUE
;
322 gtk_widget_show_now(progress
->window
);
325 dialog
->dialog
= progress
;
326 dialog
->queue_list
= NULL
;
331 static void inc_progress_dialog_clear(IncProgressDialog
*inc_dialog
)
333 progress_dialog_set_value(inc_dialog
->dialog
, 0.0);
334 progress_dialog_set_label(inc_dialog
->dialog
, "");
337 static void inc_progress_dialog_destroy(IncProgressDialog
*inc_dialog
)
339 g_return_if_fail(inc_dialog
!= NULL
);
341 progress_dialog_destroy(inc_dialog
->dialog
);
346 static IncSession
*inc_session_new(PrefsAccount
*account
)
350 g_return_val_if_fail(account
!= NULL
, NULL
);
352 if (account
->protocol
!= A_POP3
&& account
->protocol
!= A_APOP
)
354 if (!account
->recv_server
|| !account
->userid
)
357 session
= g_new0(IncSession
, 1);
358 session
->pop3_state
= inc_pop3_state_new(account
);
359 session
->pop3_state
->session
= session
;
364 static void inc_session_destroy(IncSession
*session
)
366 g_return_if_fail(session
!= NULL
);
368 inc_pop3_state_destroy(session
->pop3_state
);
372 static Pop3State
*inc_pop3_state_new(PrefsAccount
*account
)
376 state
= g_new0(Pop3State
, 1);
378 state
->ac_prefs
= account
;
379 state
->folder_table
= g_hash_table_new(NULL
, NULL
);
380 state
->id_table
= inc_get_uidl_table(account
);
381 state
->id_list
= NULL
;
382 state
->new_id_list
= NULL
;
383 state
->inc_state
= INC_SUCCESS
;
388 static void inc_pop3_state_destroy(Pop3State
*state
)
390 g_hash_table_destroy(state
->folder_table
);
391 g_free(state
->sizes
);
393 if (state
->id_table
) {
394 hash_free_strings(state
->id_table
);
395 g_hash_table_destroy(state
->id_table
);
397 slist_free_strings(state
->id_list
);
398 slist_free_strings(state
->new_id_list
);
399 g_slist_free(state
->id_list
);
400 g_slist_free(state
->new_id_list
);
402 g_free(state
->greeting
);
405 g_free(state
->prev_folder
);
410 static gint
inc_start(IncProgressDialog
*inc_dialog
)
413 GtkCList
*clist
= GTK_CLIST(inc_dialog
->dialog
->clist
);
414 Pop3State
*pop3_state
;
420 while (inc_dialog
->queue_list
!= NULL
) {
421 session
= inc_dialog
->queue_list
->data
;
422 pop3_state
= session
->pop3_state
;
424 inc_progress_dialog_clear(inc_dialog
);
426 pop3_state
->user
= g_strdup(pop3_state
->ac_prefs
->userid
);
427 if (pop3_state
->ac_prefs
->passwd
)
429 g_strdup(pop3_state
->ac_prefs
->passwd
);
430 else if (pop3_state
->ac_prefs
->tmp_pass
)
432 g_strdup(pop3_state
->ac_prefs
->tmp_pass
);
437 message
= g_strdup_printf
438 (_("Input password for %s on %s:"),
440 pop3_state
->ac_prefs
->recv_server
);
442 pass
= input_dialog_with_invisible(_("Input password"),
445 if (inc_dialog
->show_dialog
)
446 manage_window_focus_in
447 (inc_dialog
->mainwin
->window
,
450 pop3_state
->ac_prefs
->tmp_pass
= g_strdup(pass
);
451 pop3_state
->pass
= pass
;
453 inc_session_destroy(session
);
454 inc_dialog
->queue_list
= g_list_remove
455 (inc_dialog
->queue_list
, session
);
460 gtk_clist_set_pixmap(clist
, num
, 0, currentxpm
, currentxpmmask
);
461 gtk_clist_set_text(clist
, num
, 2, _("Retrieving"));
463 /* begin POP3 session */
464 inc_state
= inc_pop3_session_do(session
);
466 if (inc_state
== INC_SUCCESS
) {
467 gtk_clist_set_pixmap(clist
, num
, 0, okxpm
, okxpmmask
);
468 gtk_clist_set_text(clist
, num
, 2, _("Done"));
469 } else if (inc_state
== INC_CANCEL
) {
470 gtk_clist_set_pixmap(clist
, num
, 0, okxpm
, okxpmmask
);
471 gtk_clist_set_text(clist
, num
, 2, _("Cancelled"));
473 gtk_clist_set_pixmap(clist
, num
, 0, errorxpm
, errorxpmmask
);
474 if (inc_state
== INC_CONNECT_ERROR
)
475 gtk_clist_set_text(clist
, num
, 2,
476 _("Connection failed"));
477 else if (inc_state
== INC_AUTH_FAILED
)
478 gtk_clist_set_text(clist
, num
, 2,
481 gtk_clist_set_text(clist
, num
, 2, _("Error"));
484 if (pop3_state
->error_val
== PS_AUTHFAIL
) {
485 if(!prefs_common
.noerrorpanel
) {
486 if((prefs_common
.recv_dialog_mode
== RECV_DIALOG_ALWAYS
) ||
487 ((prefs_common
.recv_dialog_mode
== RECV_DIALOG_ACTIVE
) && focus_window
)) {
488 manage_window_focus_in(inc_dialog
->dialog
->window
, NULL
, NULL
);
491 (_("Authorization for %s on %s failed"),
493 pop3_state
->ac_prefs
->recv_server
);
499 new_msgs
+= pop3_state
->cur_total_num
;
501 if (!prefs_common
.scan_all_after_inc
) {
502 folder_item_scan_foreach(pop3_state
->folder_table
);
503 folderview_update_item_foreach
504 (pop3_state
->folder_table
);
507 if (pop3_state
->error_val
== PS_AUTHFAIL
&&
508 pop3_state
->ac_prefs
->tmp_pass
) {
509 g_free(pop3_state
->ac_prefs
->tmp_pass
);
510 pop3_state
->ac_prefs
->tmp_pass
= NULL
;
513 inc_write_uidl_list(pop3_state
);
515 if (inc_state
!= INC_SUCCESS
&& inc_state
!= INC_CANCEL
) {
517 if (inc_state
== INC_NOSPACE
) {
518 inc_put_error(inc_state
);
523 inc_session_destroy(session
);
524 inc_dialog
->queue_list
=
525 g_list_remove(inc_dialog
->queue_list
, session
);
531 if (inc_dialog
->show_dialog
)
532 manage_window_focus_in(inc_dialog
->dialog
->window
,
534 alertpanel_error(_("Some errors occured while getting mail."));
535 if (inc_dialog
->show_dialog
)
536 manage_window_focus_out(inc_dialog
->dialog
->window
,
540 while (inc_dialog
->queue_list
!= NULL
) {
541 session
= inc_dialog
->queue_list
->data
;
542 inc_session_destroy(session
);
543 inc_dialog
->queue_list
=
544 g_list_remove(inc_dialog
->queue_list
, session
);
547 inc_progress_dialog_destroy(inc_dialog
);
553 static IncState
inc_pop3_session_do(IncSession
*session
)
555 Pop3State
*pop3_state
= session
->pop3_state
;
556 IncProgressDialog
*inc_dialog
= (IncProgressDialog
*)session
->data
;
563 static AtmHandler handlers
[] = {
565 pop3_getauth_user_send
, pop3_getauth_user_recv
,
566 pop3_getauth_pass_send
, pop3_getauth_pass_recv
,
567 pop3_getauth_apop_send
, pop3_getauth_apop_recv
,
568 pop3_getrange_stat_send
, pop3_getrange_stat_recv
,
569 pop3_getrange_last_send
, pop3_getrange_last_recv
,
570 pop3_getrange_uidl_send
, pop3_getrange_uidl_recv
,
571 pop3_getsize_list_send
, pop3_getsize_list_recv
,
572 pop3_retr_send
, pop3_retr_recv
,
573 pop3_delete_send
, pop3_delete_recv
,
574 pop3_logout_send
, pop3_logout_recv
577 debug_print(_("getting new messages of account %s...\n"),
578 pop3_state
->ac_prefs
->account_name
);
580 atm
= automaton_create(N_POP3_PHASE
);
583 atm
->data
= pop3_state
;
585 buf
= g_strdup_printf(_("%s: Retrieving new messages"),
586 pop3_state
->ac_prefs
->recv_server
);
587 gtk_window_set_title(GTK_WINDOW(inc_dialog
->dialog
->window
), buf
);
590 for (i
= POP3_GREETING_RECV
; i
< N_POP3_PHASE
; i
++)
591 atm
->state
[i
].handler
= handlers
[i
];
592 atm
->state
[POP3_GREETING_RECV
].condition
= GDK_INPUT_READ
;
593 for (i
= POP3_GETAUTH_USER_SEND
; i
< N_POP3_PHASE
; ) {
594 atm
->state
[i
++].condition
= GDK_INPUT_WRITE
;
595 atm
->state
[i
++].condition
= GDK_INPUT_READ
;
598 atm
->terminate
= (AtmHandler
)pop3_automaton_terminate
;
600 atm
->num
= POP3_GREETING_RECV
;
602 server
= pop3_state
->ac_prefs
->recv_server
;
604 port
= pop3_state
->ac_prefs
->set_popport
?
605 pop3_state
->ac_prefs
->popport
: (pop3_state
->ac_prefs
->ssl_pop
? 995 : 110);
607 port
= pop3_state
->ac_prefs
->set_popport
?
608 pop3_state
->ac_prefs
->popport
: 110;
611 buf
= g_strdup_printf(_("Connecting to POP3 server: %s ..."), server
);
612 log_message("%s\n", buf
);
613 progress_dialog_set_label(inc_dialog
->dialog
, buf
);
618 if ((sockinfo
= sock_connect_with_thread(server
, port
)) == NULL
) {
620 if ((sockinfo
= sock_connect(server
, port
)) == NULL
) {
622 log_warning(_("Can't connect to POP3 server: %s:%d\n"),
624 if(!prefs_common
.noerrorpanel
) {
625 if((prefs_common
.recv_dialog_mode
== RECV_DIALOG_ALWAYS
) ||
626 ((prefs_common
.recv_dialog_mode
== RECV_DIALOG_ACTIVE
) && focus_window
)) {
627 manage_window_focus_in(inc_dialog
->dialog
->window
, NULL
, NULL
);
629 alertpanel_error(_("Can't connect to POP3 server: %s:%d"),
631 manage_window_focus_out(inc_dialog
->dialog
->window
, NULL
, NULL
);
633 pop3_automaton_terminate(NULL
, atm
);
634 automaton_destroy(atm
);
636 return INC_CONNECT_ERROR
;
639 /* :WK: Hmmm, with the later sock_gdk_input, we have 2 references
640 * to the sock structure - implement a reference counter?? */
641 pop3_state
->sockinfo
= sockinfo
;
642 atm
->help_sock
= sockinfo
;
645 if(pop3_state
->ac_prefs
->ssl_pop
) {
646 if(!ssl_init_socket(sockinfo
)) {
647 pop3_automaton_terminate(NULL
, atm
);
648 automaton_destroy(atm
);
650 return INC_CONNECT_ERROR
;
653 sockinfo
->ssl
= NULL
;
658 recv_set_ui_func(inc_pop3_recv_func
, session
);
661 atm
->timeout_tag
= gtk_timeout_add
662 (TIMEOUT_ITV
, (GtkFunction
)connection_check_cb
, atm
);
664 atm
->tag
= sock_gdk_input_add(sockinfo
,
665 atm
->state
[atm
->num
].condition
,
666 automaton_input_cb
, atm
);
671 recv_set_ui_func(NULL
, NULL
);
675 pthread_join(sockinfo->connect_thr, NULL);
680 ssl_done_socket(sockinfo
);
682 automaton_destroy(atm
);
684 return pop3_state
->inc_state
;
687 static gint
pop3_automaton_terminate(SockInfo
*source
, Automaton
*atm
)
690 gdk_input_remove(atm
->tag
);
693 if (atm
->timeout_tag
> 0) {
694 gtk_timeout_remove(atm
->timeout_tag
);
695 atm
->timeout_tag
= 0;
702 atm
->terminated
= TRUE
;
707 static GHashTable
*inc_get_uidl_table(PrefsAccount
*ac_prefs
)
712 gchar buf
[IDLEN
+ 3];
714 path
= g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S
,
715 "uidl-", ac_prefs
->recv_server
,
716 "-", ac_prefs
->userid
, NULL
);
717 if ((fp
= fopen(path
, "r")) == NULL
) {
718 if (ENOENT
!= errno
) FILE_OP_ERROR(path
, "fopen");
724 table
= g_hash_table_new(g_str_hash
, g_str_equal
);
726 while (fgets(buf
, sizeof(buf
), fp
) != NULL
) {
728 g_hash_table_insert(table
, g_strdup(buf
), GINT_TO_POINTER(1));
736 static void inc_write_uidl_list(Pop3State
*state
)
742 if (!state
->id_list
) return;
744 path
= g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S
,
745 "uidl-", state
->ac_prefs
->recv_server
,
746 "-", state
->user
, NULL
);
747 if ((fp
= fopen(path
, "w")) == NULL
) {
748 FILE_OP_ERROR(path
, "fopen");
753 for (cur
= state
->id_list
; cur
!= NULL
; cur
= cur
->next
) {
754 if (fputs((gchar
*)cur
->data
, fp
) == EOF
) {
755 FILE_OP_ERROR(path
, "fputs");
758 if (fputc('\n', fp
) == EOF
) {
759 FILE_OP_ERROR(path
, "fputc");
764 if (fclose(fp
) == EOF
) FILE_OP_ERROR(path
, "fclose");
769 static gint
connection_check_cb(Automaton
*atm
)
771 Pop3State
*state
= atm
->data
;
772 IncProgressDialog
*inc_dialog
= state
->session
->data
;
773 SockInfo
*sockinfo
= state
->sockinfo
;
775 /* g_print("connection check\n"); */
777 if (sockinfo
->state
== CONN_LOOKUPFAILED
||
778 sockinfo
->state
== CONN_FAILED
) {
779 atm
->timeout_tag
= 0;
780 log_warning(_("Can't connect to POP3 server: %s:%d\n"),
781 sockinfo
->hostname
, sockinfo
->port
);
782 if(!prefs_common
.noerrorpanel
) {
783 if((prefs_common
.recv_dialog_mode
== RECV_DIALOG_ALWAYS
) ||
784 ((prefs_common
.recv_dialog_mode
== RECV_DIALOG_ACTIVE
) && focus_window
)) {
785 manage_window_focus_in(inc_dialog
->dialog
->window
, NULL
, NULL
);
787 alertpanel_error(_("Can't connect to POP3 server: %s:%d"),
788 sockinfo
->hostname
, sockinfo
->port
);
789 manage_window_focus_out(inc_dialog
->dialog
->window
, NULL
, NULL
);
791 pop3_automaton_terminate(sockinfo
, atm
);
793 } else if (sockinfo
->state
== CONN_ESTABLISHED
) {
794 atm
->timeout_tag
= 0;
795 atm
->tag
= sock_gdk_input_add(sockinfo
,
796 atm
->state
[atm
->num
].condition
,
797 automaton_input_cb
, atm
);
805 static void inc_pop3_recv_func(SockInfo
*sock
, gint count
, gint read_bytes
,
808 gchar buf
[MSGBUFSIZE
];
809 IncSession
*session
= (IncSession
*)data
;
810 Pop3State
*state
= session
->pop3_state
;
811 IncProgressDialog
*inc_dialog
= session
->data
;
812 ProgressDialog
*dialog
= inc_dialog
->dialog
;
816 cur_total
= state
->cur_total_bytes
+ read_bytes
;
817 if (cur_total
> state
->total_bytes
)
818 cur_total
= state
->total_bytes
;
820 Xstrdup_a(total_size
, to_human_readable(state
->total_bytes
), return);
821 g_snprintf(buf
, sizeof(buf
),
822 _("Retrieving message (%d / %d) (%s / %s)"),
823 state
->cur_msg
, state
->count
,
824 to_human_readable(cur_total
), total_size
);
825 progress_dialog_set_label(dialog
, buf
);
827 progress_dialog_set_percentage
828 (dialog
, (gfloat
)cur_total
/ (gfloat
)state
->total_bytes
);
832 void inc_progress_update(Pop3State
*state
, Pop3Phase phase
)
834 gchar buf
[MSGBUFSIZE
];
835 IncProgressDialog
*inc_dialog
= state
->session
->data
;
836 ProgressDialog
*dialog
= inc_dialog
->dialog
;
840 case POP3_GREETING_RECV
:
842 case POP3_GETAUTH_USER_SEND
:
843 case POP3_GETAUTH_USER_RECV
:
844 case POP3_GETAUTH_PASS_SEND
:
845 case POP3_GETAUTH_PASS_RECV
:
846 case POP3_GETAUTH_APOP_SEND
:
847 case POP3_GETAUTH_APOP_RECV
:
848 progress_dialog_set_label(dialog
, _("Authorizing..."));
850 case POP3_GETRANGE_STAT_SEND
:
851 case POP3_GETRANGE_STAT_RECV
:
852 progress_dialog_set_label
853 (dialog
, _("Getting the number of new messages (STAT)..."));
855 case POP3_GETRANGE_LAST_SEND
:
856 case POP3_GETRANGE_LAST_RECV
:
857 progress_dialog_set_label
858 (dialog
, _("Getting the number of new messages (LAST)..."));
860 case POP3_GETRANGE_UIDL_SEND
:
861 case POP3_GETRANGE_UIDL_RECV
:
862 progress_dialog_set_label
863 (dialog
, _("Getting the number of new messages (UIDL)..."));
865 case POP3_GETSIZE_LIST_SEND
:
866 case POP3_GETSIZE_LIST_RECV
:
867 progress_dialog_set_label
868 (dialog
, _("Getting the size of messages (LIST)..."));
872 Xstrdup_a(total_size
, to_human_readable(state
->total_bytes
), return);
873 g_snprintf(buf
, sizeof(buf
),
874 _("Retrieving message (%d / %d) (%s / %s)"),
875 state
->cur_msg
, state
->count
,
876 to_human_readable(state
->cur_total_bytes
),
878 progress_dialog_set_label(dialog
, buf
);
879 progress_dialog_set_percentage
881 (gfloat
)(state
->cur_total_bytes
) /
882 (gfloat
)(state
->total_bytes
));
884 case POP3_DELETE_SEND
:
885 case POP3_DELETE_RECV
:
886 progress_dialog_set_label(dialog
, _("Deleting message"));
888 case POP3_LOGOUT_SEND
:
889 case POP3_LOGOUT_RECV
:
890 progress_dialog_set_label(dialog
, _("Quitting"));
897 gint
inc_drop_message(const gchar
*file
, Pop3State
*state
)
900 FolderItem
*dropfolder
;
904 if (state
->ac_prefs
->inbox
) {
905 inbox
= folder_find_item_from_path(state
->ac_prefs
->inbox
);
907 inbox
= folder_get_default_inbox();
909 inbox
= folder_get_default_inbox();
915 if (prefs_filtering
== NULL
) {
917 if (state
->ac_prefs
->filter_on_recv
) {
919 filter_get_dest_folder(prefs_common
.fltlist
, file
);
920 if (!dropfolder
) dropfolder
= inbox
;
921 else if (!strcmp(dropfolder
->path
, FILTER_NOT_RECEIVE
)) {
922 g_warning(_("a message won't be received\n"));
932 val
= GPOINTER_TO_INT(g_hash_table_lookup
933 (state
->folder_table
, dropfolder
));
935 folder_item_scan(dropfolder
);
936 g_hash_table_insert(state
->folder_table
, dropfolder
,
940 if (prefs_filtering
== NULL
|| !state
->ac_prefs
->filter_on_recv
) {
941 if ((msgnum
= folder_item_add_msg(dropfolder
, file
, TRUE
)) < 0) {
947 filter_incoming_message(dropfolder
, file
, state
->folder_table
);
953 static void inc_put_error(IncState istate
)
957 if(!prefs_common
.noerrorpanel
) {
958 alertpanel_error(_("Error occurred while processing mail."));
962 alertpanel_error(_("No disk space left."));
969 static void inc_cancel(GtkWidget
*widget
, gpointer data
)
971 IncProgressDialog
*dialog
= data
;
972 IncSession
*session
= dialog
->queue_list
->data
;
973 SockInfo
*sockinfo
= session
->pop3_state
->sockinfo
;
976 if (sockinfo
->state
== CONN_READY
||
977 sockinfo
->state
== CONN_LOOKUPSUCCESS
) {
978 pthread_cancel(sockinfo
->connect_thr
);
979 /* pthread_kill(sockinfo->connect_thr, SIGINT); */
980 g_print("connection was cancelled.\n");
984 session
->pop3_state
->inc_state
= INC_CANCEL
;
985 pop3_automaton_terminate(sockinfo
, session
->atm
);
988 static gint
inc_spool(void)
990 gchar
*mbox
, *logname
;
993 logname
= g_get_user_name();
994 mbox
= g_strconcat(prefs_common
.spool_path
995 ? prefs_common
.spool_path
: DEFAULT_SPOOL_PATH
,
996 G_DIR_SEPARATOR_S
, logname
, NULL
);
997 msgs
= get_spool(folder_get_default_inbox(), mbox
);
1003 static void inc_spool_account(PrefsAccount
*account
)
1006 FolderItem
*dropfolder
;
1009 if (account
->inbox
) {
1010 inbox
= folder_find_item_from_path(account
->inbox
);
1012 inbox
= folder_get_default_inbox();
1014 inbox
= folder_get_default_inbox();
1016 get_spool(inbox
, account
->local_mbox
);
1019 static void inc_all_spool(void)
1023 list
= account_get_list();
1026 for (; list
!= NULL
; list
= list
->next
) {
1027 IncSession
*session
;
1028 PrefsAccount
*account
= list
->data
;
1030 if (account
->protocol
== A_LOCAL
)
1031 inc_spool_account(account
);
1035 static gint
get_spool(FolderItem
*dest
, const gchar
*mbox
)
1039 gchar tmp_mbox
[MAXPATHLEN
+ 1];
1040 GHashTable
*folder_table
= NULL
;
1042 g_return_val_if_fail(dest
!= NULL
, -1);
1043 g_return_val_if_fail(mbox
!= NULL
, -1);
1045 if (!is_file_exist(mbox
) || (size
= get_file_size(mbox
)) == 0) {
1046 debug_print(_("no messages in local mailbox.\n"));
1048 } else if (size
< 0)
1051 if ((lockfd
= lock_mbox(mbox
, LOCK_FLOCK
)) < 0)
1054 g_snprintf(tmp_mbox
, sizeof(tmp_mbox
), "%s%ctmpmbox%d",
1055 get_rc_dir(), G_DIR_SEPARATOR
, (gint
)mbox
);
1057 if (copy_mbox(mbox
, tmp_mbox
) < 0)
1060 debug_print(_("Getting new messages from %s into %s...\n"),
1063 if (prefs_common
.filter_on_inc
)
1064 folder_table
= g_hash_table_new(NULL
, NULL
);
1065 msgs
= proc_mbox(dest
, tmp_mbox
, folder_table
);
1068 if (msgs
>= 0) empty_mbox(mbox
);
1069 unlock_mbox(mbox
, lockfd
, LOCK_FLOCK
);
1072 if (!prefs_common
.scan_all_after_inc
) {
1073 g_hash_table_insert(folder_table
, dest
,
1074 GINT_TO_POINTER(1));
1075 folder_item_scan_foreach(folder_table
);
1076 folderview_update_item_foreach(folder_table
);
1078 g_hash_table_destroy(folder_table
);
1079 } else if (!prefs_common
.scan_all_after_inc
) {
1080 folder_item_scan(dest
);
1081 folderview_update_item(dest
, FALSE
);
1087 static guint autocheck_timer
= 0;
1088 static gpointer autocheck_data
= NULL
;
1090 void inc_autocheck_timer_init(MainWindow
*mainwin
)
1092 autocheck_data
= mainwin
;
1093 inc_autocheck_timer_set();
1096 void inc_autocheck_timer_set(void)
1098 inc_autocheck_timer_remove();
1100 if (prefs_common
.autochk_newmail
&& autocheck_data
) {
1101 autocheck_timer
= gtk_timeout_add
1102 (prefs_common
.autochk_itv
* 60000,
1108 void inc_autocheck_timer_remove(void)
1110 if (autocheck_timer
) {
1111 gtk_timeout_remove(autocheck_timer
);
1112 autocheck_timer
= 0;
1116 static gint
inc_autocheck_func(gpointer data
)
1118 MainWindow
*mainwin
= (MainWindow
*)data
;
1120 inc_all_account_mail(mainwin
);