Statistics
| Revision:

root / src / main.c @ 3217

History | View | Annotate | Download (47.1 kB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2013 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/gtkrc.h>
30
#include <gtk/gtkstock.h>
31
#include <gtk/gtkaccelmap.h>
32
33
#include <stdio.h>
34
#include <stdlib.h>
35
#include <string.h>
36
#include <ctype.h>
37
#include <unistd.h>
38
#include <time.h>
39
#include <sys/stat.h>
40
#include <sys/types.h>
41
#ifdef G_OS_UNIX
42
#  include <signal.h>
43
#endif
44
45
#if HAVE_LOCALE_H
46
#  include <locale.h>
47
#endif
48
49
#if USE_GPGME
50
#  include <gpgme.h>
51
#endif
52
53
#include "main.h"
54
#include "mainwindow.h"
55
#include "folderview.h"
56
#include "summaryview.h"
57
#include "prefs_common.h"
58
#include "prefs_account.h"
59
#include "prefs_actions.h"
60
#include "prefs_display_header.h"
61
#include "account.h"
62
#include "account_dialog.h"
63
#include "procmsg.h"
64
#include "procheader.h"
65
#include "filter.h"
66
#include "send_message.h"
67
#include "inc.h"
68
#include "manage_window.h"
69
#include "alertpanel.h"
70
#include "inputdialog.h"
71
#include "statusbar.h"
72
#include "addressbook.h"
73
#include "addrindex.h"
74
#include "compose.h"
75
#include "logwindow.h"
76
#include "folder.h"
77
#include "setup.h"
78
#include "sylmain.h"
79
#include "utils.h"
80
#include "gtkutils.h"
81
#include "socket.h"
82
#include "stock_pixmap.h"
83
#include "trayicon.h"
84
#include "notificationwindow.h"
85
#include "plugin.h"
86
#include "plugin_manager.h"
87
#include "foldersel.h"
88
#include "update_check.h"
89
#include "colorlabel.h"
90
91
#if USE_GPGME
92
#  include "rfc2015.h"
93
#endif
94
#if USE_SSL
95
#  include "ssl.h"
96
#  include "sslmanager.h"
97
#endif
98
99
#ifdef G_OS_WIN32
100
#  include <windows.h>
101
#  include <pbt.h>
102
#  include <fcntl.h>
103
#  include <conio.h>
104
#endif
105
106
#include "version.h"
107
108
gchar *prog_version;
109
110
#ifdef G_OS_WIN32
111
static gboolean init_console_done = FALSE;
112
#endif
113
114
static gint lock_socket = -1;
115
static gint lock_socket_tag = 0;
116
static GIOChannel *lock_ch = NULL;
117
static gchar *instance_id = NULL;
118
119
#if USE_THREADS
120
static GThread *main_thread;
121
#endif
122
123
static struct RemoteCmd {
124
        gboolean receive;
125
        gboolean receive_all;
126
        gboolean compose;
127
        const gchar *compose_mailto;
128
        GPtrArray *attach_files;
129
        gboolean send;
130
        gboolean status;
131
        gboolean status_full;
132
        GPtrArray *status_folders;
133
        GPtrArray *status_full_folders;
134
        gchar *open_msg;
135
        gboolean configdir;
136
        gboolean safe_mode;
137
        gboolean exit;
138
        gboolean restart;
139
        gchar *argv0;
140
#ifdef G_OS_WIN32
141
        gushort ipcport;
142
#endif
143
} cmd;
144
145
#define STATUSBAR_PUSH(mainwin, str) \
146
{ \
147
        gtk_statusbar_push(GTK_STATUSBAR(mainwin->statusbar), \
148
                           mainwin->mainwin_cid, str); \
149
        gtkut_widget_draw_now(mainwin->statusbar); \
150
}
151
152
#define STATUSBAR_POP(mainwin) \
153
{ \
154
        gtk_statusbar_pop(GTK_STATUSBAR(mainwin->statusbar), \
155
                          mainwin->mainwin_cid); \
156
}
157
158
#if defined(G_OS_WIN32) || defined(__APPLE__)
159
static void fix_font_setting                (void);
160
#endif
161
162
static void parse_cmd_opt                (int                 argc,
163
                                         char                *argv[]);
164
165
static void app_init                        (void);
166
static void parse_gtkrc_files                (void);
167
static void setup_rc_dir                (void);
168
static void check_gpg                        (void);
169
static void set_log_handlers                (gboolean         enable);
170
static void register_system_events        (void);
171
static void plugin_init                        (void);
172
173
static gchar *get_socket_name                (void);
174
static gint prohibit_duplicate_launch        (void);
175
static gint lock_socket_remove                (void);
176
static gboolean lock_socket_input_cb        (GIOChannel        *source,
177
                                         GIOCondition         condition,
178
                                         gpointer         data);
179
180
static void remote_command_exec                (void);
181
182
#if !defined(G_OS_WIN32) && !defined(__APPLE__)
183
static void migrate_old_config                (void);
184
#endif
185
186
static void open_compose_new                (const gchar        *address,
187
                                         GPtrArray        *attach_files);
188
static void open_message                (const gchar        *path);
189
190
static void send_queue                        (void);
191
192
#define MAKE_DIR_IF_NOT_EXIST(dir)                                        \
193
{                                                                        \
194
        if (!is_dir_exist(dir)) {                                        \
195
                if (is_file_exist(dir)) {                                \
196
                        alertpanel_warning                                \
197
                                (_("File `%s' already exists.\n"        \
198
                                   "Can't create folder."),                \
199
                                 dir);                                        \
200
                        exit(1);                                        \
201
                }                                                        \
202
                if (make_dir(dir) < 0)                                        \
203
                        exit(1);                                        \
204
        }                                                                \
205
}
206
207
#define CHDIR_EXIT_IF_FAIL(dir, val)        \
208
{                                        \
209
        if (change_dir(dir) < 0)        \
210
                exit(val);                \
211
}
212
213
static void load_cb(GObject *obj, GModule *module, gpointer data)
214
{
215
        debug_print("load_cb: %p (%s), %p\n", module, module ? g_module_name(module) : "(null)", data);
216
}
217
218
int main(int argc, char *argv[])
219
{
220
        MainWindow *mainwin;
221
        FolderView *folderview;
222
        GdkPixbuf *icon;
223
#ifdef G_OS_WIN32
224
        GList *iconlist = NULL;
225
#endif
226
        GObject *syl_app;
227
        PrefsAccount *new_account = NULL;
228
        gboolean first_run = FALSE;
229
230
        app_init();
231
        parse_cmd_opt(argc, argv);
232
233
        /* check and create (unix domain) socket for remote operation */
234
        lock_socket = prohibit_duplicate_launch();
235
        if (lock_socket < 0) return 0;
236
237
        if (cmd.status || cmd.status_full) {
238
                puts("0 Sylpheed not running.");
239
                lock_socket_remove();
240
                return 0;
241
        }
242
243
#if USE_THREADS
244
        gdk_threads_enter();
245
#endif
246
        gtk_set_locale();
247
        gtk_init(&argc, &argv);
248
249
        syl_app = syl_app_create();
250
251
        gdk_rgb_init();
252
        gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
253
        gtk_widget_set_default_visual(gdk_rgb_get_visual());
254
255
        parse_gtkrc_files();
256
        setup_rc_dir();
257
258
        if (is_file_exist("sylpheed.log")) {
259
                if (rename_force("sylpheed.log", "sylpheed.log.bak") < 0)
260
                        FILE_OP_ERROR("sylpheed.log", "rename");
261
        }
262
        set_log_file("sylpheed.log");
263
264
        set_ui_update_func(gtkut_events_flush);
265
        set_progress_func(main_window_progress_show);
266
        set_input_query_password_func(input_dialog_query_password);
267
#if USE_SSL
268
        ssl_init();
269
        ssl_set_verify_func(ssl_manager_verify_cert);
270
#endif
271
272
        CHDIR_EXIT_IF_FAIL(get_home_dir(), 1);
273
274
        prefs_common_read_config();
275
        filter_set_addressbook_func(addressbook_has_address);
276
        filter_read_config();
277
        prefs_actions_read_config();
278
        prefs_display_header_read_config();
279
        colorlabel_read_config();
280
281
        prefs_common.user_agent_str = g_strdup_printf
282
                ("%s (GTK+ %d.%d.%d; %s)",
283
                 prog_version,
284
                 gtk_major_version, gtk_minor_version, gtk_micro_version,
285
                 TARGET_ALIAS);
286
287
#if defined(G_OS_WIN32) || defined(__APPLE__)
288
        fix_font_setting();
289
#endif
290
291
        gtkut_stock_button_set_set_reverse(!prefs_common.comply_gnome_hig);
292
293
        check_gpg();
294
295
        sock_set_io_timeout(prefs_common.io_timeout_secs);
296
297
        gtkut_widget_init();
298
299
#ifdef G_OS_WIN32
300
        stock_pixbuf_gdk(NULL, STOCK_PIXMAP_SYLPHEED_32, &icon);
301
        iconlist = g_list_append(iconlist, icon);
302
        stock_pixbuf_gdk(NULL, STOCK_PIXMAP_SYLPHEED_SMALL, &icon);
303
        iconlist = g_list_append(iconlist, icon);
304
        gtk_window_set_default_icon_list(iconlist);
305
        g_list_free(iconlist);
306
#else
307
        stock_pixbuf_gdk(NULL, STOCK_PIXMAP_SYLPHEED, &icon);
308
        gtk_window_set_default_icon(icon);
309
#endif
310
311
        mainwin = main_window_create
312
                (prefs_common.sep_folder | prefs_common.sep_msg << 1);
313
        folderview = mainwin->folderview;
314
315
        /* register the callback of socket input */
316
        if (lock_socket > 0) {
317
                lock_ch = g_io_channel_unix_new(lock_socket);
318
                lock_socket_tag = g_io_add_watch(lock_ch,
319
                                                 G_IO_IN|G_IO_PRI|G_IO_ERR,
320
                                                 lock_socket_input_cb, mainwin);
321
        }
322
323
        set_log_handlers(TRUE);
324
325
        account_read_config_all();
326
        account_set_menu();
327
        main_window_reflect_prefs_all();
328
329
        if (folder_read_list() < 0) {
330
                first_run = TRUE;
331
                setup_mailbox();
332
                folder_write_list();
333
        }
334
        if (!account_get_list()) {
335
                new_account = setup_account();
336
        }
337
338
        account_set_menu();
339
        main_window_reflect_prefs_all();
340
341
        account_set_missing_folder();
342
        folder_set_missing_folders();
343
        folderview_set(folderview);
344
        if (new_account && new_account->folder)
345
                folder_write_list();
346
347
        addressbook_read_file();
348
349
        register_system_events();
350
351
        inc_autocheck_timer_init(mainwin);
352
353
        plugin_init();
354
355
        g_signal_emit_by_name(syl_app, "init-done");
356
357
        if (first_run) {
358
                setup_import_data();
359
                setup_import_addressbook();
360
        }
361
362
        remote_command_exec();
363
364
#if USE_UPDATE_CHECK
365
        if (prefs_common.auto_update_check)
366
                update_check(FALSE);
367
#endif
368
369
        gtk_main();
370
#if USE_THREADS
371
        gdk_threads_leave();
372
#endif
373
374
        return 0;
375
}
376
377
static void init_console(void)
378
{
379
#ifdef G_OS_WIN32
380
        gint fd;
381
        FILE *fp;
382
383
        if (init_console_done)
384
                return;
385
386
        if (!AllocConsole()) {
387
                g_warning("AllocConsole() failed\n");
388
                return;
389
        }
390
391
        fd = _open_osfhandle((glong)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
392
        _dup2(fd, 1);
393
        fp = _fdopen(fd, "w");
394
        *stdout = *fp;
395
        setvbuf(stdout, NULL, _IONBF, 0);
396
        fd = _open_osfhandle((glong)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT);
397
        _dup2(fd, 2);
398
        fp = _fdopen(fd, "w");
399
        *stderr = *fp;
400
        setvbuf(stderr, NULL, _IONBF, 0);
401
402
        init_console_done = TRUE;
403
#endif
404
}
405
406
static void cleanup_console(void)
407
{
408
#ifdef G_OS_WIN32
409
        FreeConsole();
410
#endif
411
}
412
413
#ifdef G_OS_WIN32
414
static void read_ini_file(void)
415
{
416
        static gushort ipcport = REMOTE_CMD_PORT;
417
        static gchar *confdir = NULL;
418
419
        static PrefParam param[] = {
420
                {"ipcport", "50215", &ipcport, P_USHORT},
421
                {"configdir", NULL, &confdir, P_STRING},
422
423
                {NULL, NULL, NULL, P_OTHER}
424
        };
425
426
        gchar *file;
427
428
        file = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, "sylpheed.ini",
429
                           NULL);
430
        if (!is_file_exist(file)) {
431
                g_free(file);
432
                return;
433
        }
434
435
        prefs_read_config(param, "Sylpheed", file,
436
                          conv_get_locale_charset_str());
437
        g_free(file);
438
439
        cmd.ipcport = ipcport;
440
        if (confdir) {
441
                set_rc_dir(confdir);
442
                g_free(confdir);
443
                confdir = NULL;
444
                cmd.configdir = TRUE;
445
        }
446
}
447
#endif /* G_OS_WIN32 */
448
449
#if defined(G_OS_WIN32) || defined(__APPLE__)
450
static void fix_font_setting(void)
451
{
452
        const gchar *str = NULL;
453
454
        if (!conv_is_ja_locale())
455
                return;
456
457
        if (prefs_common.textfont &&
458
            strcmp(prefs_common.textfont, DEFAULT_MESSAGE_FONT) != 0) {
459
                if (gtkut_font_can_load(prefs_common.textfont)) {
460
                        debug_print("font '%s' load ok\n", prefs_common.textfont);
461
                        return;
462
                }
463
                debug_print("font '%s' load failed\n", prefs_common.textfont);
464
        }
465
466
        debug_print("fixing prefs_common.textfont setting\n");
467
468
#ifdef G_OS_WIN32
469
        str = "MS Gothic 12";
470
#else /* __APPLE__ */
471
        str = "Hiragino Kaku Gothic Pro Light 13";
472
#endif
473
474
        if (!gtkut_font_can_load(str)) {
475
#ifdef G_OS_WIN32
476
                debug_print("font '%s' load failed\n", str);
477
                str = "\xef\xbc\xad\xef\xbc\xb3 \xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf 12";
478
                if (!gtkut_font_can_load(str)) {
479
                        debug_print("font '%s' load failed\n", str);
480
                        str = NULL;
481
                }
482
#else /* __APPLE__ */
483
                debug_print("font '%s' load failed\n", str);
484
                str = NULL;
485
#endif
486
        }
487
488
        if (str) {
489
                debug_print("font '%s' load ok\n", str);
490
                g_free(prefs_common.textfont);
491
                prefs_common.textfont = g_strdup(str);
492
        } else
493
                g_warning("failed to load text font!");
494
}
495
#endif
496
497
static void parse_cmd_opt(int argc, char *argv[])
498
{
499
        gint i;
500
501
        for (i = 1; i < argc; i++) {
502
                if (!strncmp(argv[i], "--debug", 7)) {
503
                        init_console();
504
                        set_debug_mode(TRUE);
505
                } else if (!strncmp(argv[i], "--receive-all", 13))
506
                        cmd.receive_all = TRUE;
507
                else if (!strncmp(argv[i], "--receive", 9))
508
                        cmd.receive = TRUE;
509
                else if (!strncmp(argv[i], "--compose", 9)) {
510
                        const gchar *p = argv[i + 1];
511
512
                        cmd.compose = TRUE;
513
                        cmd.compose_mailto = NULL;
514
                        if (p && *p != '\0' && *p != '-') {
515
                                if (!strncmp(p, "mailto:", 7))
516
                                        cmd.compose_mailto = p + 7;
517
                                else
518
                                        cmd.compose_mailto = p;
519
                                i++;
520
                        }
521
                } else if (!strncmp(argv[i], "--attach", 8)) {
522
                        const gchar *p = argv[i + 1];
523
                        gchar *file;
524
525
                        while (p && *p != '\0' && *p != '-') {
526
                                if (!cmd.attach_files)
527
                                        cmd.attach_files = g_ptr_array_new();
528
                                if (!g_path_is_absolute(p))
529
                                        file = g_strconcat(get_startup_dir(),
530
                                                           G_DIR_SEPARATOR_S,
531
                                                           p, NULL);
532
                                else
533
                                        file = g_strdup(p);
534
                                g_ptr_array_add(cmd.attach_files, file);
535
                                i++;
536
                                p = argv[i + 1];
537
                        }
538
                } else if (!strncmp(argv[i], "--send", 6)) {
539
                        cmd.send = TRUE;
540
                } else if (!strncmp(argv[i], "--version", 9)) {
541
                        puts("Sylpheed version " VERSION);
542
                        exit(0);
543
                } else if (!strncmp(argv[i], "--status-full", 13)) {
544
                        const gchar *p = argv[i + 1];
545
546
                        cmd.status_full = TRUE;
547
                        while (p && *p != '\0' && *p != '-') {
548
                                if (!cmd.status_full_folders)
549
                                        cmd.status_full_folders =
550
                                                g_ptr_array_new();
551
                                g_ptr_array_add(cmd.status_full_folders,
552
                                                g_strdup(p));
553
                                i++;
554
                                p = argv[i + 1];
555
                        }
556
                } else if (!strncmp(argv[i], "--status", 8)) {
557
                        const gchar *p = argv[i + 1];
558
559
                        cmd.status = TRUE;
560
                        while (p && *p != '\0' && *p != '-') {
561
                                if (!cmd.status_folders)
562
                                        cmd.status_folders = g_ptr_array_new();
563
                                g_ptr_array_add(cmd.status_folders,
564
                                                g_strdup(p));
565
                                i++;
566
                                p = argv[i + 1];
567
                        }
568
                } else if (!strncmp(argv[i], "--open", 6)) {
569
                        const gchar *p = argv[i + 1];
570
571
                        if (p && *p != '\0' && *p != '-') {
572
                                if (cmd.open_msg)
573
                                        g_free(cmd.open_msg);
574
                                cmd.open_msg = g_locale_to_utf8
575
                                        (p, -1, NULL, NULL, NULL);
576
                                i++;
577
                        }
578
                } else if (!strncmp(argv[i], "--configdir", 11)) {
579
                        const gchar *p = argv[i + 1];
580
581
                        if (p && *p != '\0' && *p != '-') {
582
                                /* this must only be done at startup */
583
#ifdef G_OS_WIN32
584
                                gchar *utf8dir;
585
586
                                utf8dir = g_locale_to_utf8
587
                                        (p, -1, NULL, NULL, NULL);
588
                                if (utf8dir) {
589
                                        set_rc_dir(utf8dir);
590
                                        g_free(utf8dir);
591
                                } else
592
                                        set_rc_dir(p);
593
#else
594
                                set_rc_dir(p);
595
#endif
596
                                cmd.configdir = TRUE;
597
                                i++;
598
                        }
599
#ifdef G_OS_WIN32
600
                } else if (!strncmp(argv[i], "--ipcport", 9)) {
601
                        if (argv[i + 1]) {
602
                                cmd.ipcport = atoi(argv[i + 1]);
603
                                i++;
604
                        }
605
#endif
606
                } else if (!strncmp(argv[i], "--instance-id", 13)) {
607
                        if (argv[i + 1]) {
608
                                instance_id = g_locale_to_utf8
609
                                        (argv[i + 1], -1, NULL, NULL, NULL);
610
                                i++;
611
                        }
612
                } else if (!strncmp(argv[i], "--safe-mode", 11)) {
613
                        cmd.safe_mode = TRUE;
614
                } else if (!strncmp(argv[i], "--exit", 6)) {
615
                        cmd.exit = TRUE;
616
                } else if (!strncmp(argv[i], "--help", 6)) {
617
                        init_console();
618
619
                        g_print(_("Usage: %s [OPTIONS ...] [URL]\n"),
620
                                g_basename(argv[0]));
621
622
                        g_print("%s\n", _("  --compose [mailto URL] open composition window"));
623
                        g_print("%s\n", _("  --attach file1 [file2]...\n"
624
                                "                         open composition window with specified files\n"
625
                                "                         attached"));
626
                        g_print("%s\n", _("  --receive              receive new messages"));
627
                        g_print("%s\n", _("  --receive-all          receive new messages of all accounts"));
628
                        g_print("%s\n", _("  --send                 send all queued messages"));
629
                        g_print("%s\n", _("  --status [folder]...   show the total number of messages"));
630
                        g_print("%s\n", _("  --status-full [folder]...\n"
631
                                "                         show the status of each folder"));
632
                        g_print("%s\n", _("  --open folderid/msgnum open existing message in a new window"));
633
                        g_print("%s\n", _("  --open <file URL>      open an rfc822 message file in a new window"));
634
                        g_print("%s\n", _("  --configdir dirname    specify directory which stores configuration files"));
635
#ifdef G_OS_WIN32
636
                        g_print("%s\n", _("  --ipcport portnum      specify port for IPC remote commands"));
637
#endif
638
                        g_print("%s\n", _("  --exit                 exit Sylpheed"));
639
                        g_print("%s\n", _("  --debug                debug mode"));
640
                        g_print("%s\n", _("  --safe-mode            safe mode"));
641
                        g_print("%s\n", _("  --help                 display this help and exit"));
642
                        g_print("%s\n", _("  --version              output version information and exit"));
643
644
#ifdef G_OS_WIN32
645
                        g_print("\n");
646
                        g_print(_("Press any key..."));
647
                        _getch();
648
#endif
649
650
                        cleanup_console();
651
                        exit(1);
652
                } else {
653
                        /* file or URL */
654
                        const gchar *p = argv[i];
655
656
                        if (p && *p != '\0') {
657
                                if (!strncmp(p, "mailto:", 7)) {
658
                                        cmd.compose = TRUE;
659
                                        cmd.compose_mailto = p + 7;
660
                                } else {
661
                                        if (cmd.open_msg)
662
                                                g_free(cmd.open_msg);
663
                                        cmd.open_msg = g_locale_to_utf8
664
                                                (p, -1, NULL, NULL, NULL);
665
                                }
666
                        }
667
                }
668
        }
669
670
        if (cmd.attach_files && cmd.compose == FALSE) {
671
                cmd.compose = TRUE;
672
                cmd.compose_mailto = NULL;
673
        }
674
675
        cmd.argv0 = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
676
        if (!cmd.argv0)
677
                cmd.argv0 = g_strdup(argv[0]);
678
}
679
680
static gint get_queued_message_num(void)
681
{
682
        FolderItem *queue;
683
684
        queue = folder_get_default_queue();
685
        if (!queue) return -1;
686
687
        folder_item_scan(queue);
688
        return queue->total;
689
}
690
691
#if USE_THREADS
692
/* enables recursive locking with gdk_thread_enter / gdk_threads_leave */
693
static GStaticRecMutex syl_mutex = G_STATIC_REC_MUTEX_INIT;
694
695
static void thread_enter_func(void)
696
{
697
        g_static_rec_mutex_lock(&syl_mutex);
698
#if 0
699
        syl_mutex_lock_count++;
700
        if (syl_mutex_lock_count > 1)
701
                g_print("enter: syl_mutex_lock_count: %d\n", syl_mutex_lock_count);
702
#endif
703
}
704
705
static void thread_leave_func(void)
706
{
707
#if 0
708
        syl_mutex_lock_count--;
709
        if (syl_mutex_lock_count > 0)
710
                g_print("leave: syl_mutex_lock_count: %d\n", syl_mutex_lock_count);
711
#endif
712
        g_static_rec_mutex_unlock(&syl_mutex);
713
}
714
715
static void event_loop_iteration_func(void)
716
{
717
        if (g_thread_self() != main_thread) {
718
                g_fprintf(stderr, "event_loop_iteration_func called from non-main thread (%p)\n", g_thread_self());
719
                g_usleep(10000);
720
                return;
721
        }
722
        gtk_main_iteration();
723
}
724
#endif
725
726
static void app_init(void)
727
{
728
#if USE_THREADS
729
        if (!g_thread_supported())
730
                g_thread_init(NULL);
731
        if (!g_thread_supported())
732
                g_error("g_thread is not supported by glib.");
733
        else {
734
                gdk_threads_set_lock_functions(thread_enter_func,
735
                                               thread_leave_func);
736
                gdk_threads_init();
737
                main_thread = g_thread_self();
738
        }
739
#endif
740
        syl_init();
741
742
#if USE_THREADS
743
        set_event_loop_func(event_loop_iteration_func);
744
#endif
745
        prog_version = PROG_VERSION;
746
747
#ifdef G_OS_WIN32
748
        read_ini_file();
749
#endif
750
}
751
752
static void parse_gtkrc_files(void)
753
{
754
        gchar *userrc;
755
756
        /* parse gtkrc files */
757
        userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtkrc-2.0",
758
                             NULL);
759
        gtk_rc_parse(userrc);
760
        g_free(userrc);
761
        userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtk",
762
                             G_DIR_SEPARATOR_S, "gtkrc-2.0", NULL);
