Synch with Hiroyuki's main branch.
[claws.git] / src / inc.c
1 /*
2  * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3  * Copyright (C) 1999,2000 Hiroyuki Yamamoto
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  */
19
20 #ifdef HAVE_CONFIG_H
21 #  include "config.h"
22 #endif
23
24 #include "defs.h"
25
26 #include <glib.h>
27 #include <gtk/gtkmain.h>
28 #include <gtk/gtkwindow.h>
29 #include <gtk/gtksignal.h>
30 #include <stdio.h>
31 #include <unistd.h>
32 #include <string.h>
33 #include <sys/types.h>
34 #include <sys/stat.h>
35 #include <sys/wait.h>
36 #include <signal.h>
37 #include <errno.h>
38
39 #include "intl.h"
40 #include "main.h"
41 #include "inc.h"
42 #include "mainwindow.h"
43 #include "folderview.h"
44 #include "summaryview.h"
45 #include "prefs_common.h"
46 #include "prefs_account.h"
47 #include "account.h"
48 #include "procmsg.h"
49 #include "socket.h"
50 #include "pop.h"
51 #include "recv.h"
52 #include "mbox.h"
53 #include "utils.h"
54 #include "gtkutils.h"
55 #include "statusbar.h"
56 #include "manage_window.h"
57 #include "progressdialog.h"
58 #include "inputdialog.h"
59 #include "alertpanel.h"
60 #include "filter.h"
61 #include "automaton.h"
62 #include "folder.h"
63
64 #define MSGBUFSIZE      8192
65
66 static void inc_finished                (MainWindow             *mainwin);
67 static void inc_account_mail            (PrefsAccount           *account,
68                                          MainWindow             *mainwin);
69
70 static IncProgressDialog *inc_progress_dialog_create    (void);
71 static void inc_progress_dialog_destroy (IncProgressDialog      *inc_dialog);
72
73 static IncSession *inc_session_new      (PrefsAccount           *account);
74 static void inc_session_destroy         (IncSession             *session);
75 static Pop3State *inc_pop3_state_new    (PrefsAccount           *account);
76 static void inc_pop3_state_destroy      (Pop3State              *state);
77 static void inc_start                   (IncProgressDialog      *inc_dialog);
78 static IncState inc_pop3_session_do     (IncSession             *session);
79 static gint pop3_automaton_terminate    (gint                    source,
80                                          Automaton              *atm);
81
82 static GHashTable *inc_get_uidl_table   (PrefsAccount           *ac_prefs);
83 static void inc_write_uidl_list         (Pop3State              *state);
84
85 #if USE_THREADS
86 static gint connection_check_cb         (Automaton      *atm);
87 #endif
88
89 static void inc_put_error               (IncState        istate);
90
91 static void inc_cancel                  (GtkWidget      *widget,
92                                          gpointer        data);
93
94 static gint inc_spool                   (void);
95 static gint get_spool                   (FolderItem     *dest,
96                                          const gchar    *mbox);
97
98 static void inc_finished(MainWindow *mainwin)
99 {
100         FolderItem *item;
101
102         if (prefs_common.open_inbox_on_inc) {
103                 item = cur_account && cur_account->inbox
104                         ? folder_find_item_from_path(cur_account->inbox)
105                         : folder_get_default_inbox();
106                 folderview_unselect(mainwin->folderview);
107                 folderview_select(mainwin->folderview, item);
108         } else {
109                 item = mainwin->summaryview->folder_item;
110                 folderview_unselect(mainwin->folderview);
111                 folderview_select(mainwin->folderview, item);
112         }
113 }
114
115 void inc_mail(MainWindow *mainwin)
116 {
117         summary_write_cache(mainwin->summaryview);
118
119         if (prefs_common.use_extinc && prefs_common.extinc_path) {
120                 gint pid;
121
122                 /* external incorporating program */
123                 if ((pid = fork()) < 0) {
124                         perror("fork");
125                         return;
126                 }
127
128                 if (pid == 0) {
129                         execlp(prefs_common.extinc_path,
130                                g_basename(prefs_common.extinc_path),
131                                NULL);
132
133                         /* this will be called when failed */
134                         perror("exec");
135                         _exit(1);
136                 }
137
138                 /* wait until child process is terminated */
139                 waitpid(pid, NULL, 0);
140
141                 if (prefs_common.inc_local) inc_spool();
142         } else {
143                 if (prefs_common.inc_local) inc_spool();
144
145                 inc_account_mail(cur_account, mainwin);
146         }
147
148         inc_finished(mainwin);
149 }
150
151 static void inc_account_mail(PrefsAccount *account, MainWindow *mainwin)
152 {
153         IncProgressDialog *inc_dialog;
154         IncSession *session;
155
156         session = inc_session_new(account);
157         if (!session) return;
158
159         inc_dialog = inc_progress_dialog_create();
160         inc_dialog->queue_list = g_list_append(inc_dialog->queue_list, session);
161         inc_dialog->mainwin = mainwin;
162         session->data = inc_dialog;
163
164         inc_start(inc_dialog);
165 }
166
167 void inc_all_account_mail(MainWindow *mainwin)
168 {
169         GList *list, *queue_list = NULL;
170         IncProgressDialog *inc_dialog;
171
172         summary_write_cache(mainwin->summaryview);
173
174         if (prefs_common.inc_local) inc_spool();
175
176         list = account_get_list();
177         if (!list) return;
178
179         for (; list != NULL; list = list->next) {
180                 IncSession *session;
181                 PrefsAccount *account = list->data;
182
183                 if (account->recv_at_getall) {
184                         session = inc_session_new(account);
185                         if (session)
186                                 queue_list = g_list_append(queue_list, session);
187                 }
188         }
189
190         if (!queue_list) return;
191
192         inc_dialog = inc_progress_dialog_create();
193         inc_dialog->queue_list = queue_list;
194         inc_dialog->mainwin = mainwin;
195         for (list = queue_list; list != NULL; list = list->next) {
196                 IncSession *session = list->data;
197                 session->data = inc_dialog;
198         }
199
200         inc_start(inc_dialog);
201
202         inc_finished(mainwin);
203 }
204
205 static IncProgressDialog *inc_progress_dialog_create(void)
206 {
207         IncProgressDialog *dialog;
208         ProgressDialog *progress;
209
210         dialog = g_new0(IncProgressDialog, 1);
211
212         progress = progress_dialog_create();
213         gtk_window_set_title(GTK_WINDOW(progress->window),
214                              _("Retrieving new messages"));
215         gtk_signal_connect(GTK_OBJECT(progress->cancel_btn), "clicked",
216                            GTK_SIGNAL_FUNC(inc_cancel), dialog);
217         gtk_signal_connect(GTK_OBJECT(progress->window), "delete_event",
218                            GTK_SIGNAL_FUNC(gtk_true), NULL);
219         manage_window_set_transient(GTK_WINDOW(progress->window));
220
221         progress_dialog_set_value(progress, 0.0);
222
223         gtk_widget_show_now(progress->window);
224
225         dialog->dialog = progress;
226         dialog->queue_list = NULL;
227
228         return dialog;
229 }
230
231 static void inc_progress_dialog_clear(IncProgressDialog *inc_dialog)
232 {
233         progress_dialog_set_value(inc_dialog->dialog, 0.0);
234         progress_dialog_set_label(inc_dialog->dialog, "");
235 }
236
237 static void inc_progress_dialog_destroy(IncProgressDialog *inc_dialog)
238 {
239         g_return_if_fail(inc_dialog != NULL);
240
241         progress_dialog_destroy(inc_dialog->dialog);
242
243         g_free(inc_dialog);
244 }
245
246 static IncSession *inc_session_new(PrefsAccount *account)
247 {
248         IncSession *session;
249
250         g_return_val_if_fail(account != NULL, NULL);
251
252         if (account->protocol != A_POP3 && account->protocol != A_APOP)
253                 return NULL;
254         if (!account->recv_server || !account->userid)
255                 return NULL;
256
257         session = g_new0(IncSession, 1);
258         session->pop3_state = inc_pop3_state_new(account);
259         session->pop3_state->session = session;
260
261         return session;
262 }
263
264 static void inc_session_destroy(IncSession *session)
265 {
266         g_return_if_fail(session != NULL);
267
268         inc_pop3_state_destroy(session->pop3_state);
269         g_free(session);
270 }
271
272 static Pop3State *inc_pop3_state_new(PrefsAccount *account)
273 {
274         Pop3State *state;
275
276         state = g_new0(Pop3State, 1);
277
278         state->ac_prefs = account;
279         state->folder_table = g_hash_table_new(NULL, NULL);
280         state->id_table = inc_get_uidl_table(account);
281         state->id_list = NULL;
282         state->new_id_list = NULL;
283         state->inc_state = INC_SUCCESS;
284
285         return state;
286 }
287
288 static void inc_pop3_state_destroy(Pop3State *state)
289 {
290         g_hash_table_destroy(state->folder_table);
291         if (state->id_table) {
292                 hash_free_strings(state->id_table);
293                 g_hash_table_destroy(state->id_table);
294         }
295         slist_free_strings(state->id_list);
296         slist_free_strings(state->new_id_list);
297         g_slist_free(state->id_list);
298         g_slist_free(state->new_id_list);
299
300         g_free(state->greeting);
301         g_free(state->user);
302         g_free(state->pass);
303         g_free(state->prev_folder);
304
305         g_free(state);
306 }
307
308 static void inc_start(IncProgressDialog *inc_dialog)
309 {
310         IncSession *session;
311         Pop3State *pop3_state;
312         IncState inc_state;
313
314         while (inc_dialog->queue_list != NULL) {
315                 session = inc_dialog->queue_list->data;
316                 pop3_state = session->pop3_state;
317
318                 inc_progress_dialog_clear(inc_dialog);
319
320                 pop3_state->user = g_strdup(pop3_state->ac_prefs->userid);
321                 if (pop3_state->ac_prefs->passwd)
322                         pop3_state->pass =
323                                 g_strdup(pop3_state->ac_prefs->passwd);
324                 else if (pop3_state->ac_prefs->tmp_pass)
325                         pop3_state->pass =
326                                 g_strdup(pop3_state->ac_prefs->tmp_pass);
327                 else {
328                         gchar *pass;
329                         gchar *message;
330
331                         message = g_strdup_printf
332                                 (_("Input password for %s on %s:"),
333                                  pop3_state->user,
334                                  pop3_state->ac_prefs->recv_server);
335
336                         pass = input_dialog_with_invisible(_("Input password"),
337                                                            message, NULL);
338                         g_free(message);
339                         manage_window_focus_in(inc_dialog->mainwin->window,
340                                                NULL, NULL);
341                         if (pass) {
342                                 pop3_state->ac_prefs->tmp_pass = g_strdup(pass);
343                                 pop3_state->pass = pass;
344                         } else {
345                                 inc_session_destroy(session);
346                                 inc_dialog->queue_list = g_list_remove
347                                         (inc_dialog->queue_list, session);
348                                 continue;
349                         }
350                 }
351
352                 /* begin POP3 session */
353                 inc_state = inc_pop3_session_do(session);
354
355                 if (pop3_state->error_val == PS_AUTHFAIL) {
356                         manage_window_focus_in(inc_dialog->dialog->window, NULL, NULL);
357                         alertpanel_error
358                                 (_("Authorization for %s on %s failed"),
359                                  pop3_state->user,
360                                  pop3_state->ac_prefs->recv_server);
361                 }
362
363                 statusbar_pop_all();
364                 manage_window_focus_in(inc_dialog->mainwin->window, NULL, NULL);
365
366                 folder_item_scan_foreach(pop3_state->folder_table);
367                 folderview_update_item_foreach(pop3_state->folder_table);
368
369                 if (pop3_state->error_val == PS_AUTHFAIL &&
370                     pop3_state->ac_prefs->tmp_pass) {
371                         g_free(pop3_state->ac_prefs->tmp_pass);
372                         pop3_state->ac_prefs->tmp_pass = NULL;
373                 }
374
375                 inc_write_uidl_list(pop3_state);
376
377                 if (inc_state != INC_SUCCESS) {
378                         inc_put_error(inc_state);
379                         break;
380                 }
381
382                 inc_session_destroy(session);
383                 inc_dialog->queue_list =
384                         g_list_remove(inc_dialog->queue_list, session);
385         }
386
387         while (inc_dialog->queue_list != NULL) {
388                 session = inc_dialog->queue_list->data;
389                 inc_session_destroy(session);
390                 inc_dialog->queue_list =
391                         g_list_remove(inc_dialog->queue_list, session);
392         }
393
394         inc_progress_dialog_destroy(inc_dialog);
395 }
396
397 static IncState inc_pop3_session_do(IncSession *session)
398 {
399         Pop3State *pop3_state = session->pop3_state;
400         IncProgressDialog *inc_dialog = (IncProgressDialog *)session->data;
401         Automaton *atm;
402         SockInfo *sockinfo;
403         gint i;
404         gchar *server;
405         gushort port;
406         gchar *buf;
407         AtmHandler handlers[] = {
408                 pop3_greeting_recv      ,
409                 pop3_getauth_user_send  , pop3_getauth_user_recv,
410                 pop3_getauth_pass_send  , pop3_getauth_pass_recv,
411                 pop3_getauth_apop_send  , pop3_getauth_apop_recv,
412                 pop3_getrange_stat_send , pop3_getrange_stat_recv,
413                 pop3_getrange_last_send , pop3_getrange_last_recv,
414                 pop3_getrange_uidl_send , pop3_getrange_uidl_recv,
415                 pop3_retr_send          , pop3_retr_recv,
416                 pop3_delete_send        , pop3_delete_recv,
417                 pop3_logout_send        , pop3_logout_recv
418         };
419
420         debug_print(_("getting new messages of account %s...\n"),
421                     pop3_state->ac_prefs->account_name);
422
423         atm = automaton_create(N_POP3_PHASE);
424
425         session->atm = atm;
426         atm->data = pop3_state;
427
428         buf = g_strdup_printf(_("%s: Retrieving new messages"),
429                               pop3_state->ac_prefs->recv_server);
430         gtk_window_set_title(GTK_WINDOW(inc_dialog->dialog->window), buf);
431         g_free(buf);
432
433         for (i = POP3_GREETING_RECV; i < N_POP3_PHASE; i++)
434                 atm->state[i].handler = handlers[i];
435         atm->state[POP3_GREETING_RECV].condition = GDK_INPUT_READ;
436         for (i = POP3_GETAUTH_USER_SEND; i < N_POP3_PHASE; ) {
437                 atm->state[i++].condition = GDK_INPUT_WRITE;
438                 atm->state[i++].condition = GDK_INPUT_READ;
439         }
440
441         atm->terminate = (AtmHandler)pop3_automaton_terminate;
442
443         atm->num = POP3_GREETING_RECV;
444
445         server = pop3_state->ac_prefs->recv_server;
446         port = pop3_state->ac_prefs->set_popport ?
447                 pop3_state->ac_prefs->popport : 110;
448
449         buf = g_strdup_printf(_("Connecting to POP3 server: %s ..."), server);
450         log_message("%s\n", buf);
451         progress_dialog_set_label(inc_dialog->dialog, buf);
452         g_free(buf);
453         GTK_EVENTS_FLUSH();
454
455 #if USE_THREADS
456         if ((sockinfo = sock_connect_with_thread(server, port)) == NULL) {
457 #else
458         if ((sockinfo = sock_connect_nb(server, port)) == NULL) {
459 #endif
460                 log_warning(_("Can't connect to POP3 server: %s:%d\n"),
461                             server, port);
462                 manage_window_focus_in(inc_dialog->dialog->window, NULL, NULL);
463                 alertpanel_error(_("Can't connect to POP3 server: %s:%d"),
464                                  server, port);
465                 manage_window_focus_out(inc_dialog->dialog->window, NULL, NULL);
466                 pop3_automaton_terminate(-1, atm);
467                 automaton_destroy(atm);
468
469                 return pop3_state->inc_state;
470         }
471
472         pop3_state->sockinfo = sockinfo;
473
474 #if USE_THREADS
475         atm->timeout_tag = gtk_timeout_add
476                 (TIMEOUT_ITV, (GtkFunction)connection_check_cb, atm);
477 #else
478         atm->tag = gdk_input_add(sockinfo->sock,
479                                  atm->state[atm->num].condition,
480                                  automaton_input_cb, atm);
481 #endif
482
483         gtk_main();
484
485 #if USE_THREADS
486         //pthread_join(sockinfo->connect_thr, NULL);
487 #endif
488         sock_sockinfo_free(sockinfo);
489         automaton_destroy(atm);
490
491         return pop3_state->inc_state;
492 }
493
494 static gint pop3_automaton_terminate(gint source, Automaton *atm)
495 {
496         if (atm->tag > 0) {
497                 gdk_input_remove(atm->tag);
498                 atm->tag = 0;
499         }
500         if (atm->timeout_tag > 0) {
501                 gtk_timeout_remove(atm->timeout_tag);
502                 atm->timeout_tag = 0;
503         }
504         if (source > 0) {
505                 sock_close(source);
506                 gtk_main_quit();
507         }
508
509         atm->terminated = TRUE;
510
511         return 0;
512 }
513
514 static GHashTable *inc_get_uidl_table(PrefsAccount *ac_prefs)
515 {
516         GHashTable *table;
517         gchar *path;
518         FILE *fp;
519         gchar buf[IDLEN + 3];
520
521         path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
522                            "uidl-", ac_prefs->recv_server,
523                            "-", ac_prefs->userid, NULL);
524         if ((fp = fopen(path, "r")) == NULL) {
525                 if (ENOENT != errno) FILE_OP_ERROR(path, "fopen");
526                 g_free(path);
527                 return NULL;
528         }
529         g_free(path);
530
531         table = g_hash_table_new(g_str_hash, g_str_equal);
532
533         while (fgets(buf, sizeof(buf), fp) != NULL) {
534                 strretchomp(buf);
535                 g_hash_table_insert(table, g_strdup(buf), GINT_TO_POINTER(1));
536         }
537
538         fclose(fp);
539
540         return table;
541 }
542
543 static void inc_write_uidl_list(Pop3State *state)
544 {
545         gchar *path;
546         FILE *fp;
547         GSList *cur;
548
549         if (!state->id_list) return;
550
551         path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S,
552                            "uidl-", state->ac_prefs->recv_server,
553                            "-", state->user, NULL);
554         if ((fp = fopen(path, "w")) == NULL) {
555                 FILE_OP_ERROR(path, "fopen");
556                 g_free(path);
557                 return;
558         }
559
560         for (cur = state->id_list; cur != NULL; cur = cur->next) {
561                 if (fputs((gchar *)cur->data, fp) == EOF) {
562                         FILE_OP_ERROR(path, "fputs");
563                         break;
564                 }
565                 if (fputc('\n', fp) == EOF) {
566                         FILE_OP_ERROR(path, "fputc");
567                         break;
568                 }
569         }
570
571         if (fclose(fp) == EOF) FILE_OP_ERROR(path, "fclose");
572         g_free(path);
573 }
574
575 #if USE_THREADS
576 static gint connection_check_cb(Automaton *atm)
577 {
578         Pop3State *state = atm->data;
579         IncProgressDialog *inc_dialog = state->session->data;
580         SockInfo *sockinfo = state->sockinfo;
581
582         //g_print("connection check\n");
583
584         if (sockinfo->state == CONN_LOOKUPFAILED ||
585             sockinfo->state == CONN_FAILED) {
586                 atm->timeout_tag = 0;
587                 pop3_automaton_terminate(sockinfo->sock, atm);
588                 log_warning(_("Can't connect to POP3 server: %s:%d\n"),
589                             sockinfo->hostname, sockinfo->port);
590                 manage_window_focus_in(inc_dialog->dialog->window, NULL, NULL);
591                 alertpanel_error(_("Can't connect to POP3 server: %s:%d"),
592                                  sockinfo->hostname, sockinfo->port);
593                 manage_window_focus_out(inc_dialog->dialog->window, NULL, NULL);
594                 return FALSE;
595         } else if (sockinfo->state == CONN_ESTABLISHED) {
596                 atm->timeout_tag = 0;
597                 atm->tag = gdk_input_add(sockinfo->sock,
598                                          atm->state[atm->num].condition,
599                                          automaton_input_cb, atm);
600                 return FALSE;
601         } else {
602                 return TRUE;
603         }
604 }
605 #endif
606
607 void inc_progress_update(Pop3State *state, Pop3Phase phase)
608 {
609         gchar buf[MSGBUFSIZE];
610         IncProgressDialog *inc_dialog = state->session->data;
611         ProgressDialog *dialog = inc_dialog->dialog;
612
613         switch (phase) {
614         case POP3_GREETING_RECV:
615                 break;
616         case POP3_GETAUTH_USER_SEND:
617         case POP3_GETAUTH_USER_RECV:
618         case POP3_GETAUTH_PASS_SEND:
619         case POP3_GETAUTH_PASS_RECV:
620         case POP3_GETAUTH_APOP_SEND:
621         case POP3_GETAUTH_APOP_RECV:
622                 progress_dialog_set_label(dialog, _("Authorizing"));
623                 break;
624         case POP3_GETRANGE_STAT_SEND:
625         case POP3_GETRANGE_STAT_RECV:
626         case POP3_GETRANGE_LAST_SEND:
627         case POP3_GETRANGE_LAST_RECV:
628         case POP3_GETRANGE_UIDL_SEND:
629         case POP3_GETRANGE_UIDL_RECV:
630                 progress_dialog_set_label(dialog,
631                                           _("Getting number of new messages"));
632                 break;
633         case POP3_RETR_SEND:
634         case POP3_RETR_RECV:
635                 g_snprintf(buf, sizeof(buf),
636                            _("Retrieving message (%d / %d)"),
637                            state->cur_msg, state->count);
638                 progress_dialog_set_label(dialog, buf);
639                 progress_dialog_set_percentage
640                         (dialog, (gfloat)state->cur_msg / state->count);
641                 break;
642         case POP3_DELETE_SEND:
643         case POP3_DELETE_RECV:
644                 progress_dialog_set_label(dialog, _("Deleting message"));
645                 break;
646         case POP3_LOGOUT_SEND:
647         case POP3_LOGOUT_RECV:
648                 progress_dialog_set_label(dialog, _("Quitting"));
649                 break;
650         default:
651         }
652 }
653
654 gint inc_drop_message(const gchar *file, Pop3State *state)
655 {
656         FolderItem *inbox;
657         FolderItem *dropfolder;
658         gint val;
659
660         if (state->ac_prefs->inbox) {
661                 inbox = folder_find_item_from_path(state->ac_prefs->inbox);
662                 if (!inbox)
663                         inbox = folder_get_default_inbox();
664         } else
665                 inbox = folder_get_default_inbox();
666         if (!inbox) {
667                 unlink(file);
668                 return -1;
669         }
670
671         if (state->ac_prefs->filter_on_recv) {
672                 dropfolder =
673                         filter_get_dest_folder(prefs_common.fltlist, file);
674                 if (!dropfolder) dropfolder = inbox;
675                 else if (!strcmp(dropfolder->path, FILTER_NOT_RECEIVE)) {
676                         g_warning(_("a message won't be received\n"));
677                         return 1;
678                 }
679         } else
680                 dropfolder = inbox;
681
682         val = GPOINTER_TO_INT(g_hash_table_lookup
683                               (state->folder_table, dropfolder));
684         if (val == 0) {
685                 folder_item_scan(dropfolder);
686                 g_hash_table_insert(state->folder_table, dropfolder,
687                                     GINT_TO_POINTER(1));
688         }
689
690         if (folder_item_add_msg(dropfolder, file) < 0) {
691                 unlink(file);
692                 return -1;
693         }
694
695         unlink(file);
696         return 0;
697 }
698
699 static void inc_put_error(IncState istate)
700 {
701         switch (istate) {
702         case INC_ERROR:
703                 alertpanel_error(_("Error occurred while processing mail."));
704                 break;
705         case INC_NOSPACE:
706                 alertpanel_error(_("No disk space left."));
707                 break;
708         default:
709         }
710 }
711
712 static void inc_cancel(GtkWidget *widget, gpointer data)
713 {
714         IncProgressDialog *dialog = data;
715         IncSession *session = dialog->queue_list->data;
716         SockInfo *sockinfo = session->pop3_state->sockinfo;
717
718 #if USE_THREADS
719         if (sockinfo->state == CONN_READY ||
720             sockinfo->state == CONN_LOOKUPSUCCESS) {
721                 pthread_cancel(sockinfo->connect_thr);
722                 //pthread_kill(sockinfo->connect_thr, SIGINT);
723                 g_print("connection was cancelled.\n");
724         }
725 #endif
726
727         session->pop3_state->inc_state = INC_CANCEL;
728         pop3_automaton_terminate(sockinfo->sock, session->atm);
729 }
730
731 static gint inc_spool(void)
732 {
733         gchar *mbox, *logname;
734         gint msgs;
735
736         logname = g_get_user_name();
737         mbox = g_strconcat(prefs_common.spool_path
738                            ? prefs_common.spool_path : DEFAULT_SPOOL_PATH,
739                            G_DIR_SEPARATOR_S, logname, NULL);
740         msgs = get_spool(folder_get_default_inbox(), mbox);
741         g_free(mbox);
742
743         return msgs;
744 }
745
746 static gint get_spool(FolderItem *dest, const gchar *mbox)
747 {
748         gint msgs, size;
749         gint lockfd;
750         gchar *tmp_mbox = "/tmp/tmpmbox";
751         GHashTable *folder_table = NULL;
752
753         g_return_val_if_fail(dest != NULL, -1);
754         g_return_val_if_fail(mbox != NULL, -1);
755
756         if (!is_file_exist(mbox) || (size = get_file_size(mbox)) == 0) {
757                 debug_print(_("no messages in local mailbox.\n"));
758                 return 0;
759         } else if (size < 0)
760                 return -1;
761
762         if ((lockfd = lock_mbox(mbox, LOCK_FLOCK)) < 0)
763                 return -1;
764
765         if (copy_mbox(mbox, tmp_mbox) < 0)
766                 return -1;
767
768         debug_print(_("Getting new messages from %s into %s...\n"),
769                     mbox, dest->path);
770
771         if (prefs_common.filter_on_inc)
772                 folder_table = g_hash_table_new(NULL, NULL);
773         msgs = proc_mbox(dest, tmp_mbox, folder_table);
774
775         unlink(tmp_mbox);
776         if (msgs >= 0) empty_mbox(mbox);
777         unlock_mbox(mbox, lockfd, LOCK_FLOCK);
778
779         if (folder_table) {
780                 folder_item_scan_foreach(folder_table);
781                 folderview_update_item_foreach(folder_table);
782                 g_hash_table_destroy(folder_table);
783         } else {
784                 folder_item_scan(dest);
785                 folderview_update_item(dest, FALSE);
786         }
787
788         return msgs;
789 }