763
        gtk_rc_parse(userrc);
764
        g_free(userrc);
765
        userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, "gtkrc", NULL);
766
        gtk_rc_parse(userrc);
767
        g_free(userrc);
768
769
        userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
770
        gtk_accel_map_load(userrc);
771
        g_free(userrc);
772
}
773
774
static void setup_rc_dir(void)
775
{
776
#if !defined(G_OS_WIN32) && !defined(__APPLE__)
777
        CHDIR_EXIT_IF_FAIL(get_home_dir(), 1);
778
779
        /* backup if old rc file exists */
780
        if (!cmd.configdir && is_file_exist(RC_DIR)) {
781
                if (rename_force(RC_DIR, RC_DIR ".bak") < 0)
782
                        FILE_OP_ERROR(RC_DIR, "rename");
783
        }
784
785
        /* migration from ~/.sylpheed to ~/.sylpheed-2.0 */
786
        if (!cmd.configdir && !is_dir_exist(RC_DIR)) {
787
                const gchar *envstr;
788
                AlertValue val;
789
790
                /* check for filename encoding */
791
                if (conv_get_locale_charset() != C_UTF_8) {
792
                        envstr = g_getenv("G_FILENAME_ENCODING");
793
                        if (!envstr)
794
                                envstr = g_getenv("G_BROKEN_FILENAMES");
795
                        if (!envstr) {
796
                                val = alertpanel(_("Filename encoding"),
797
                                                 _("The locale encoding is not UTF-8, but the environmental variable G_FILENAME_ENCODING is not set.\n"
798
                                                   "If the locale encoding is used for file name or directory name, it will not work correctly.\n"
799
                                                   "In that case, you must set the following environmental variable (see README for detail):\n"
800
                                                   "\n"
801
                                                   "\tG_FILENAME_ENCODING=@locale\n"
802
                                                   "\n"
803
                                                   "Continue?"),
804
                                                 GTK_STOCK_OK, GTK_STOCK_QUIT,
805
                                                 NULL);
806
                                if (G_ALERTDEFAULT != val)
807
                                        exit(1);
808
                        }
809
                }
810
811
                if (make_dir(RC_DIR) < 0)
812
                        exit(1);
813
                if (is_dir_exist(OLD_RC_DIR))
814
                        migrate_old_config();
815
        }
816
#endif /* !G_OS_WIN32 && !__APPLE__ */
817
818
        syl_setup_rc_dir();
819
}
820
821
static void app_restart(void)
822
{
823
        gchar *cmdline;
824
        GError *error = NULL;
825
#ifdef G_OS_WIN32
826
        if (cmd.configdir) {
827
                cmdline = g_strdup_printf("\"%s\"%s --configdir \"%s\" --ipcport %d",
828
                                          cmd.argv0,
829
                                          get_debug_mode() ? " --debug" : "",
830
                                          get_rc_dir(),
831
                                          cmd.ipcport);
832
        } else {
833
                cmdline = g_strdup_printf("\"%s\"%s --ipcport %d",
834
                                          cmd.argv0,
835
                                          get_debug_mode() ? " --debug" : "",
836
                                          cmd.ipcport);
837
        }
838
#else
839
        if (cmd.configdir) {
840
                cmdline = g_strdup_printf("\"%s\"%s --configdir \"%s\"",
841
                                          cmd.argv0,
842
                                          get_debug_mode() ? " --debug" : "",
843
                                          get_rc_dir());
844
        } else {
845
                cmdline = g_strdup_printf("\"%s\"%s",
846
                                          cmd.argv0,
847
                                          get_debug_mode() ? " --debug" : "");
848
        }
849
#endif
850
        if (!g_spawn_command_line_async(cmdline, &error)) {
851
                alertpanel_error("restart failed\n'%s'\n%s", cmdline, error->message);
852
                g_error_free(error);
853
        }
854
        g_free(cmdline);
855
}
856
857
void app_will_restart(gboolean force)
858
{
859
        cmd.restart = TRUE;
860
        app_will_exit(force);
861
        /* canceled */
862
        cmd.restart = FALSE;
863
}
864
865
void app_will_exit(gboolean force)
866
{
867
        MainWindow *mainwin;
868
        gchar *filename;
869
        static gboolean on_exit = FALSE;
870
        GList *cur;
871
872
        if (on_exit)
873
                return;
874
        on_exit = TRUE;
875
876
        mainwin = main_window_get();
877
878
        if (!force && compose_get_compose_list()) {
879
                if (alertpanel(_("Notice"),
880
                               _("Composing message exists. Really quit?"),
881
                               GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL)
882
                    != G_ALERTDEFAULT) {
883
                        on_exit = FALSE;
884
                        return;
885
                }
886
                manage_window_focus_in(mainwin->window, NULL, NULL);
887
        }
888
889
        if (!force &&
890
            prefs_common.warn_queued_on_exit && get_queued_message_num() > 0) {
891
                if (alertpanel(_("Queued messages"),
892
                               _("Some unsent messages are queued. Exit now?"),
893
                               GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL)
894
                    != G_ALERTDEFAULT) {
895
                        on_exit = FALSE;
896
                        return;
897
                }
898
                manage_window_focus_in(mainwin->window, NULL, NULL);
899
        }
900
901
        if (force)
902
                g_signal_emit_by_name(syl_app_get(), "app-force-exit");
903
        g_signal_emit_by_name(syl_app_get(), "app-exit");
904
905
        inc_autocheck_timer_remove();
906
907
        if (prefs_common.clean_on_exit)
908
                main_window_empty_trash(mainwin,
909
                                        !force && prefs_common.ask_on_clean);
910
911
        for (cur = account_get_list(); cur != NULL; cur = cur->next) {
912
                PrefsAccount *ac = (PrefsAccount *)cur->data;
913
                if (ac->protocol == A_IMAP4 && ac->imap_clear_cache_on_exit &&
914
                    ac->folder)
915
                        procmsg_remove_all_cached_messages(FOLDER(ac->folder));
916
        }
917
918
        syl_plugin_unload_all();
919
920
        trayicon_destroy(mainwin->tray_icon);
921
922
        /* save all state before exiting */
923
        summary_write_cache(mainwin->summaryview);
924
        main_window_get_size(mainwin);
925
        main_window_get_position(mainwin);
926
        syl_save_all_state();
927
        addressbook_export_to_file();
928
929
        filename = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
930
        gtk_accel_map_save(filename);
931
        g_free(filename);
932
933
        /* remove temporary files, close log file, socket cleanup */
934
#if USE_SSL
935
        ssl_done();
936
#endif
937
        syl_cleanup();
938
        lock_socket_remove();
939
940
#ifdef USE_UPDATE_CHECK_PLUGIN
941
#ifdef G_OS_WIN32
942
        cur = gtk_window_list_toplevels();
943
        g_list_foreach(cur, (GFunc)gtk_widget_hide, NULL);
944
        g_list_free(cur);
945
        update_check_spawn_plugin_updater();
946
#endif
947
#endif
948
949
        cleanup_console();
950
951
        if (gtk_main_level() > 0)
952
                gtk_main_quit();
953
954
        if (cmd.restart)
955
                app_restart();
956
957
        exit(0);
958
}
959
960
#if 0
961
#if USE_GPGME
962
static void idle_function_for_gpgme(void)
963
{
964
        while (gtk_events_pending())
965
                gtk_main_iteration();
966
}
967
#endif /* USE_GPGME */
968
#endif /* 0 */
969
970
static void check_gpg(void)
971
{
972
#if USE_GPGME
973
        const gchar *version;
974
        gpgme_error_t err = 0;
975
976
        version = gpgme_check_version("1.0.0");
977
        if (version) {
978
                debug_print("GPGME Version: %s\n", version);
979
                err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
980
                if (err)
981
                        debug_print("gpgme_engine_check_version: %s\n",
982
                                    gpgme_strerror(err));
983
        }
984
985
        if (version && !err) {
986
                /* Also does some gpgme init */
987
                gpgme_engine_info_t engineInfo;
988
989
#if HAVE_LOCALE_H
990
                gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
991
                gpgme_set_locale(NULL, LC_MESSAGES,
992
                                 setlocale(LC_MESSAGES, NULL));
993
#endif
994
995
                if (!gpgme_get_engine_info(&engineInfo)) {
996
                        while (engineInfo) {
997
                                debug_print("GPGME Protocol: %s\n      Version: %s\n",
998
                                            gpgme_get_protocol_name
999
                                                (engineInfo->protocol),
1000
                                            engineInfo->version ?
1001
                                            engineInfo->version : "(unknown)");
1002
                                engineInfo = engineInfo->next;
1003
                        }
1004
                }
1005
1006
                procmsg_set_decrypt_message_func
1007
                        (rfc2015_open_message_decrypted);
1008
                procmsg_set_auto_decrypt_message(TRUE);
1009
        } else {
1010
                rfc2015_disable_all();
1011
1012
                if (prefs_common.gpg_warning) {
1013
                        AlertValue val;
1014
1015
                        val = alertpanel_message_with_disable
1016
                                (_("Warning"),
1017
                                 _("GnuPG is not installed properly, or its version is too old.\n"
1018
                                   "OpenPGP support disabled."),
1019
                                 ALERT_WARNING);
1020
                        if (val & G_ALERTDISABLE)
1021
                                prefs_common.gpg_warning = FALSE;
1022
                }
1023
        }
1024
        /* FIXME: This function went away.  We can either block until gpgme
1025
         * operations finish (currently implemented) or register callbacks
1026
         * with the gtk main loop via the gpgme io callback interface instead.
1027
         *
1028
         * gpgme_register_idle(idle_function_for_gpgme);
1029
         */
1030
#endif
1031
}
1032
1033
static void default_log_func(const gchar *log_domain, GLogLevelFlags log_level,
1034
                             const gchar *message, gpointer user_data)
1035
{
1036
        gchar *prefix = "";
1037
        gchar *file_prefix = "";
1038
        LogType level = LOG_NORMAL;
1039
        gchar *str;
1040
        const gchar *message_;
1041
1042
        switch (log_level) {
1043
        case G_LOG_LEVEL_ERROR:
1044
                prefix = "ERROR";
1045
                file_prefix = "*** ";
1046
                level = LOG_ERROR;
1047
                break;
1048
        case G_LOG_LEVEL_CRITICAL:
1049
                prefix = "CRITICAL";
1050
                file_prefix = "** ";
1051
                level = LOG_WARN;
1052
                break;
1053
        case G_LOG_LEVEL_WARNING:
1054
                prefix = "WARNING";
1055
                file_prefix = "** ";
1056
                level = LOG_WARN;
1057
                break;
1058
        case G_LOG_LEVEL_MESSAGE:
1059
                prefix = "Message";
1060
                file_prefix = "* ";
1061
                level = LOG_MSG;
1062
                break;
1063
        case G_LOG_LEVEL_INFO:
1064
                prefix = "INFO";
1065
                file_prefix = "* ";
1066
                level = LOG_MSG;
1067
                break;
1068
        case G_LOG_LEVEL_DEBUG:
1069
                prefix = "DEBUG";
1070
                break;
1071
        default:
1072
                prefix = "LOG";
1073
                break;
1074
        }
1075
1076
        if (!message)
1077
                message_ = "(NULL) message";
1078
        else
1079
                message_ = message;
1080
        if (log_domain)
1081
                str = g_strconcat(log_domain, "-", prefix, ": ", message_, "\n",
1082
                                  NULL);
1083
        else
1084
                str = g_strconcat(prefix, ": ", message_, "\n", NULL);
1085
        log_window_append(str, level);
1086
        log_write(str, file_prefix);
1087
        g_free(str);
1088
1089
        g_log_default_handler(log_domain, log_level, message, user_data);
1090
}
1091
1092
static void set_log_handlers(gboolean enable)
1093
{
1094
#if GLIB_CHECK_VERSION(2, 6, 0)
1095
        if (enable)
1096
                g_log_set_default_handler(default_log_func, NULL);
1097
        else
1098
                g_log_set_default_handler(g_log_default_handler, NULL);
1099
#else
1100
        static guint handler_id[4] = {0, 0, 0, 0};
1101
1102
        if (enable) {
1103
                handler_id[0] = g_log_set_handler
1104
                        ("GLib", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1105
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1106
                handler_id[1] = g_log_set_handler
1107
                        ("Gtk", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1108
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1109
                handler_id[2] = g_log_set_handler
1110
                        ("LibSylph", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1111
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1112
                handler_id[3] = g_log_set_handler
1113
                        ("Sylpheed", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1114
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1115
        } else {
1116
                g_log_remove_handler("GLib", handler_id[0]);
1117
                g_log_remove_handler("Gtk", handler_id[1]);
1118
                g_log_remove_handler("LibSylph", handler_id[2]);
1119
                g_log_remove_handler("Sylpheed", handler_id[3]);
1120
                handler_id[0] = 0;
1121
                handler_id[1] = 0;
1122
                handler_id[2] = 0;
1123
                handler_id[3] = 0;
1124
        }
1125
#endif
1126
}
1127
1128
#ifdef G_OS_WIN32
1129
static BOOL WINAPI
1130
ctrl_handler(DWORD dwctrltype)
1131
{
1132
        log_print("ctrl_handler: received %d\n", dwctrltype);
1133
        app_will_exit(TRUE);
1134
1135
        return TRUE;
1136
}
1137
1138
static LRESULT CALLBACK
1139
wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
1140
{
1141
        switch (message) {
1142
        case WM_POWERBROADCAST:
1143
                debug_print("WM_POWERBROADCAST received: wparam = %d\n",
1144
                            wparam);
1145
                if (wparam == PBT_APMSUSPEND || wparam == PBT_APMSTANDBY) {
1146
                        debug_print("suspend now\n");
1147
                        inc_autocheck_timer_remove();
1148
                } else if (wparam == PBT_APMRESUMESUSPEND ||
1149
                           wparam == PBT_APMRESUMESTANDBY) {
1150
                        debug_print("resume now\n");
1151
                        inc_autocheck_timer_set();
1152
                }
1153
                break;
1154
        case WM_ENDSESSION:
1155
                if (wparam == 1) {
1156
                        log_print("WM_ENDSESSION received: system is quitting\n");
1157
                        app_will_exit(TRUE);
1158
                }
1159
                break;
1160
        default:
1161
                break;
1162
        }
1163
1164
        return DefWindowProc(hwnd, message, wparam, lparam);
1165
}
1166
1167
static void register_system_events(void)
1168
{
1169
        WNDCLASS wclass;
1170
        static HWND hwnd = NULL;
1171
        static BOOL ctrl_handler_set = FALSE;
1172
        ATOM klass;
1173
        HINSTANCE hmodule = GetModuleHandle(NULL);
1174
1175
        if (init_console_done && !ctrl_handler_set) {
1176
                debug_print("register_system_events(): SetConsoleCtrlHandler\n");
1177
                ctrl_handler_set = SetConsoleCtrlHandler(ctrl_handler, TRUE);
1178
                if (!ctrl_handler_set)
1179
                        g_warning("SetConsoleCtrlHandler() failed\n");
1180
        }
1181
1182
        if (hwnd)
1183
                return;
1184
1185
        debug_print("register_system_events(): RegisterClass\n");
1186
1187
        memset(&wclass, 0, sizeof(WNDCLASS));
1188
        wclass.lpszClassName = "sylpheed-observer";
1189
        wclass.lpfnWndProc   = wndproc;
1190
        wclass.hInstance     = hmodule;
1191
1192
        klass = RegisterClass(&wclass);
1193
        if (!klass)
1194
                return;
1195
1196
        hwnd = CreateWindow(MAKEINTRESOURCE(klass), NULL, WS_POPUP,
1197
                            0, 0, 1, 1, NULL, NULL, hmodule, NULL);
1198
        if (!hwnd)
1199
                UnregisterClass(MAKEINTRESOURCE(klass), hmodule);
1200
}
1201
#else /* G_OS_WIN32 */
1202
static void sig_handler(gint signum)
1203
{
1204
        debug_print("signal %d received\n", signum);
1205
1206
        switch (signum) {
1207
        case SIGHUP:
1208
        case SIGINT:
1209
        case SIGTERM:
1210
        case SIGQUIT:
1211
                app_will_exit(TRUE);
1212
                break;
1213
        default:
1214
                break;
1215
        }
1216
}
1217
1218
static void register_system_events(void)
1219
{
1220
        struct sigaction sa;
1221
1222
        memset(&sa, 0, sizeof(sa));
1223
        sa.sa_handler = sig_handler;
1224
        sa.sa_flags = SA_RESTART;
1225
1226
        sigemptyset(&sa.sa_mask);
1227
        sigaddset(&sa.sa_mask, SIGHUP);
1228
        sigaddset(&sa.sa_mask, SIGINT);
1229
        sigaddset(&sa.sa_mask, SIGTERM);
1230
        sigaddset(&sa.sa_mask, SIGQUIT);
1231
        sigaddset(&sa.sa_mask, SIGPIPE);
1232
1233
        sigaction(SIGHUP, &sa, NULL);
1234
        sigaction(SIGINT, &sa, NULL);
1235
        sigaction(SIGTERM, &sa, NULL);
1236
        sigaction(SIGQUIT, &sa, NULL);
1237
        sigaction(SIGPIPE, &sa, NULL);
1238
}
1239
#endif
1240
1241
#define ADD_SYM(sym)        syl_plugin_add_symbol(#sym, sym)
1242
1243
static void plugin_init(void)
1244
{
1245
        MainWindow *mainwin;
1246
        gchar *path;
1247
1248
        mainwin = main_window_get();
1249
1250
        STATUSBAR_PUSH(mainwin, _("Loading plug-ins..."));
1251
1252
        if (syl_plugin_init_lib() != 0) {
1253
                STATUSBAR_POP(mainwin);
1254
                return;
1255
        }
1256
1257
        if (cmd.safe_mode) {
1258
                debug_print("plugin_init: safe mode enabled, skipping plug-in loading.\n");
1259
                STATUSBAR_POP(mainwin);
1260
                return;
1261
        }
1262
1263
        ADD_SYM(prog_version);
1264
        ADD_SYM(app_will_exit);
1265
1266
        ADD_SYM(main_window_lock);
1267
        ADD_SYM(main_window_unlock);
1268
        ADD_SYM(main_window_get);
1269
        ADD_SYM(main_window_popup);
1270
1271
        syl_plugin_add_symbol("main_window_menu_factory",
1272
                              mainwin->menu_factory);
1273
        syl_plugin_add_symbol("main_window_statusbar", mainwin->statusbar);
1274
1275
        ADD_SYM(folderview_get);
1276
        ADD_SYM(folderview_add_sub_widget);
1277
        ADD_SYM(folderview_select);
1278
        ADD_SYM(folderview_unselect);
1279
        ADD_SYM(folderview_select_next_unread);
1280
        ADD_SYM(folderview_get_selected_item);
1281
        ADD_SYM(folderview_check_new);
1282
        ADD_SYM(folderview_check_new_item);
1283
        ADD_SYM(folderview_check_new_all);
1284
        ADD_SYM(folderview_update_item);
1285
        ADD_SYM(folderview_update_item_foreach);
1286
        ADD_SYM(folderview_update_all_updated);
1287
        ADD_SYM(folderview_check_new_selected);
1288
1289
        syl_plugin_add_symbol("folderview_mail_popup_factory",
1290
                              mainwin->folderview->mail_factory);
1291
        syl_plugin_add_symbol("folderview_imap_popup_factory",
1292
                              mainwin->folderview->imap_factory);
1293
        syl_plugin_add_symbol("folderview_news_popup_factory",
1294
                              mainwin->folderview->news_factory);
1295
1296
        syl_plugin_add_symbol("summaryview", mainwin->summaryview);
1297
        syl_plugin_add_symbol("summaryview_popup_factory",
1298
                              mainwin->summaryview->popupfactory);
1299
1300
        ADD_SYM(summary_select_by_msgnum);
1301
        ADD_SYM(summary_select_by_msginfo);
1302
        ADD_SYM(summary_lock);
1303
        ADD_SYM(summary_unlock);
1304
        ADD_SYM(summary_is_locked);
1305
        ADD_SYM(summary_is_read_locked);
1306
        ADD_SYM(summary_write_lock);
1307
        ADD_SYM(summary_write_unlock);
1308
        ADD_SYM(summary_is_write_locked);
1309
        ADD_SYM(summary_get_current_folder);
1310
        ADD_SYM(summary_get_selection_type);
1311
        ADD_SYM(summary_get_selected_msg_list);
1312
        ADD_SYM(summary_get_msg_list);
1313
        ADD_SYM(summary_show_queued_msgs);
1314
        ADD_SYM(summary_redisplay_msg);
1315
        ADD_SYM(summary_open_msg);
1316
        ADD_SYM(summary_view_source);
1317
        ADD_SYM(summary_reedit);
1318
        ADD_SYM(summary_update_selected_rows);
1319
        ADD_SYM(summary_update_by_msgnum);
1320
1321
        ADD_SYM(messageview_create_with_new_window);
1322
        ADD_SYM(messageview_show);
1323
1324
        ADD_SYM(compose_new);
1325
        ADD_SYM(compose_entry_set);
1326
        ADD_SYM(compose_entry_append);
1327
        ADD_SYM(compose_entry_get_text);
1328
        ADD_SYM(compose_lock);
1329
        ADD_SYM(compose_unlock);
1330
1331
        ADD_SYM(foldersel_folder_sel);
1332
        ADD_SYM(foldersel_folder_sel_full);
1333
1334
        ADD_SYM(input_dialog);
1335
        ADD_SYM(input_dialog_with_invisible);
1336
1337
        ADD_SYM(manage_window_set_transient);
1338
        ADD_SYM(manage_window_signals_connect);
1339
        ADD_SYM(manage_window_get_focus_window);
1340
1341
        ADD_SYM(inc_mail);
1342
        ADD_SYM(inc_is_active);
1343
        ADD_SYM(inc_lock);
1344
        ADD_SYM(inc_unlock);
1345
1346
#if USE_UPDATE_CHECK
1347
        ADD_SYM(update_check);
1348
        ADD_SYM(update_check_set_check_url);
1349
        ADD_SYM(update_check_get_check_url);
1350
        ADD_SYM(update_check_set_download_url);
1351
        ADD_SYM(update_check_get_download_url);
1352
        ADD_SYM(update_check_set_jump_url);
1353
        ADD_SYM(update_check_get_jump_url);
1354
#ifdef USE_UPDATE_CHECK_PLUGIN
1355
        ADD_SYM(update_check_set_check_plugin_url);
1356
        ADD_SYM(update_check_get_check_plugin_url);
1357
        ADD_SYM(update_check_set_jump_plugin_url);
1358
        ADD_SYM(update_check_get_jump_plugin_url);
1359
#endif /* USE_UPDATE_CHECK_PLUGIN */
1360
#endif
1361
1362
        ADD_SYM(alertpanel_full);
1363
        ADD_SYM(alertpanel);
1364
        ADD_SYM(alertpanel_message);
1365
        ADD_SYM(alertpanel_message_with_disable);
1366
1367
        ADD_SYM(send_message);
1368
        ADD_SYM(send_message_queue_all);
1369
        ADD_SYM(send_message_set_reply_flag);
1370
        ADD_SYM(send_message_set_forward_flags);
1371
1372
        ADD_SYM(notification_window_open);
1373
        ADD_SYM(notification_window_set_message);
1374
        ADD_SYM(notification_window_close);
1375
1376
        syl_plugin_signal_connect("plugin-load", G_CALLBACK(load_cb), NULL);
1377
1378
        /* loading plug-ins from user plug-in directory */
1379
        path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, PLUGIN_DIR, NULL);
1380
        syl_plugin_load_all(path);
1381
        g_free(path);
1382
1383
        /* loading plug-ins from system plug-in directory */
1384
#ifdef G_OS_WIN32
1385
        path = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, PLUGIN_DIR,
1386
                           NULL);
1387
        syl_plugin_load_all(path);
1388
        g_free(path);
1389
#else
1390
        syl_plugin_load_all(PLUGINDIR);
1391
#endif
1392
1393
        STATUSBAR_POP(mainwin);
1394
}
1395
1396
static gchar *get_socket_name(void)
1397
{
1398
        static gchar *filename = NULL;
1399
1400
        if (filename == NULL) {
1401
                filename = g_strdup_printf("%s%c%s-%d",
1402
                                           g_get_tmp_dir(), G_DIR_SEPARATOR,
1403
                                           instance_id ? instance_id : "sylpheed",
1404
#if HAVE_GETUID
1405
                                           getuid());
1406
#else
1407
                                           0);
1408
#endif
1409
        }
1410
1411
        return filename;
1412
}
1413
1414
static gint prohibit_duplicate_launch(void)
1415
{
1416
        gint sock;
1417
1418
#ifdef G_OS_WIN32
1419
        HANDLE hmutex;
1420
        const gchar *ins_id = instance_id ? instance_id : "Sylpheed";
1421
        gushort port = cmd.ipcport ? cmd.ipcport : REMOTE_CMD_PORT;
1422
1423
        debug_print("prohibit_duplicate_launch: checking mutex: %s\n", ins_id);
1424
        hmutex = CreateMutexA(NULL, FALSE, ins_id);
1425
        if (!hmutex) {
1426
                g_warning("cannot create Mutex: %s\n", ins_id);
1427
                return -1;
1428
        }
1429
        if (GetLastError() != ERROR_ALREADY_EXISTS) {
1430
                debug_print("prohibit_duplicate_launch: creating socket: port %d\n", port);
1431
                sock = fd_open_inet(port);
1432
                if (sock < 0)
1433
                        return 0;
1434
                return sock;
1435
        }
1436
1437
        debug_print("prohibit_duplicate_launch: connecting to socket: port %d\n", port);
1438
        sock = fd_connect_inet(port);
1439
        if (sock < 0)
1440
                return -1;
1441
#else
1442
        gchar *path;
1443
1444
        path = get_socket_name();
1445
        debug_print("prohibit_duplicate_launch: checking socket: %s\n", path);
1446
        sock = fd_connect_unix(path);
1447
        if (sock < 0) {
1448
                debug_print("prohibit_duplicate_launch: creating socket: %s\n", path);
1449
                g_unlink(path);
1450
                return fd_open_unix(path);
1451
        }
1452
#endif
1453
1454
        /* remote command mode */
1455
1456
        debug_print(_("another Sylpheed is already running.\n"));
1457
1458
        if (cmd.receive_all)
1459
                fd_write_all(sock, "receive_all\n", 12);
1460
        else if (cmd.receive)
1461
                fd_write_all(sock, "receive\n", 8);
1462
        else if (cmd.compose && cmd.attach_files) {
1463
                gchar *str, *compose_str;
1464
                gint i;
1465
1466
                if (cmd.compose_mailto)
1467
                        compose_str = g_strdup_printf("compose_attach %s\n",
1468
                                                      cmd.compose_mailto);
1469
                else
1470
                        compose_str = g_strdup("compose_attach\n");
1471
1472
                fd_write_all(sock, compose_str, strlen(compose_str));
1473
                g_free(compose_str);
1474
1475
                for (i = 0; i < cmd.attach_files->len; i++) {
1476
                        str = g_ptr_array_index(cmd.attach_files, i);
1477
                        fd_write_all(sock, str, strlen(str));
1478
                        fd_write_all(sock, "\n", 1);
1479
                }
1480
1481
                fd_write_all(sock, ".\n", 2);
1482
        } else if (cmd.compose) {
1483
                gchar *compose_str;
1484
1485
                if (cmd.compose_mailto)
1486
                        compose_str = g_strdup_printf
1487
                                ("compose %s\n", cmd.compose_mailto);
1488
                else
1489
                        compose_str = g_strdup("compose\n");
1490
1491
                fd_write_all(sock, compose_str, strlen(compose_str));
1492
                g_free(compose_str);
1493
        } else if (cmd.send) {
1494
                fd_write_all(sock, "send\n", 5);
1495
        } else if (cmd.status || cmd.status_full) {
1496
                gchar buf[BUFFSIZE];
1497
                gint i;
1498
                const gchar *command;
1499
                GPtrArray *folders;
1500
                gchar *folder;
1501
1502
                command = cmd.status_full ? "status-full\n" : "status\n";
1503
                folders = cmd.status_full ? cmd.status_full_folders :
1504
                        cmd.status_folders;
1505
1506
                fd_write_all(sock, command, strlen(command));
1507
                for (i = 0; folders && i < folders->len; ++i) {
1508
                        folder = g_ptr_array_index(folders, i);
1509
                        fd_write_all(sock, folder, strlen(folder));
1510
                        fd_write_all(sock, "\n", 1);
1511
                }
1512
                fd_write_all(sock, ".\n", 2);
1513
                for (;;) {
1514
                        fd_gets(sock, buf, sizeof(buf));
1515
                        if (!strncmp(buf, ".\n", 2)) break;
1516
                        fputs(buf, stdout);
1517
                }
1518
        } else if (cmd.open_msg) {
1519
                gchar *str;
1520
1521
                str = g_strdup_printf("open %s\n", cmd.open_msg);
1522
                fd_write_all(sock, str, strlen(str));
1523
                g_free(str);
1524
        } else if (cmd.exit) {
1525
                fd_write_all(sock, "exit\n", 5);
1526
        } else {
1527
#ifdef G_OS_WIN32
1528
                HWND hwnd;
1529
1530
                fd_write_all(sock, "popup\n", 6);
1531
                if (fd_read(sock, (gchar *)&hwnd, sizeof(hwnd)) == sizeof(hwnd))
1532
                        SetForegroundWindow(hwnd);
1533
#else
1534
                fd_write_all(sock, "popup\n", 6);
1535
#endif
1536
        }
1537
1538
        fd_close(sock);
1539
        return -1;
1540
}
1541
1542
static gint lock_socket_remove(void)
1543
{
1544
#ifndef G_OS_WIN32
1545
        gchar *filename;
1546
#endif
1547
1548
        if (lock_socket < 0) return -1;
1549
1550
        if (lock_socket_tag > 0)
1551
                g_source_remove(lock_socket_tag);
1552
        if (lock_ch) {
1553
                g_io_channel_shutdown(lock_ch, FALSE, NULL);
1554
                g_io_channel_unref(lock_ch);
1555
                lock_ch = NULL;
1556
        }
1557
1558
#ifndef G_OS_WIN32
1559
        filename = get_socket_name();
1560
        debug_print("lock_socket_remove: removing socket: %s\n", filename);
1561
        g_unlink(filename);
1562
#endif
1563
1564
        return 0;
1565
}
1566
1567
static GPtrArray *get_folder_item_list(gint sock)
1568
{
1569
        gchar buf[BUFFSIZE];
1570
        FolderItem *item;
1571
        GPtrArray *folders = NULL;
1572
1573
        for (;;) {
1574
                fd_gets(sock, buf, sizeof(buf));
1575
                if (!strncmp(buf, ".\n", 2)) break;
1576
                strretchomp(buf);
1577
                if (!folders) folders = g_ptr_array_new();
1578
                item = folder_find_item_from_identifier(buf);
1579
                if (item)
1580
                        g_ptr_array_add(folders, item);
1581
                else
1582
                        g_warning("no such folder: %s\n", buf);
1583
        }
1584
1585
        return folders;
1586
}
1587
1588
static gboolean lock_socket_input_cb(GIOChannel *source, GIOCondition condition,
1589
                                     gpointer data)
1590
{
1591
        MainWindow *mainwin = (MainWindow *)data;
1592
        gint fd, sock;
1593
        gchar buf[BUFFSIZE];
1594
1595
#if USE_THREADS
1596
        gdk_threads_enter();
1597
#endif
1598
1599
        fd = g_io_channel_unix_get_fd(source);
1600
        sock = fd_accept(fd);
1601
        fd_gets(sock, buf, sizeof(buf));
1602
1603
        if (!strncmp(buf, "popup", 5)) {
1604
#ifdef G_OS_WIN32
1605
                HWND hwnd;
1606
1607
                hwnd = (HWND)gdk_win32_drawable_get_handle
1608
                        (GDK_DRAWABLE(mainwin->window->window));
1609
                fd_write(sock, (gchar *)&hwnd, sizeof(hwnd));
1610
                if (mainwin->window_hidden)
1611
                        main_window_popup(mainwin);
1612
#else
1613
                main_window_popup(mainwin);
1614
#endif
1615
        } else if (!strncmp(buf, "receive_all", 11)) {
1616
                main_window_popup(mainwin);
1617
                if (!gtkut_window_modal_exist())
1618
                        inc_all_account_mail(mainwin, FALSE);
1619
        } else if (!strncmp(buf, "receive", 7)) {
1620
                main_window_popup(mainwin);
1621
                if (!gtkut_window_modal_exist())
1622
                        inc_mail(mainwin);
1623
        } else if (!strncmp(buf, "compose_attach", 14)) {
1624
                GPtrArray *files;
1625
                gchar *mailto;
1626
1627
                mailto = g_strdup(buf + strlen("compose_attach") + 1);
1628
                files = g_ptr_array_new();
1629
                while (fd_gets(sock, buf, sizeof(buf)) > 0) {
1630
                        if (buf[0] == '.' && buf[1] == '\n') break;
1631
                        strretchomp(buf);
1632
                        g_ptr_array_add(files, g_strdup(buf));
1633
                }
1634
                open_compose_new(mailto, files);
1635
                ptr_array_free_strings(files);
1636
                g_ptr_array_free(files, TRUE);
1637
                g_free(mailto);
1638
        } else if (!strncmp(buf, "compose", 7)) {
1639
                open_compose_new(buf + strlen("compose") + 1, NULL);
1640
        } else if (!strncmp(buf, "send", 4)) {
1641
                send_queue();
1642
        } else if (!strncmp(buf, "status-full", 11) ||
1643
                   !strncmp(buf, "status", 6)) {
1644
                gchar *status;
1645
                GPtrArray *folders;
1646
1647
                folders = get_folder_item_list(sock);
1648
                status = folder_get_status
1649
                        (folders, !strncmp(buf, "status-full", 11));
1650
                fd_write_all(sock, status, strlen(status));
1651
                fd_write_all(sock, ".\n", 2);
1652
                g_free(status);
1653
                if (folders) g_ptr_array_free(folders, TRUE);
1654
        } else if (!strncmp(buf, "open", 4)) {
1655
                strretchomp(buf);
1656
                if (strlen(buf) < 6 || buf[4] != ' ') {
1657
                        fd_close(sock);
1658
#if USE_THREADS
1659
                        gdk_threads_leave();
1660
#endif
1661
                        return TRUE;
1662
                }
1663
                open_message(buf + 5);
1664
        } else if (!strncmp(buf, "exit", 4)) {
1665
                fd_close(sock);
1666
                app_will_exit(TRUE);
1667
        }
1668
1669
        fd_close(sock);
1670
1671
#if USE_THREADS
1672
        gdk_threads_leave();
1673
#endif
1674
1675
        return TRUE;
1676
}
1677
1678
static void remote_command_exec(void)
1679
{
1680
        MainWindow *mainwin;
1681
1682
        mainwin = main_window_get();
1683
1684
        if (prefs_common.open_inbox_on_startup) {
1685
                FolderItem *item;
1686
                PrefsAccount *ac;
1687
1688
                ac = account_get_default();
1689
                if (!ac)
1690
                        ac = cur_account;
1691
                item = ac && ac->inbox
1692
                        ? folder_find_item_from_identifier(ac->inbox)
1693
                        : folder_get_default_inbox();
1694
                folderview_select(mainwin->folderview, item);
1695
        }
1696
1697
        if (!gtkut_window_modal_exist()) {
1698
                if (cmd.compose)
1699
                        open_compose_new(cmd.compose_mailto, cmd.attach_files);
1700
1701
                if (cmd.open_msg)
1702
                        open_message(cmd.open_msg);
1703
1704
                if (cmd.receive_all)
1705
                        inc_all_account_mail(mainwin, FALSE);
1706
                else if (prefs_common.chk_on_startup)
1707
                        inc_all_account_mail(mainwin, TRUE);
1708
                else if (cmd.receive)
1709
                        inc_mail(mainwin);
1710
1711
                if (cmd.send)
1712
                        send_queue();
1713
        }
1714
1715
        if (cmd.attach_files) {
1716
                ptr_array_free_strings(cmd.attach_files);
1717
                g_ptr_array_free(cmd.attach_files, TRUE);
1718
                cmd.attach_files = NULL;
1719
        }
1720
        if (cmd.status_folders) {
1721
                g_ptr_array_free(cmd.status_folders, TRUE);
1722
                cmd.status_folders = NULL;
1723
        }
1724
        if (cmd.status_full_folders) {
1725
                g_ptr_array_free(cmd.status_full_folders, TRUE);
1726
                cmd.status_full_folders = NULL;
1727
        }
1728
        if (cmd.open_msg) {
1729
                g_free(cmd.open_msg);
1730
                cmd.open_msg = NULL;
1731
        }
1732
        if (cmd.exit) {
1733
                app_will_exit(TRUE);
1734
        }
1735
}
1736
1737
#if !defined(G_OS_WIN32) && !defined(__APPLE__)
1738
static void migrate_old_config(void)
1739
{
1740
        GDir *dir;
1741
        const gchar *dir_name;
1742
        GPatternSpec *pspec;
1743
1744
        if (alertpanel(_("Migration of configuration"),
1745
                       _("The previous version of configuration found.\n"
1746
                         "Do you want to migrate it?"),
1747
                       GTK_STOCK_YES, GTK_STOCK_NO, NULL) != G_ALERTDEFAULT)
1748
                return;
1749
1750
        debug_print("Migrating old configuration...\n");
1751
1752
#define COPY_FILE(rcfile)                                                \
1753
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile)) {        \
1754
                conv_copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile,        \
1755
                               RC_DIR G_DIR_SEPARATOR_S rcfile,                \
1756
                               conv_get_locale_charset_str());                \
1757
        }
1758
1759
        COPY_FILE(ACCOUNT_RC);
1760
        COPY_FILE(ACTIONS_RC);
1761
        COPY_FILE(COMMON_RC);
1762
        COPY_FILE(CUSTOM_HEADER_RC);
1763
        COPY_FILE(DISPLAY_HEADER_RC);
1764
        COPY_FILE(FILTER_HEADER_RC);
1765
        COPY_FILE(COMMAND_HISTORY);
1766
1767
#undef COPY_FILE
1768
1769
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST))
1770
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST,
1771
                          RC_DIR G_DIR_SEPARATOR_S FILTER_LIST, FALSE);
1772
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST))
1773
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST,
1774
                          RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST, FALSE);
1775
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types"))
1776
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types",
1777
                          RC_DIR G_DIR_SEPARATOR_S "mime.types", FALSE);
1778
1779
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR))
1780
                conv_copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1781
                              RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1782
                              conv_get_locale_charset_str());
1783
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR))
1784
                copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR,
1785
                         RC_DIR G_DIR_SEPARATOR_S UIDL_DIR);
1786
1787
        if (!is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S ADDRESSBOOK_INDEX_FILE))
1788
                return;
1789
1790
        if ((dir = g_dir_open(OLD_RC_DIR, 0, NULL)) == NULL) {
1791
                g_warning("failed to open directory: %s\n", OLD_RC_DIR);
1792
                return;
1793
        }
1794
1795
        pspec = g_pattern_spec_new("addrbook-*.xml");
1796
1797
        while ((dir_name = g_dir_read_name(dir)) != NULL) {
1798
                if (g_pattern_match_string(pspec, dir_name)) {
1799
                        gchar *old_file;
1800
                        gchar *new_file;
1801
1802
                        old_file = g_strconcat(OLD_RC_DIR G_DIR_SEPARATOR_S,
1803
                                               dir_name, NULL);
1804
                        new_file = g_strconcat(RC_DIR G_DIR_SEPARATOR_S,
1805
                                               dir_name, NULL);
1806
                        copy_file(old_file, new_file, FALSE);
1807
                        g_free(new_file);
1808
                        g_free(old_file);
1809
                }
1810
        }
1811
1812
        g_pattern_spec_free(pspec);
1813
        g_dir_close(dir);
1814
}
1815
#endif /* !G_OS_WIN32 && !__APPLE__ */
1816
1817
static void open_compose_new(const gchar *address, GPtrArray *attach_files)
1818
{
1819
        gchar *utf8addr = NULL;
1820
#ifdef G_OS_WIN32
1821
        GPtrArray *utf8files = NULL;
1822
#endif
1823
1824
        if (gtkut_window_modal_exist())
1825
                return;
1826
1827
        if (address) {
1828
                utf8addr = g_locale_to_utf8(address, -1, NULL, NULL, NULL);
1829
                if (utf8addr)
1830
                        g_strstrip(utf8addr);
1831
                debug_print("open compose: %s\n", utf8addr ? utf8addr : "");
1832
        }
1833
1834
#ifdef G_OS_WIN32
1835
        if (attach_files) {
1836
                gint i;
1837
                gchar *file, *utf8file;
1838
1839
                utf8files = g_ptr_array_new();
1840
                for (i = 0; i < attach_files->len; i++) {
1841
                        file = g_ptr_array_index(attach_files, i);
1842
                        utf8file = g_locale_to_utf8(file, -1, NULL, NULL, NULL);
1843
                        if (utf8file)
1844
                                g_ptr_array_add(utf8files, utf8file);
1845
                }
1846
        }
1847
1848
        compose_new(NULL, NULL, utf8addr, utf8files);
1849
        if (utf8files) {
1850
                ptr_array_free_strings(utf8files);
1851
                g_ptr_array_free(utf8files, TRUE);
1852
        }
1853
#else
1854
        compose_new(NULL, NULL, utf8addr, attach_files);
1855
#endif
1856
1857
        g_free(utf8addr);
1858
}
1859
1860
static void open_message_file(const gchar *file)
1861
{
1862
        MsgInfo *msginfo;
1863
        MsgFlags flags = {0};
1864
        MessageView *msgview;
1865
1866
        g_return_if_fail(file != NULL);
1867
1868
        debug_print("open message file: %s\n", file);
1869
1870
        if (!is_file_exist(file) || get_file_size(file) <= 0) {
1871
                debug_print("file not found: %s\n", file);
1872
                return;
1873
        }
1874
1875
        msginfo = procheader_parse_file(file, flags, FALSE);
1876
        if (msginfo) {
1877
                msginfo->file_path = g_strdup(file);
1878
                msgview = messageview_create_with_new_window();
1879
                messageview_show(msgview, msginfo, FALSE);
1880
                procmsg_msginfo_free(msginfo);
1881
        } else
1882
                debug_print("cannot open message: %s\n", file);
1883
}
1884
1885
static void open_message(const gchar *path)
1886
{
1887
        gchar *fid;
1888
        gchar *msg;
1889
        gint num;
1890
        FolderItem *item;
1891
        MsgInfo *msginfo;
1892
        MessageView *msgview;
1893
        gchar *file;
1894
1895
        g_return_if_fail(path != NULL);
1896
1897
        if (gtkut_window_modal_exist())
1898
                return;
1899
1900
        debug_print("open message: %s\n", path);
1901
1902
        if (!strncmp(path, "file:", 5)) {
1903
                file = g_filename_from_uri(path, NULL, NULL);
1904
                open_message_file(file);
1905
                g_free(file);
1906
                return;
1907
        } else if (g_path_is_absolute(path)) {
1908
                open_message_file(path);
1909
                return;
1910
        }
1911
1912
        /* relative path, or folder identifier */
1913
1914
        fid = g_path_get_dirname(path);
1915
        msg = g_path_get_basename(path);
1916
        num = to_number(msg);
1917
        item = folder_find_item_from_identifier(fid);
1918
1919
        if (num > 0 && item) {
1920
                debug_print("open folder id: %s (msg %d)\n", fid, num);
1921
                msginfo = folder_item_get_msginfo(item, num);
1922
                if (msginfo) {
1923
                        msgview = messageview_create_with_new_window();
1924
                        messageview_show(msgview, msginfo, FALSE);
1925
                        procmsg_msginfo_free(msginfo);
1926
                        g_free(msg);
1927
                        g_free(fid);
1928
                        return;
1929
                } else
1930
                        debug_print("message %d not found\n", num);
1931
        }
1932
1933
        g_free(msg);
1934
        g_free(fid);
1935
1936
        /* relative path */
1937
1938
        file = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, path, NULL);
1939
        open_message_file(file);
1940
        g_free(file);
1941
}
1942
1943
static void send_queue(void)
1944
{
1945
        GList *list;
1946
1947
        if (gtkut_window_modal_exist())
1948
                return;
1949
        if (!main_window_toggle_online_if_offline(main_window_get()))
1950
                return;
1951
1952
        for (list = folder_get_list(); list != NULL; list = list->next) {
1953
                Folder *folder = list->data;
1954
1955
                if (folder->queue) {
1956
                        gint ret;
1957
1958
                        ret = send_message_queue_all(folder->queue,
1959
                                                     prefs_common.savemsg,
1960
                                                     prefs_common.filter_sent);
1961
                        statusbar_pop_all();
1962
                        if (ret > 0)
1963
                                folder_item_scan(folder->queue);
1964
                }
1965
        }
1966
1967
        folderview_update_all_updated(TRUE);
1968
        main_window_set_menu_sensitive(main_window_get());
1969
        main_window_set_toolbar_sensitive(main_window_get());
1970
}