Statistics
| Revision:

root / src / main.c @ 3193

History | View | Annotate | Download (46.8 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 "plugin.h"
85
#include "plugin_manager.h"
86
#include "foldersel.h"
87
#include "update_check.h"
88
#include "colorlabel.h"
89

    
90
#if USE_GPGME
91
#  include "rfc2015.h"
92
#endif
93
#if USE_SSL
94
#  include "ssl.h"
95
#  include "sslmanager.h"
96
#endif
97

    
98
#ifdef G_OS_WIN32
99
#  include <windows.h>
100
#  include <pbt.h>
101
#  include <fcntl.h>
102
#  include <conio.h>
103
#endif
104

    
105
#include "version.h"
106

    
107
gchar *prog_version;
108

    
109
#ifdef G_OS_WIN32
110
static gboolean init_console_done = FALSE;
111
#endif
112

    
113
static gint lock_socket = -1;
114
static gint lock_socket_tag = 0;
115
static GIOChannel *lock_ch = NULL;
116
static gchar *instance_id = NULL;
117

    
118
#if USE_THREADS
119
static GThread *main_thread;
120
#endif
121

    
122
static struct RemoteCmd {
123
        gboolean receive;
124
        gboolean receive_all;
125
        gboolean compose;
126
        const gchar *compose_mailto;
127
        GPtrArray *attach_files;
128
        gboolean send;
129
        gboolean status;
130
        gboolean status_full;
131
        GPtrArray *status_folders;
132
        GPtrArray *status_full_folders;
133
        gchar *open_msg;
134
        gboolean configdir;
135
        gboolean safe_mode;
136
        gboolean exit;
137
        gboolean restart;
138
        gchar *argv0;
139
#ifdef G_OS_WIN32
140
        gushort ipcport;
141
#endif
142
} cmd;
143

    
144
#define STATUSBAR_PUSH(mainwin, str) \
145
{ \
146
        gtk_statusbar_push(GTK_STATUSBAR(mainwin->statusbar), \
147
                           mainwin->mainwin_cid, str); \
148
        gtkut_widget_draw_now(mainwin->statusbar); \
149
}
150

    
151
#define STATUSBAR_POP(mainwin) \
152
{ \
153
        gtk_statusbar_pop(GTK_STATUSBAR(mainwin->statusbar), \
154
                          mainwin->mainwin_cid); \
155
}
156

    
157
#if defined(G_OS_WIN32) || defined(__APPLE__)
158
static void fix_font_setting                (void);
159
#endif
160

    
161
static void parse_cmd_opt                (int                 argc,
162
                                         char                *argv[]);
163

    
164
static void app_init                        (void);
165
static void parse_gtkrc_files                (void);
166
static void setup_rc_dir                (void);
167
static void check_gpg                        (void);
168
static void set_log_handlers                (gboolean         enable);
169
static void register_system_events        (void);
170
static void plugin_init                        (void);
171

    
172
static gchar *get_socket_name                (void);
173
static gint prohibit_duplicate_launch        (void);
174
static gint lock_socket_remove                (void);
175
static gboolean lock_socket_input_cb        (GIOChannel        *source,
176
                                         GIOCondition         condition,
177
                                         gpointer         data);
178

    
179
static void remote_command_exec                (void);
180

    
181
#if !defined(G_OS_WIN32) && !defined(__APPLE__)
182
static void migrate_old_config                (void);
183
#endif
184

    
185
static void open_compose_new                (const gchar        *address,
186
                                         GPtrArray        *attach_files);
187
static void open_message                (const gchar        *path);
188

    
189
static void send_queue                        (void);
190

    
191
#define MAKE_DIR_IF_NOT_EXIST(dir)                                        \
192
{                                                                        \
193
        if (!is_dir_exist(dir)) {                                        \
194
                if (is_file_exist(dir)) {                                \
195
                        alertpanel_warning                                \
196
                                (_("File `%s' already exists.\n"        \
197
                                   "Can't create folder."),                \
198
                                 dir);                                        \
199
                        exit(1);                                        \
200
                }                                                        \
201
                if (make_dir(dir) < 0)                                        \
202
                        exit(1);                                        \
203
        }                                                                \
204
}
205

    
206
#define CHDIR_EXIT_IF_FAIL(dir, val)        \
207
{                                        \
208
        if (change_dir(dir) < 0)        \
209
                exit(val);                \
210
}
211

    
212
static void load_cb(GObject *obj, GModule *module, gpointer data)
213
{
214
        debug_print("load_cb: %p (%s), %p\n", module, module ? g_module_name(module) : "(null)", data);
215
}
216

    
217
int main(int argc, char *argv[])
218
{
219
        MainWindow *mainwin;
220
        FolderView *folderview;
221
        GdkPixbuf *icon;
222
#ifdef G_OS_WIN32
223
        GList *iconlist = NULL;
224
#endif
225
        GObject *syl_app;
226
        PrefsAccount *new_account = NULL;
227
        gboolean first_run = FALSE;
228

    
229
        app_init();
230
        parse_cmd_opt(argc, argv);
231

    
232
        /* check and create (unix domain) socket for remote operation */
233
        lock_socket = prohibit_duplicate_launch();
234
        if (lock_socket < 0) return 0;
235

    
236
        if (cmd.status || cmd.status_full) {
237
                puts("0 Sylpheed not running.");
238
                lock_socket_remove();
239
                return 0;
240
        }
241

    
242
#if USE_THREADS
243
        gdk_threads_enter();
244
#endif
245
        gtk_set_locale();
246
        gtk_init(&argc, &argv);
247

    
248
        syl_app = syl_app_create();
249

    
250
        gdk_rgb_init();
251
        gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
252
        gtk_widget_set_default_visual(gdk_rgb_get_visual());
253

    
254
        parse_gtkrc_files();
255
        setup_rc_dir();
256

    
257
        if (is_file_exist("sylpheed.log")) {
258
                if (rename_force("sylpheed.log", "sylpheed.log.bak") < 0)
259
                        FILE_OP_ERROR("sylpheed.log", "rename");
260
        }
261
        set_log_file("sylpheed.log");
262

    
263
        set_ui_update_func(gtkut_events_flush);
264
        set_progress_func(main_window_progress_show);
265
        set_input_query_password_func(input_dialog_query_password);
266
#if USE_SSL
267
        ssl_init();
268
        ssl_set_verify_func(ssl_manager_verify_cert);
269
#endif
270

    
271
        CHDIR_EXIT_IF_FAIL(get_home_dir(), 1);
272

    
273
        prefs_common_read_config();
274
        filter_set_addressbook_func(addressbook_has_address);
275
        filter_read_config();
276
        prefs_actions_read_config();
277
        prefs_display_header_read_config();
278
        colorlabel_read_config();
279

    
280
        prefs_common.user_agent_str = g_strdup_printf
281
                ("%s (GTK+ %d.%d.%d; %s)",
282
                 prog_version,
283
                 gtk_major_version, gtk_minor_version, gtk_micro_version,
284
                 TARGET_ALIAS);
285

    
286
#if defined(G_OS_WIN32) || defined(__APPLE__)
287
        fix_font_setting();
288
#endif
289

    
290
        gtkut_stock_button_set_set_reverse(!prefs_common.comply_gnome_hig);
291

    
292
        check_gpg();
293

    
294
        sock_set_io_timeout(prefs_common.io_timeout_secs);
295

    
296
        gtkut_widget_init();
297

    
298
#ifdef G_OS_WIN32
299
        stock_pixbuf_gdk(NULL, STOCK_PIXMAP_SYLPHEED_32, &icon);
300
        iconlist = g_list_append(iconlist, icon);
301
        stock_pixbuf_gdk(NULL, STOCK_PIXMAP_SYLPHEED_SMALL, &icon);
302
        iconlist = g_list_append(iconlist, icon);
303
        gtk_window_set_default_icon_list(iconlist);
304
        g_list_free(iconlist);
305
#else
306
        stock_pixbuf_gdk(NULL, STOCK_PIXMAP_SYLPHEED, &icon);
307
        gtk_window_set_default_icon(icon);
308
#endif
309

    
310
        mainwin = main_window_create
311
                (prefs_common.sep_folder | prefs_common.sep_msg << 1);
312
        folderview = mainwin->folderview;
313

    
314
        /* register the callback of socket input */
315
        if (lock_socket > 0) {
316
                lock_ch = g_io_channel_unix_new(lock_socket);
317
                lock_socket_tag = g_io_add_watch(lock_ch,
318
                                                 G_IO_IN|G_IO_PRI|G_IO_ERR,
319
                                                 lock_socket_input_cb, mainwin);
320
        }
321

    
322
        set_log_handlers(TRUE);
323

    
324
        account_read_config_all();
325
        account_set_menu();
326
        main_window_reflect_prefs_all();
327

    
328
        if (folder_read_list() < 0) {
329
                first_run = TRUE;
330
                setup_mailbox();
331
                folder_write_list();
332
        }
333
        if (!account_get_list()) {
334
                new_account = setup_account();
335
        }
336

    
337
        account_set_menu();
338
        main_window_reflect_prefs_all();
339

    
340
        account_set_missing_folder();
341
        folder_set_missing_folders();
342
        folderview_set(folderview);
343
        if (new_account && new_account->folder)
344
                folder_write_list();
345

    
346
        addressbook_read_file();
347

    
348
        register_system_events();
349

    
350
        inc_autocheck_timer_init(mainwin);
351

    
352
        plugin_init();
353

    
354
        g_signal_emit_by_name(syl_app, "init-done");
355

    
356
        if (first_run) {
357
                setup_import_data();
358
                setup_import_addressbook();
359
        }
360

    
361
        remote_command_exec();
362

    
363
#if USE_UPDATE_CHECK
364
        if (prefs_common.auto_update_check)
365
                update_check(FALSE);
366
#endif
367

    
368
        gtk_main();
369
#if USE_THREADS
370
        gdk_threads_leave();
371
#endif
372

    
373
        return 0;
374
}
375

    
376
static void init_console(void)
377
{
378
#ifdef G_OS_WIN32
379
        gint fd;
380
        FILE *fp;
381

    
382
        if (init_console_done)
383
                return;
384

    
385
        if (!AllocConsole()) {
386
                g_warning("AllocConsole() failed\n");
387
                return;
388
        }
389

    
390
        fd = _open_osfhandle((glong)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
391
        _dup2(fd, 1);
392
        fp = _fdopen(fd, "w");
393
        *stdout = *fp;
394
        setvbuf(stdout, NULL, _IONBF, 0);
395
        fd = _open_osfhandle((glong)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT);
396
        _dup2(fd, 2);
397
        fp = _fdopen(fd, "w");
398
        *stderr = *fp;
399
        setvbuf(stderr, NULL, _IONBF, 0);
400

    
401
        init_console_done = TRUE;
402
#endif
403
}
404

    
405
static void cleanup_console(void)
406
{
407
#ifdef G_OS_WIN32
408
        FreeConsole();
409
#endif
410
}
411

    
412
#ifdef G_OS_WIN32
413
static void read_ini_file(void)
414
{
415
        static gushort ipcport = REMOTE_CMD_PORT;
416
        static gchar *confdir = NULL;
417

    
418
        static PrefParam param[] = {
419
                {"ipcport", "50215", &ipcport, P_USHORT},
420
                {"configdir", NULL, &confdir, P_STRING},
421

    
422
                {NULL, NULL, NULL, P_OTHER}
423
        };
424

    
425
        gchar *file;
426

    
427
        file = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, "sylpheed.ini",
428
                           NULL);
429
        if (!is_file_exist(file)) {
430
                g_free(file);
431
                return;
432
        }
433

    
434
        prefs_read_config(param, "Sylpheed", file,
435
                          conv_get_locale_charset_str());
436
        g_free(file);
437

    
438
        cmd.ipcport = ipcport;
439
        if (confdir) {
440
                set_rc_dir(confdir);
441
                g_free(confdir);
442
                confdir = NULL;
443
                cmd.configdir = TRUE;
444
        }
445
}
446
#endif /* G_OS_WIN32 */
447

    
448
#if defined(G_OS_WIN32) || defined(__APPLE__)
449
static void fix_font_setting(void)
450
{
451
        const gchar *str = NULL;
452

    
453
        if (!conv_is_ja_locale())
454
                return;
455

    
456
        if (prefs_common.textfont &&
457
            strcmp(prefs_common.textfont, DEFAULT_MESSAGE_FONT) != 0) {
458
                if (gtkut_font_can_load(prefs_common.textfont)) {
459
                        debug_print("font '%s' load ok\n", prefs_common.textfont);
460
                        return;
461
                }
462
                debug_print("font '%s' load failed\n", prefs_common.textfont);
463
        }
464

    
465
        debug_print("fixing prefs_common.textfont setting\n");
466

    
467
#ifdef G_OS_WIN32
468
        str = "MS Gothic 12";
469
#else /* __APPLE__ */
470
        str = "Hiragino Kaku Gothic Pro Light 13";
471
#endif
472

    
473
        if (!gtkut_font_can_load(str)) {
474
#ifdef G_OS_WIN32
475
                debug_print("font '%s' load failed\n", str);
476
                str = "\xef\xbc\xad\xef\xbc\xb3 \xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf 12";
477
                if (!gtkut_font_can_load(str)) {
478
                        debug_print("font '%s' load failed\n", str);
479
                        str = NULL;
480
                }
481
#else /* __APPLE__ */
482
                debug_print("font '%s' load failed\n", str);
483
                str = NULL;
484
#endif
485
        }
486

    
487
        if (str) {
488
                debug_print("font '%s' load ok\n", str);
489
                g_free(prefs_common.textfont);
490
                prefs_common.textfont = g_strdup(str);
491
        } else
492
                g_warning("failed to load text font!");
493
}
494
#endif
495

    
496
static void parse_cmd_opt(int argc, char *argv[])
497
{
498
        gint i;
499

    
500
        for (i = 1; i < argc; i++) {
501
                if (!strncmp(argv[i], "--debug", 7)) {
502
                        init_console();
503
                        set_debug_mode(TRUE);
504
                } else if (!strncmp(argv[i], "--receive-all", 13))
505
                        cmd.receive_all = TRUE;
506
                else if (!strncmp(argv[i], "--receive", 9))
507
                        cmd.receive = TRUE;
508
                else if (!strncmp(argv[i], "--compose", 9)) {
509
                        const gchar *p = argv[i + 1];
510

    
511
                        cmd.compose = TRUE;
512
                        cmd.compose_mailto = NULL;
513
                        if (p && *p != '\0' && *p != '-') {
514
                                if (!strncmp(p, "mailto:", 7))
515
                                        cmd.compose_mailto = p + 7;
516
                                else
517
                                        cmd.compose_mailto = p;
518
                                i++;
519
                        }
520
                } else if (!strncmp(argv[i], "--attach", 8)) {
521
                        const gchar *p = argv[i + 1];
522
                        gchar *file;
523

    
524
                        while (p && *p != '\0' && *p != '-') {
525
                                if (!cmd.attach_files)
526
                                        cmd.attach_files = g_ptr_array_new();
527
                                if (!g_path_is_absolute(p))
528
                                        file = g_strconcat(get_startup_dir(),
529
                                                           G_DIR_SEPARATOR_S,
530
                                                           p, NULL);
531
                                else
532
                                        file = g_strdup(p);
533
                                g_ptr_array_add(cmd.attach_files, file);
534
                                i++;
535
                                p = argv[i + 1];
536
                        }
537
                } else if (!strncmp(argv[i], "--send", 6)) {
538
                        cmd.send = TRUE;
539
                } else if (!strncmp(argv[i], "--version", 9)) {
540
                        puts("Sylpheed version " VERSION);
541
                        exit(0);
542
                } else if (!strncmp(argv[i], "--status-full", 13)) {
543
                        const gchar *p = argv[i + 1];
544

    
545
                        cmd.status_full = TRUE;
546
                        while (p && *p != '\0' && *p != '-') {
547
                                if (!cmd.status_full_folders)
548
                                        cmd.status_full_folders =
549
                                                g_ptr_array_new();
550
                                g_ptr_array_add(cmd.status_full_folders,
551
                                                g_strdup(p));
552
                                i++;
553
                                p = argv[i + 1];
554
                        }
555
                } else if (!strncmp(argv[i], "--status", 8)) {
556
                        const gchar *p = argv[i + 1];
557

    
558
                        cmd.status = TRUE;
559
                        while (p && *p != '\0' && *p != '-') {
560
                                if (!cmd.status_folders)
561
                                        cmd.status_folders = g_ptr_array_new();
562
                                g_ptr_array_add(cmd.status_folders,
563
                                                g_strdup(p));
564
                                i++;
565
                                p = argv[i + 1];
566
                        }
567
                } else if (!strncmp(argv[i], "--open", 6)) {
568
                        const gchar *p = argv[i + 1];
569

    
570
                        if (p && *p != '\0' && *p != '-') {
571
                                if (cmd.open_msg)
572
                                        g_free(cmd.open_msg);
573
                                cmd.open_msg = g_locale_to_utf8
574
                                        (p, -1, NULL, NULL, NULL);
575
                                i++;
576
                        }
577
                } else if (!strncmp(argv[i], "--configdir", 11)) {
578
                        const gchar *p = argv[i + 1];
579

    
580
                        if (p && *p != '\0' && *p != '-') {
581
                                /* this must only be done at startup */
582
#ifdef G_OS_WIN32
583
                                gchar *utf8dir;
584

    
585
                                utf8dir = g_locale_to_utf8
586
                                        (p, -1, NULL, NULL, NULL);
587
                                if (utf8dir) {
588
                                        set_rc_dir(utf8dir);
589
                                        g_free(utf8dir);
590
                                } else
591
                                        set_rc_dir(p);
592
#else
593
                                set_rc_dir(p);
594
#endif
595
                                cmd.configdir = TRUE;
596
                                i++;
597
                        }
598
#ifdef G_OS_WIN32
599
                } else if (!strncmp(argv[i], "--ipcport", 9)) {
600
                        if (argv[i + 1]) {
601
                                cmd.ipcport = atoi(argv[i + 1]);
602
                                i++;
603
                        }
604
#endif
605
                } else if (!strncmp(argv[i], "--instance-id", 13)) {
606
                        if (argv[i + 1]) {
607
                                instance_id = g_locale_to_utf8
608
                                        (argv[i + 1], -1, NULL, NULL, NULL);
609
                                i++;
610
                        }
611
                } else if (!strncmp(argv[i], "--safemode", 10)) {
612
                        cmd.safe_mode = TRUE;
613
                } else if (!strncmp(argv[i], "--exit", 6)) {
614
                        cmd.exit = TRUE;
615
                } else if (!strncmp(argv[i], "--help", 6)) {
616
                        init_console();
617

    
618
                        g_print(_("Usage: %s [OPTIONS ...] [URL]\n"),
619
                                g_basename(argv[0]));
620

    
621
                        g_print("%s\n", _("  --compose [mailto URL] open composition window"));
622
                        g_print("%s\n", _("  --attach file1 [file2]...\n"
623
                                "                         open composition window with specified files\n"
624
                                "                         attached"));
625
                        g_print("%s\n", _("  --receive              receive new messages"));
626
                        g_print("%s\n", _("  --receive-all          receive new messages of all accounts"));
627
                        g_print("%s\n", _("  --send                 send all queued messages"));
628
                        g_print("%s\n", _("  --status [folder]...   show the total number of messages"));
629
                        g_print("%s\n", _("  --status-full [folder]...\n"
630
                                "                         show the status of each folder"));
631
                        g_print("%s\n", _("  --open folderid/msgnum open existing message in a new window"));
632
                        g_print("%s\n", _("  --open <file URL>      open an rfc822 message file in a new window"));
633
                        g_print("%s\n", _("  --configdir dirname    specify directory which stores configuration files"));
634
#ifdef G_OS_WIN32
635
                        g_print("%s\n", _("  --ipcport portnum      specify port for IPC remote commands"));
636
#endif
637
                        g_print("%s\n", _("  --exit                 exit Sylpheed"));
638
                        g_print("%s\n", _("  --debug                debug mode"));
639
                        g_print("%s\n", _("  --safemode             safe mode"));
640
                        g_print("%s\n", _("  --help                 display this help and exit"));
641
                        g_print("%s\n", _("  --version              output version information and exit"));
642

    
643
#ifdef G_OS_WIN32
644
                        g_print("\n");
645
                        g_print(_("Press any key..."));
646
                        _getch();
647
#endif
648

    
649
                        cleanup_console();
650
                        exit(1);
651
                } else {
652
                        /* file or URL */
653
                        const gchar *p = argv[i];
654

    
655
                        if (p && *p != '\0') {
656
                                if (!strncmp(p, "mailto:", 7)) {
657
                                        cmd.compose = TRUE;
658
                                        cmd.compose_mailto = p + 7;
659
                                } else {
660
                                        if (cmd.open_msg)
661
                                                g_free(cmd.open_msg);
662
                                        cmd.open_msg = g_locale_to_utf8
663
                                                (p, -1, NULL, NULL, NULL);
664
                                }
665
                        }
666
                }
667
        }
668

    
669
        if (cmd.attach_files && cmd.compose == FALSE) {
670
                cmd.compose = TRUE;
671
                cmd.compose_mailto = NULL;
672
        }
673

    
674
        cmd.argv0 = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
675
        if (!cmd.argv0)
676
                cmd.argv0 = g_strdup(argv[0]);
677
}
678

    
679
static gint get_queued_message_num(void)
680
{
681
        FolderItem *queue;
682

    
683
        queue = folder_get_default_queue();
684
        if (!queue) return -1;
685

    
686
        folder_item_scan(queue);
687
        return queue->total;
688
}
689

    
690
#if USE_THREADS
691
/* enables recursive locking with gdk_thread_enter / gdk_threads_leave */
692
static GStaticRecMutex syl_mutex = G_STATIC_REC_MUTEX_INIT;
693

    
694
static void thread_enter_func(void)
695
{
696
        g_static_rec_mutex_lock(&syl_mutex);
697
#if 0
698
        syl_mutex_lock_count++;
699
        if (syl_mutex_lock_count > 1)
700
                g_print("enter: syl_mutex_lock_count: %d\n", syl_mutex_lock_count);
701
#endif
702
}
703

    
704
static void thread_leave_func(void)
705
{
706
#if 0
707
        syl_mutex_lock_count--;
708
        if (syl_mutex_lock_count > 0)
709
                g_print("leave: syl_mutex_lock_count: %d\n", syl_mutex_lock_count);
710
#endif
711
        g_static_rec_mutex_unlock(&syl_mutex);
712
}
713

    
714
static void event_loop_iteration_func(void)
715
{
716
        if (g_thread_self() != main_thread) {
717
                g_fprintf(stderr, "event_loop_iteration_func called from non-main thread (%p)\n", g_thread_self());
718
                g_usleep(10000);
719
                return;
720
        }
721
        gtk_main_iteration();
722
}
723
#endif
724

    
725
static void app_init(void)
726
{
727
#if USE_THREADS
728
        if (!g_thread_supported())
729
                g_thread_init(NULL);
730
        if (!g_thread_supported())
731
                g_error("g_thread is not supported by glib.");
732
        else {
733
                gdk_threads_set_lock_functions(thread_enter_func,
734
                                               thread_leave_func);
735
                gdk_threads_init();
736
                main_thread = g_thread_self();
737
        }
738
#endif
739
        syl_init();
740

    
741
#if USE_THREADS
742
        set_event_loop_func(event_loop_iteration_func);
743
#endif
744
        prog_version = PROG_VERSION;
745

    
746
#ifdef G_OS_WIN32
747
        read_ini_file();
748
#endif
749
}
750

    
751
static void parse_gtkrc_files(void)
752
{
753
        gchar *userrc;
754

    
755
        /* parse gtkrc files */
756
        userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtkrc-2.0",
757
                             NULL);
758
        gtk_rc_parse(userrc);
759
        g_free(userrc);
760
        userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtk",
761
                             G_DIR_SEPARATOR_S, "gtkrc-2.0", NULL);
762
        gtk_rc_parse(userrc);
763
        g_free(userrc);
764
        userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, "gtkrc", NULL);
765
        gtk_rc_parse(userrc);
766
        g_free(userrc);
767

    
768
        userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
769
        gtk_accel_map_load(userrc);
770
        g_free(userrc);
771
}
772

    
773
static void setup_rc_dir(void)
774
{
775
#if !defined(G_OS_WIN32) && !defined(__APPLE__)
776
        CHDIR_EXIT_IF_FAIL(get_home_dir(), 1);
777

    
778
        /* backup if old rc file exists */
779
        if (!cmd.configdir && is_file_exist(RC_DIR)) {
780
                if (rename_force(RC_DIR, RC_DIR ".bak") < 0)
781
                        FILE_OP_ERROR(RC_DIR, "rename");
782
        }
783

    
784
        /* migration from ~/.sylpheed to ~/.sylpheed-2.0 */
785
        if (!cmd.configdir && !is_dir_exist(RC_DIR)) {
786
                const gchar *envstr;
787
                AlertValue val;
788

    
789
                /* check for filename encoding */
790
                if (conv_get_locale_charset() != C_UTF_8) {
791
                        envstr = g_getenv("G_FILENAME_ENCODING");
792
                        if (!envstr)
793
                                envstr = g_getenv("G_BROKEN_FILENAMES");
794
                        if (!envstr) {
795
                                val = alertpanel(_("Filename encoding"),
796
                                                 _("The locale encoding is not UTF-8, but the environmental variable G_FILENAME_ENCODING is not set.\n"
797
                                                   "If the locale encoding is used for file name or directory name, it will not work correctly.\n"
798
                                                   "In that case, you must set the following environmental variable (see README for detail):\n"
799
                                                   "\n"
800
                                                   "\tG_FILENAME_ENCODING=@locale\n"
801
                                                   "\n"
802
                                                   "Continue?"),
803
                                                 GTK_STOCK_OK, GTK_STOCK_QUIT,
804
                                                 NULL);
805
                                if (G_ALERTDEFAULT != val)
806
                                        exit(1);
807
                        }
808
                }
809

    
810
                if (make_dir(RC_DIR) < 0)
811
                        exit(1);
812
                if (is_dir_exist(OLD_RC_DIR))
813
                        migrate_old_config();
814
        }
815
#endif /* !G_OS_WIN32 && !__APPLE__ */
816

    
817
        syl_setup_rc_dir();
818
}
819

    
820
static void app_restart(void)
821
{
822
        gchar *cmdline;
823
        GError *error = NULL;
824
#ifdef G_OS_WIN32
825
        if (cmd.configdir) {
826
                cmdline = g_strdup_printf("\"%s\"%s --configdir \"%s\" --ipcport %d",
827
                                          cmd.argv0,
828
                                          get_debug_mode() ? " --debug" : "",
829
                                          get_rc_dir(),
830
                                          cmd.ipcport);
831
        } else {
832
                cmdline = g_strdup_printf("\"%s\"%s --ipcport %d",
833
                                          cmd.argv0,
834
                                          get_debug_mode() ? " --debug" : "",
835
                                          cmd.ipcport);
836
        }
837
#else
838
        if (cmd.configdir) {
839
                cmdline = g_strdup_printf("\"%s\"%s --configdir \"%s\"",
840
                                          cmd.argv0,
841
                                          get_debug_mode() ? " --debug" : "",
842
                                          get_rc_dir());
843
        } else {
844
                cmdline = g_strdup_printf("\"%s\"%s",
845
                                          cmd.argv0,
846
                                          get_debug_mode() ? " --debug" : "");
847
        }
848
#endif
849
        if (!g_spawn_command_line_async(cmdline, &error)) {
850
                alertpanel_error("restart failed\n'%s'\n%s", cmdline, error->message);
851
                g_error_free(error);
852
        }
853
        g_free(cmdline);
854
}
855

    
856
void app_will_restart(gboolean force)
857
{
858
        cmd.restart = TRUE;
859
        app_will_exit(force);
860
        /* canceled */
861
        cmd.restart = FALSE;
862
}
863

    
864
void app_will_exit(gboolean force)
865
{
866
        MainWindow *mainwin;
867
        gchar *filename;
868
        static gboolean on_exit = FALSE;
869
        GList *cur;
870

    
871
        if (on_exit)
872
                return;
873
        on_exit = TRUE;
874

    
875
        mainwin = main_window_get();
876

    
877
        if (!force && compose_get_compose_list()) {
878
                if (alertpanel(_("Notice"),
879
                               _("Composing message exists. Really quit?"),
880
                               GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL)
881
                    != G_ALERTDEFAULT) {
882
                        on_exit = FALSE;
883
                        return;
884
                }
885
                manage_window_focus_in(mainwin->window, NULL, NULL);
886
        }
887

    
888
        if (!force &&
889
            prefs_common.warn_queued_on_exit && get_queued_message_num() > 0) {
890
                if (alertpanel(_("Queued messages"),
891
                               _("Some unsent messages are queued. Exit now?"),
892
                               GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL)
893
                    != G_ALERTDEFAULT) {
894
                        on_exit = FALSE;
895
                        return;
896
                }
897
                manage_window_focus_in(mainwin->window, NULL, NULL);
898
        }
899

    
900
        if (force)
901
                g_signal_emit_by_name(syl_app_get(), "app-force-exit");
902
        g_signal_emit_by_name(syl_app_get(), "app-exit");
903

    
904
        inc_autocheck_timer_remove();
905

    
906
        if (prefs_common.clean_on_exit)
907
                main_window_empty_trash(mainwin,
908
                                        !force && prefs_common.ask_on_clean);
909

    
910
        for (cur = account_get_list(); cur != NULL; cur = cur->next) {
911
                PrefsAccount *ac = (PrefsAccount *)cur->data;
912
                if (ac->protocol == A_IMAP4 && ac->imap_clear_cache_on_exit &&
913
                    ac->folder)
914
                        procmsg_remove_all_cached_messages(FOLDER(ac->folder));
915
        }
916

    
917
        syl_plugin_unload_all();
918

    
919
        trayicon_destroy(mainwin->tray_icon);
920

    
921
        /* save all state before exiting */
922
        summary_write_cache(mainwin->summaryview);
923
        main_window_get_size(mainwin);
924
        main_window_get_position(mainwin);
925
        syl_save_all_state();
926
        addressbook_export_to_file();
927

    
928
        filename = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
929
        gtk_accel_map_save(filename);
930
        g_free(filename);
931

    
932
        /* remove temporary files, close log file, socket cleanup */
933
#if USE_SSL
934
        ssl_done();
935
#endif
936
        syl_cleanup();
937
        lock_socket_remove();
938

    
939
#ifdef USE_UPDATE_CHECK_PLUGIN
940
#ifdef G_OS_WIN32
941
        cur = gtk_window_list_toplevels();
942
        g_list_foreach(cur, (GFunc)gtk_widget_hide, NULL);
943
        g_list_free(cur);
944
        update_check_spawn_plugin_updater();
945
#endif
946
#endif
947

    
948
        cleanup_console();
949

    
950
        if (gtk_main_level() > 0)
951
                gtk_main_quit();
952

    
953
        if (cmd.restart)
954
                app_restart();
955

    
956
        exit(0);
957
}
958

    
959
#if 0
960
#if USE_GPGME
961
static void idle_function_for_gpgme(void)
962
{
963
        while (gtk_events_pending())
964
                gtk_main_iteration();
965
}
966
#endif /* USE_GPGME */
967
#endif /* 0 */
968

    
969
static void check_gpg(void)
970
{
971
#if USE_GPGME
972
        const gchar *version;
973
        gpgme_error_t err = 0;
974

    
975
        version = gpgme_check_version("1.0.0");
976
        if (version) {
977
                debug_print("GPGME Version: %s\n", version);
978
                err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
979
                if (err)
980
                        debug_print("gpgme_engine_check_version: %s\n",
981
                                    gpgme_strerror(err));
982
        }
983

    
984
        if (version && !err) {
985
                /* Also does some gpgme init */
986
                gpgme_engine_info_t engineInfo;
987

    
988
#if HAVE_LOCALE_H
989
                gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
990
                gpgme_set_locale(NULL, LC_MESSAGES,
991
                                 setlocale(LC_MESSAGES, NULL));
992
#endif
993

    
994
                if (!gpgme_get_engine_info(&engineInfo)) {
995
                        while (engineInfo) {
996
                                debug_print("GPGME Protocol: %s\n      Version: %s\n",
997
                                            gpgme_get_protocol_name
998
                                                (engineInfo->protocol),
999
                                            engineInfo->version ?
1000
                                            engineInfo->version : "(unknown)");
1001
                                engineInfo = engineInfo->next;
1002
                        }
1003
                }
1004

    
1005
                procmsg_set_decrypt_message_func
1006
                        (rfc2015_open_message_decrypted);
1007
                procmsg_set_auto_decrypt_message(TRUE);
1008
        } else {
1009
                rfc2015_disable_all();
1010

    
1011
                if (prefs_common.gpg_warning) {
1012
                        AlertValue val;
1013

    
1014
                        val = alertpanel_message_with_disable
1015
                                (_("Warning"),
1016
                                 _("GnuPG is not installed properly, or its version is too old.\n"
1017
                                   "OpenPGP support disabled."),
1018
                                 ALERT_WARNING);
1019
                        if (val & G_ALERTDISABLE)
1020
                                prefs_common.gpg_warning = FALSE;
1021
                }
1022
        }
1023
        /* FIXME: This function went away.  We can either block until gpgme
1024
         * operations finish (currently implemented) or register callbacks
1025
         * with the gtk main loop via the gpgme io callback interface instead.
1026
         *
1027
         * gpgme_register_idle(idle_function_for_gpgme);
1028
         */
1029
#endif
1030
}
1031

    
1032
static void default_log_func(const gchar *log_domain, GLogLevelFlags log_level,
1033
                             const gchar *message, gpointer user_data)
1034
{
1035
        gchar *prefix = "";
1036
        gchar *file_prefix = "";
1037
        LogType level = LOG_NORMAL;
1038
        gchar *str;
1039
        const gchar *message_;
1040

    
1041
        switch (log_level) {
1042
        case G_LOG_LEVEL_ERROR:
1043
                prefix = "ERROR";
1044
                file_prefix = "*** ";
1045
                level = LOG_ERROR;
1046
                break;
1047
        case G_LOG_LEVEL_CRITICAL:
1048
                prefix = "CRITICAL";
1049
                file_prefix = "** ";
1050
                level = LOG_WARN;
1051
                break;
1052
        case G_LOG_LEVEL_WARNING:
1053
                prefix = "WARNING";
1054
                file_prefix = "** ";
1055
                level = LOG_WARN;
1056
                break;
1057
        case G_LOG_LEVEL_MESSAGE:
1058
                prefix = "Message";
1059
                file_prefix = "* ";
1060
                level = LOG_MSG;
1061
                break;
1062
        case G_LOG_LEVEL_INFO:
1063
                prefix = "INFO";
1064
                file_prefix = "* ";
1065
                level = LOG_MSG;
1066
                break;
1067
        case G_LOG_LEVEL_DEBUG:
1068
                prefix = "DEBUG";
1069
                break;
1070
        default:
1071
                prefix = "LOG";
1072
                break;
1073
        }
1074

    
1075
        if (!message)
1076
                message_ = "(NULL) message";
1077
        else
1078
                message_ = message;
1079
        if (log_domain)
1080
                str = g_strconcat(log_domain, "-", prefix, ": ", message_, "\n",
1081
                                  NULL);
1082
        else
1083
                str = g_strconcat(prefix, ": ", message_, "\n", NULL);
1084
        log_window_append(str, level);
1085
        log_write(str, file_prefix);
1086
        g_free(str);
1087

    
1088
        g_log_default_handler(log_domain, log_level, message, user_data);
1089
}
1090

    
1091
static void set_log_handlers(gboolean enable)
1092
{
1093
#if GLIB_CHECK_VERSION(2, 6, 0)
1094
        if (enable)
1095
                g_log_set_default_handler(default_log_func, NULL);
1096
        else
1097
                g_log_set_default_handler(g_log_default_handler, NULL);
1098
#else
1099
        static guint handler_id[4] = {0, 0, 0, 0};
1100

    
1101
        if (enable) {
1102
                handler_id[0] = g_log_set_handler
1103
                        ("GLib", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1104
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1105
                handler_id[1] = g_log_set_handler
1106
                        ("Gtk", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1107
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1108
                handler_id[2] = g_log_set_handler
1109
                        ("LibSylph", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1110
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1111
                handler_id[3] = g_log_set_handler
1112
                        ("Sylpheed", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1113
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1114
        } else {
1115
                g_log_remove_handler("GLib", handler_id[0]);
1116
                g_log_remove_handler("Gtk", handler_id[1]);
1117
                g_log_remove_handler("LibSylph", handler_id[2]);
1118
                g_log_remove_handler("Sylpheed", handler_id[3]);
1119
                handler_id[0] = 0;
1120
                handler_id[1] = 0;
1121
                handler_id[2] = 0;
1122
                handler_id[3] = 0;
1123
        }
1124
#endif
1125
}
1126

    
1127
#ifdef G_OS_WIN32
1128
static BOOL WINAPI
1129
ctrl_handler(DWORD dwctrltype)
1130
{
1131
        log_print("ctrl_handler: received %d\n", dwctrltype);
1132
        app_will_exit(TRUE);
1133

    
1134
        return TRUE;
1135
}
1136

    
1137
static LRESULT CALLBACK
1138
wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
1139
{
1140
        switch (message) {
1141
        case WM_POWERBROADCAST:
1142
                debug_print("WM_POWERBROADCAST received: wparam = %d\n",
1143
                            wparam);
1144
                if (wparam == PBT_APMSUSPEND || wparam == PBT_APMSTANDBY) {
1145
                        debug_print("suspend now\n");
1146
                        inc_autocheck_timer_remove();
1147
                } else if (wparam == PBT_APMRESUMESUSPEND ||
1148
                           wparam == PBT_APMRESUMESTANDBY) {
1149
                        debug_print("resume now\n");
1150
                        inc_autocheck_timer_set();
1151
                }
1152
                break;
1153
        case WM_ENDSESSION:
1154
                if (wparam == 1) {
1155
                        log_print("WM_ENDSESSION received: system is quitting\n");
1156
                        app_will_exit(TRUE);
1157
                }
1158
                break;
1159
        default:
1160
                break;
1161
        }
1162

    
1163
        return DefWindowProc(hwnd, message, wparam, lparam);
1164
}
1165

    
1166
static void register_system_events(void)
1167
{
1168
        WNDCLASS wclass;
1169
        static HWND hwnd = NULL;
1170
        static BOOL ctrl_handler_set = FALSE;
1171
        ATOM klass;
1172
        HINSTANCE hmodule = GetModuleHandle(NULL);
1173

    
1174
        if (init_console_done && !ctrl_handler_set) {
1175
                debug_print("register_system_events(): SetConsoleCtrlHandler\n");
1176
                ctrl_handler_set = SetConsoleCtrlHandler(ctrl_handler, TRUE);
1177
                if (!ctrl_handler_set)
1178
                        g_warning("SetConsoleCtrlHandler() failed\n");
1179
        }
1180

    
1181
        if (hwnd)
1182
                return;
1183

    
1184
        debug_print("register_system_events(): RegisterClass\n");
1185

    
1186
        memset(&wclass, 0, sizeof(WNDCLASS));
1187
        wclass.lpszClassName = "sylpheed-observer";
1188
        wclass.lpfnWndProc   = wndproc;
1189
        wclass.hInstance     = hmodule;
1190

    
1191
        klass = RegisterClass(&wclass);
1192
        if (!klass)
1193
                return;
1194

    
1195
        hwnd = CreateWindow(MAKEINTRESOURCE(klass), NULL, WS_POPUP,
1196
                            0, 0, 1, 1, NULL, NULL, hmodule, NULL);
1197
        if (!hwnd)
1198
                UnregisterClass(MAKEINTRESOURCE(klass), hmodule);
1199
}
1200
#else /* G_OS_WIN32 */
1201
static void sig_handler(gint signum)
1202
{
1203
        debug_print("signal %d received\n", signum);
1204

    
1205
        switch (signum) {
1206
        case SIGHUP:
1207
        case SIGINT:
1208
        case SIGTERM:
1209
        case SIGQUIT:
1210
                app_will_exit(TRUE);
1211
                break;
1212
        default:
1213
                break;
1214
        }
1215
}
1216

    
1217
static void register_system_events(void)
1218
{
1219
        struct sigaction sa;
1220

    
1221
        memset(&sa, 0, sizeof(sa));
1222
        sa.sa_handler = sig_handler;
1223
        sa.sa_flags = SA_RESTART;
1224

    
1225
        sigemptyset(&sa.sa_mask);
1226
        sigaddset(&sa.sa_mask, SIGHUP);
1227
        sigaddset(&sa.sa_mask, SIGINT);
1228
        sigaddset(&sa.sa_mask, SIGTERM);
1229
        sigaddset(&sa.sa_mask, SIGQUIT);
1230
        sigaddset(&sa.sa_mask, SIGPIPE);
1231

    
1232
        sigaction(SIGHUP, &sa, NULL);
1233
        sigaction(SIGINT, &sa, NULL);
1234
        sigaction(SIGTERM, &sa, NULL);
1235
        sigaction(SIGQUIT, &sa, NULL);
1236
        sigaction(SIGPIPE, &sa, NULL);
1237
}
1238
#endif
1239

    
1240
#define ADD_SYM(sym)        syl_plugin_add_symbol(#sym, sym)
1241

    
1242
static void plugin_init(void)
1243
{
1244
        MainWindow *mainwin;
1245
        gchar *path;
1246

    
1247
        mainwin = main_window_get();
1248

    
1249
        STATUSBAR_PUSH(mainwin, _("Loading plug-ins..."));
1250

    
1251
        if (syl_plugin_init_lib() != 0) {
1252
                STATUSBAR_POP(mainwin);
1253
                return;
1254
        }
1255

    
1256
        if (cmd.safe_mode) {
1257
                STATUSBAR_POP(mainwin);
1258
                return;
1259
        }
1260

    
1261
        ADD_SYM(prog_version);
1262
        ADD_SYM(app_will_exit);
1263

    
1264
        ADD_SYM(main_window_lock);
1265
        ADD_SYM(main_window_unlock);
1266
        ADD_SYM(main_window_get);
1267
        ADD_SYM(main_window_popup);
1268

    
1269
        syl_plugin_add_symbol("main_window_menu_factory",
1270
                              mainwin->menu_factory);
1271
        syl_plugin_add_symbol("main_window_statusbar", mainwin->statusbar);
1272

    
1273
        ADD_SYM(folderview_get);
1274
        ADD_SYM(folderview_add_sub_widget);
1275
        ADD_SYM(folderview_select);
1276
        ADD_SYM(folderview_unselect);
1277
        ADD_SYM(folderview_select_next_unread);
1278
        ADD_SYM(folderview_get_selected_item);
1279
        ADD_SYM(folderview_check_new);
1280
        ADD_SYM(folderview_check_new_item);
1281
        ADD_SYM(folderview_check_new_all);
1282
        ADD_SYM(folderview_update_item);
1283
        ADD_SYM(folderview_update_item_foreach);
1284
        ADD_SYM(folderview_update_all_updated);
1285
        ADD_SYM(folderview_check_new_selected);
1286

    
1287
        syl_plugin_add_symbol("folderview_mail_popup_factory",
1288
                              mainwin->folderview->mail_factory);
1289
        syl_plugin_add_symbol("folderview_imap_popup_factory",
1290
                              mainwin->folderview->imap_factory);
1291
        syl_plugin_add_symbol("folderview_news_popup_factory",
1292
                              mainwin->folderview->news_factory);
1293

    
1294
        syl_plugin_add_symbol("summaryview", mainwin->summaryview);
1295
        syl_plugin_add_symbol("summaryview_popup_factory",
1296
                              mainwin->summaryview->popupfactory);
1297

    
1298
        ADD_SYM(summary_select_by_msgnum);
1299
        ADD_SYM(summary_select_by_msginfo);
1300
        ADD_SYM(summary_lock);
1301
        ADD_SYM(summary_unlock);
1302
        ADD_SYM(summary_is_locked);
1303
        ADD_SYM(summary_is_read_locked);
1304
        ADD_SYM(summary_write_lock);
1305
        ADD_SYM(summary_write_unlock);
1306
        ADD_SYM(summary_is_write_locked);
1307
        ADD_SYM(summary_get_current_folder);
1308
        ADD_SYM(summary_get_selection_type);
1309
        ADD_SYM(summary_get_selected_msg_list);
1310
        ADD_SYM(summary_get_msg_list);
1311
        ADD_SYM(summary_show_queued_msgs);
1312
        ADD_SYM(summary_redisplay_msg);
1313
        ADD_SYM(summary_open_msg);
1314
        ADD_SYM(summary_view_source);
1315
        ADD_SYM(summary_reedit);
1316
        ADD_SYM(summary_update_selected_rows);
1317
        ADD_SYM(summary_update_by_msgnum);
1318

    
1319
        ADD_SYM(messageview_create_with_new_window);
1320
        ADD_SYM(messageview_show);
1321

    
1322
        ADD_SYM(compose_new);
1323
        ADD_SYM(compose_entry_set);
1324
        ADD_SYM(compose_entry_append);
1325
        ADD_SYM(compose_entry_get_text);
1326
        ADD_SYM(compose_lock);
1327
        ADD_SYM(compose_unlock);
1328

    
1329
        ADD_SYM(foldersel_folder_sel);
1330
        ADD_SYM(foldersel_folder_sel_full);
1331

    
1332
        ADD_SYM(input_dialog);
1333
        ADD_SYM(input_dialog_with_invisible);
1334

    
1335
        ADD_SYM(manage_window_set_transient);
1336
        ADD_SYM(manage_window_signals_connect);
1337
        ADD_SYM(manage_window_get_focus_window);
1338

    
1339
        ADD_SYM(inc_mail);
1340
        ADD_SYM(inc_is_active);
1341
        ADD_SYM(inc_lock);
1342
        ADD_SYM(inc_unlock);
1343

    
1344
#if USE_UPDATE_CHECK
1345
        ADD_SYM(update_check);
1346
        ADD_SYM(update_check_set_check_url);
1347
        ADD_SYM(update_check_get_check_url);
1348
        ADD_SYM(update_check_set_download_url);
1349
        ADD_SYM(update_check_get_download_url);
1350
        ADD_SYM(update_check_set_jump_url);
1351
        ADD_SYM(update_check_get_jump_url);
1352
#ifdef USE_UPDATE_CHECK_PLUGIN
1353
        ADD_SYM(update_check_set_check_plugin_url);
1354
        ADD_SYM(update_check_get_check_plugin_url);
1355
        ADD_SYM(update_check_set_jump_plugin_url);
1356
        ADD_SYM(update_check_get_jump_plugin_url);
1357
#endif /* USE_UPDATE_CHECK_PLUGIN */
1358
#endif
1359

    
1360
        ADD_SYM(alertpanel_full);
1361
        ADD_SYM(alertpanel);
1362
        ADD_SYM(alertpanel_message);
1363
        ADD_SYM(alertpanel_message_with_disable);
1364

    
1365
        ADD_SYM(send_message);
1366
        ADD_SYM(send_message_queue_all);
1367
        ADD_SYM(send_message_set_reply_flag);
1368
        ADD_SYM(send_message_set_forward_flags);
1369

    
1370
        syl_plugin_signal_connect("plugin-load", G_CALLBACK(load_cb), NULL);
1371

    
1372
        /* loading plug-ins from user plug-in directory */
1373
        path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, PLUGIN_DIR, NULL);
1374
        syl_plugin_load_all(path);
1375
        g_free(path);
1376

    
1377
        /* loading plug-ins from system plug-in directory */
1378
#ifdef G_OS_WIN32
1379
        path = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, PLUGIN_DIR,
1380
                           NULL);
1381
        syl_plugin_load_all(path);
1382
        g_free(path);
1383
#else
1384
        syl_plugin_load_all(PLUGINDIR);
1385
#endif
1386

    
1387
        STATUSBAR_POP(mainwin);
1388
}
1389

    
1390
static gchar *get_socket_name(void)
1391
{
1392
        static gchar *filename = NULL;
1393

    
1394
        if (filename == NULL) {
1395
                filename = g_strdup_printf("%s%c%s-%d",
1396
                                           g_get_tmp_dir(), G_DIR_SEPARATOR,
1397
                                           instance_id ? instance_id : "sylpheed",
1398
#if HAVE_GETUID
1399
                                           getuid());
1400
#else
1401
                                           0);
1402
#endif
1403
        }
1404

    
1405
        return filename;
1406
}
1407

    
1408
static gint prohibit_duplicate_launch(void)
1409
{
1410
        gint sock;
1411

    
1412
#ifdef G_OS_WIN32
1413
        HANDLE hmutex;
1414
        const gchar *ins_id = instance_id ? instance_id : "Sylpheed";
1415
        gushort port = cmd.ipcport ? cmd.ipcport : REMOTE_CMD_PORT;
1416

    
1417
        debug_print("prohibit_duplicate_launch: checking mutex: %s\n", ins_id);
1418
        hmutex = CreateMutexA(NULL, FALSE, ins_id);
1419
        if (!hmutex) {
1420
                g_warning("cannot create Mutex: %s\n", ins_id);
1421
                return -1;
1422
        }
1423
        if (GetLastError() != ERROR_ALREADY_EXISTS) {
1424
                debug_print("prohibit_duplicate_launch: creating socket: port %d\n", port);
1425
                sock = fd_open_inet(port);
1426
                if (sock < 0)
1427
                        return 0;
1428
                return sock;
1429
        }
1430

    
1431
        debug_print("prohibit_duplicate_launch: connecting to socket: port %d\n", port);
1432
        sock = fd_connect_inet(port);
1433
        if (sock < 0)
1434
                return -1;
1435
#else
1436
        gchar *path;
1437

    
1438
        path = get_socket_name();
1439
        debug_print("prohibit_duplicate_launch: checking socket: %s\n", path);
1440
        sock = fd_connect_unix(path);
1441
        if (sock < 0) {
1442
                debug_print("prohibit_duplicate_launch: creating socket: %s\n", path);
1443
                g_unlink(path);
1444
                return fd_open_unix(path);
1445
        }
1446
#endif
1447

    
1448
        /* remote command mode */
1449

    
1450
        debug_print(_("another Sylpheed is already running.\n"));
1451

    
1452
        if (cmd.receive_all)
1453
                fd_write_all(sock, "receive_all\n", 12);
1454
        else if (cmd.receive)
1455
                fd_write_all(sock, "receive\n", 8);
1456
        else if (cmd.compose && cmd.attach_files) {
1457
                gchar *str, *compose_str;
1458
                gint i;
1459

    
1460
                if (cmd.compose_mailto)
1461
                        compose_str = g_strdup_printf("compose_attach %s\n",
1462
                                                      cmd.compose_mailto);
1463
                else
1464
                        compose_str = g_strdup("compose_attach\n");
1465

    
1466
                fd_write_all(sock, compose_str, strlen(compose_str));
1467
                g_free(compose_str);
1468

    
1469
                for (i = 0; i < cmd.attach_files->len; i++) {
1470
                        str = g_ptr_array_index(cmd.attach_files, i);
1471
                        fd_write_all(sock, str, strlen(str));
1472
                        fd_write_all(sock, "\n", 1);
1473
                }
1474

    
1475
                fd_write_all(sock, ".\n", 2);
1476
        } else if (cmd.compose) {
1477
                gchar *compose_str;
1478

    
1479
                if (cmd.compose_mailto)
1480
                        compose_str = g_strdup_printf
1481
                                ("compose %s\n", cmd.compose_mailto);
1482
                else
1483
                        compose_str = g_strdup("compose\n");
1484

    
1485
                fd_write_all(sock, compose_str, strlen(compose_str));
1486
                g_free(compose_str);
1487
        } else if (cmd.send) {
1488
                fd_write_all(sock, "send\n", 5);
1489
        } else if (cmd.status || cmd.status_full) {
1490
                gchar buf[BUFFSIZE];
1491
                gint i;
1492
                const gchar *command;
1493
                GPtrArray *folders;
1494
                gchar *folder;
1495

    
1496
                command = cmd.status_full ? "status-full\n" : "status\n";
1497
                folders = cmd.status_full ? cmd.status_full_folders :
1498
                        cmd.status_folders;
1499

    
1500
                fd_write_all(sock, command, strlen(command));
1501
                for (i = 0; folders && i < folders->len; ++i) {
1502
                        folder = g_ptr_array_index(folders, i);
1503
                        fd_write_all(sock, folder, strlen(folder));
1504
                        fd_write_all(sock, "\n", 1);
1505
                }
1506
                fd_write_all(sock, ".\n", 2);
1507
                for (;;) {
1508
                        fd_gets(sock, buf, sizeof(buf));
1509
                        if (!strncmp(buf, ".\n", 2)) break;
1510
                        fputs(buf, stdout);
1511
                }
1512
        } else if (cmd.open_msg) {
1513
                gchar *str;
1514

    
1515
                str = g_strdup_printf("open %s\n", cmd.open_msg);
1516
                fd_write_all(sock, str, strlen(str));
1517
                g_free(str);
1518
        } else if (cmd.exit) {
1519
                fd_write_all(sock, "exit\n", 5);
1520
        } else {
1521
#ifdef G_OS_WIN32
1522
                HWND hwnd;
1523

    
1524
                fd_write_all(sock, "popup\n", 6);
1525
                if (fd_read(sock, (gchar *)&hwnd, sizeof(hwnd)) == sizeof(hwnd))
1526
                        SetForegroundWindow(hwnd);
1527
#else
1528
                fd_write_all(sock, "popup\n", 6);
1529
#endif
1530
        }
1531

    
1532
        fd_close(sock);
1533
        return -1;
1534
}
1535

    
1536
static gint lock_socket_remove(void)
1537
{
1538
#ifndef G_OS_WIN32
1539
        gchar *filename;
1540
#endif
1541

    
1542
        if (lock_socket < 0) return -1;
1543

    
1544
        if (lock_socket_tag > 0)
1545
                g_source_remove(lock_socket_tag);
1546
        if (lock_ch) {
1547
                g_io_channel_shutdown(lock_ch, FALSE, NULL);
1548
                g_io_channel_unref(lock_ch);
1549
                lock_ch = NULL;
1550
        }
1551

    
1552
#ifndef G_OS_WIN32
1553
        filename = get_socket_name();
1554
        debug_print("lock_socket_remove: removing socket: %s\n", filename);
1555
        g_unlink(filename);
1556
#endif
1557

    
1558
        return 0;
1559
}
1560

    
1561
static GPtrArray *get_folder_item_list(gint sock)
1562
{
1563
        gchar buf[BUFFSIZE];
1564
        FolderItem *item;
1565
        GPtrArray *folders = NULL;
1566

    
1567
        for (;;) {
1568
                fd_gets(sock, buf, sizeof(buf));
1569
                if (!strncmp(buf, ".\n", 2)) break;
1570
                strretchomp(buf);
1571
                if (!folders) folders = g_ptr_array_new();
1572
                item = folder_find_item_from_identifier(buf);
1573
                if (item)
1574
                        g_ptr_array_add(folders, item);
1575
                else
1576
                        g_warning("no such folder: %s\n", buf);
1577
        }
1578

    
1579
        return folders;
1580
}
1581

    
1582
static gboolean lock_socket_input_cb(GIOChannel *source, GIOCondition condition,
1583
                                     gpointer data)
1584
{
1585
        MainWindow *mainwin = (MainWindow *)data;
1586
        gint fd, sock;
1587
        gchar buf[BUFFSIZE];
1588

    
1589
#if USE_THREADS
1590
        gdk_threads_enter();
1591
#endif
1592

    
1593
        fd = g_io_channel_unix_get_fd(source);
1594
        sock = fd_accept(fd);
1595
        fd_gets(sock, buf, sizeof(buf));
1596

    
1597
        if (!strncmp(buf, "popup", 5)) {
1598
#ifdef G_OS_WIN32
1599
                HWND hwnd;
1600

    
1601
                hwnd = (HWND)gdk_win32_drawable_get_handle
1602
                        (GDK_DRAWABLE(mainwin->window->window));
1603
                fd_write(sock, (gchar *)&hwnd, sizeof(hwnd));
1604
                if (mainwin->window_hidden)
1605
                        main_window_popup(mainwin);
1606
#else
1607
                main_window_popup(mainwin);
1608
#endif
1609
        } else if (!strncmp(buf, "receive_all", 11)) {
1610
                main_window_popup(mainwin);
1611
                if (!gtkut_window_modal_exist())
1612
                        inc_all_account_mail(mainwin, FALSE);
1613
        } else if (!strncmp(buf, "receive", 7)) {
1614
                main_window_popup(mainwin);
1615
                if (!gtkut_window_modal_exist())
1616
                        inc_mail(mainwin);
1617
        } else if (!strncmp(buf, "compose_attach", 14)) {
1618
                GPtrArray *files;
1619
                gchar *mailto;
1620

    
1621
                mailto = g_strdup(buf + strlen("compose_attach") + 1);
1622
                files = g_ptr_array_new();
1623
                while (fd_gets(sock, buf, sizeof(buf)) > 0) {
1624
                        if (buf[0] == '.' && buf[1] == '\n') break;
1625
                        strretchomp(buf);
1626
                        g_ptr_array_add(files, g_strdup(buf));
1627
                }
1628
                open_compose_new(mailto, files);
1629
                ptr_array_free_strings(files);
1630
                g_ptr_array_free(files, TRUE);
1631
                g_free(mailto);
1632
        } else if (!strncmp(buf, "compose", 7)) {
1633
                open_compose_new(buf + strlen("compose") + 1, NULL);
1634
        } else if (!strncmp(buf, "send", 4)) {
1635
                send_queue();
1636
        } else if (!strncmp(buf, "status-full", 11) ||
1637
                   !strncmp(buf, "status", 6)) {
1638
                gchar *status;
1639
                GPtrArray *folders;
1640

    
1641
                folders = get_folder_item_list(sock);
1642
                status = folder_get_status
1643
                        (folders, !strncmp(buf, "status-full", 11));
1644
                fd_write_all(sock, status, strlen(status));
1645
                fd_write_all(sock, ".\n", 2);
1646
                g_free(status);
1647
                if (folders) g_ptr_array_free(folders, TRUE);
1648
        } else if (!strncmp(buf, "open", 4)) {
1649
                strretchomp(buf);
1650
                if (strlen(buf) < 6 || buf[4] != ' ') {
1651
                        fd_close(sock);
1652
#if USE_THREADS
1653
                        gdk_threads_leave();
1654
#endif
1655
                        return TRUE;
1656
                }
1657
                open_message(buf + 5);
1658
        } else if (!strncmp(buf, "exit", 4)) {
1659
                fd_close(sock);
1660
                app_will_exit(TRUE);
1661
        }
1662

    
1663
        fd_close(sock);
1664

    
1665
#if USE_THREADS
1666
        gdk_threads_leave();
1667
#endif
1668

    
1669
        return TRUE;
1670
}
1671

    
1672
static void remote_command_exec(void)
1673
{
1674
        MainWindow *mainwin;
1675

    
1676
        mainwin = main_window_get();
1677

    
1678
        if (prefs_common.open_inbox_on_startup) {
1679
                FolderItem *item;
1680
                PrefsAccount *ac;
1681

    
1682
                ac = account_get_default();
1683
                if (!ac)
1684
                        ac = cur_account;
1685
                item = ac && ac->inbox
1686
                        ? folder_find_item_from_identifier(ac->inbox)
1687
                        : folder_get_default_inbox();
1688
                folderview_select(mainwin->folderview, item);
1689
        }
1690

    
1691
        if (!gtkut_window_modal_exist()) {
1692
                if (cmd.compose)
1693
                        open_compose_new(cmd.compose_mailto, cmd.attach_files);
1694

    
1695
                if (cmd.open_msg)
1696
                        open_message(cmd.open_msg);
1697

    
1698
                if (cmd.receive_all)
1699
                        inc_all_account_mail(mainwin, FALSE);
1700
                else if (prefs_common.chk_on_startup)
1701
                        inc_all_account_mail(mainwin, TRUE);
1702
                else if (cmd.receive)
1703
                        inc_mail(mainwin);
1704

    
1705
                if (cmd.send)
1706
                        send_queue();
1707
        }
1708

    
1709
        if (cmd.attach_files) {
1710
                ptr_array_free_strings(cmd.attach_files);
1711
                g_ptr_array_free(cmd.attach_files, TRUE);
1712
                cmd.attach_files = NULL;
1713
        }
1714
        if (cmd.status_folders) {
1715
                g_ptr_array_free(cmd.status_folders, TRUE);
1716
                cmd.status_folders = NULL;
1717
        }
1718
        if (cmd.status_full_folders) {
1719
                g_ptr_array_free(cmd.status_full_folders, TRUE);
1720
                cmd.status_full_folders = NULL;
1721
        }
1722
        if (cmd.open_msg) {
1723
                g_free(cmd.open_msg);
1724
                cmd.open_msg = NULL;
1725
        }
1726
        if (cmd.exit) {
1727
                app_will_exit(TRUE);
1728
        }
1729
}
1730

    
1731
#if !defined(G_OS_WIN32) && !defined(__APPLE__)
1732
static void migrate_old_config(void)
1733
{
1734
        GDir *dir;
1735
        const gchar *dir_name;
1736
        GPatternSpec *pspec;
1737

    
1738
        if (alertpanel(_("Migration of configuration"),
1739
                       _("The previous version of configuration found.\n"
1740
                         "Do you want to migrate it?"),
1741
                       GTK_STOCK_YES, GTK_STOCK_NO, NULL) != G_ALERTDEFAULT)
1742
                return;
1743

    
1744
        debug_print("Migrating old configuration...\n");
1745

    
1746
#define COPY_FILE(rcfile)                                                \
1747
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile)) {        \
1748
                conv_copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile,        \
1749
                               RC_DIR G_DIR_SEPARATOR_S rcfile,                \
1750
                               conv_get_locale_charset_str());                \
1751
        }
1752

    
1753
        COPY_FILE(ACCOUNT_RC);
1754
        COPY_FILE(ACTIONS_RC);
1755
        COPY_FILE(COMMON_RC);
1756
        COPY_FILE(CUSTOM_HEADER_RC);
1757
        COPY_FILE(DISPLAY_HEADER_RC);
1758
        COPY_FILE(FILTER_HEADER_RC);
1759
        COPY_FILE(COMMAND_HISTORY);
1760

    
1761
#undef COPY_FILE
1762

    
1763
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST))
1764
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST,
1765
                          RC_DIR G_DIR_SEPARATOR_S FILTER_LIST, FALSE);
1766
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST))
1767
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST,
1768
                          RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST, FALSE);
1769
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types"))
1770
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types",
1771
                          RC_DIR G_DIR_SEPARATOR_S "mime.types", FALSE);
1772

    
1773
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR))
1774
                conv_copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1775
                              RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1776
                              conv_get_locale_charset_str());
1777
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR))
1778
                copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR,
1779
                         RC_DIR G_DIR_SEPARATOR_S UIDL_DIR);
1780

    
1781
        if (!is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S ADDRESSBOOK_INDEX_FILE))
1782
                return;
1783

    
1784
        if ((dir = g_dir_open(OLD_RC_DIR, 0, NULL)) == NULL) {
1785
                g_warning("failed to open directory: %s\n", OLD_RC_DIR);
1786
                return;
1787
        }
1788

    
1789
        pspec = g_pattern_spec_new("addrbook-*.xml");
1790

    
1791
        while ((dir_name = g_dir_read_name(dir)) != NULL) {
1792
                if (g_pattern_match_string(pspec, dir_name)) {
1793
                        gchar *old_file;
1794
                        gchar *new_file;
1795

    
1796
                        old_file = g_strconcat(OLD_RC_DIR G_DIR_SEPARATOR_S,
1797
                                               dir_name, NULL);
1798
                        new_file = g_strconcat(RC_DIR G_DIR_SEPARATOR_S,
1799
                                               dir_name, NULL);
1800
                        copy_file(old_file, new_file, FALSE);
1801
                        g_free(new_file);
1802
                        g_free(old_file);
1803
                }
1804
        }
1805

    
1806
        g_pattern_spec_free(pspec);
1807
        g_dir_close(dir);
1808
}
1809
#endif /* !G_OS_WIN32 && !__APPLE__ */
1810

    
1811
static void open_compose_new(const gchar *address, GPtrArray *attach_files)
1812
{
1813
        gchar *utf8addr = NULL;
1814
#ifdef G_OS_WIN32
1815
        GPtrArray *utf8files = NULL;
1816
#endif
1817

    
1818
        if (gtkut_window_modal_exist())
1819
                return;
1820

    
1821
        if (address) {
1822
                utf8addr = g_locale_to_utf8(address, -1, NULL, NULL, NULL);
1823
                if (utf8addr)
1824
                        g_strstrip(utf8addr);
1825
                debug_print("open compose: %s\n", utf8addr ? utf8addr : "");
1826
        }
1827

    
1828
#ifdef G_OS_WIN32
1829
        if (attach_files) {
1830
                gint i;
1831
                gchar *file, *utf8file;
1832

    
1833
                utf8files = g_ptr_array_new();
1834
                for (i = 0; i < attach_files->len; i++) {
1835
                        file = g_ptr_array_index(attach_files, i);
1836
                        utf8file = g_locale_to_utf8(file, -1, NULL, NULL, NULL);
1837
                        if (utf8file)
1838
                                g_ptr_array_add(utf8files, utf8file);
1839
                }
1840
        }
1841

    
1842
        compose_new(NULL, NULL, utf8addr, utf8files);
1843
        if (utf8files) {
1844
                ptr_array_free_strings(utf8files);
1845
                g_ptr_array_free(utf8files, TRUE);
1846
        }
1847
#else
1848
        compose_new(NULL, NULL, utf8addr, attach_files);
1849
#endif
1850

    
1851
        g_free(utf8addr);
1852
}
1853

    
1854
static void open_message_file(const gchar *file)
1855
{
1856
        MsgInfo *msginfo;
1857
        MsgFlags flags = {0};
1858
        MessageView *msgview;
1859

    
1860
        g_return_if_fail(file != NULL);
1861

    
1862
        debug_print("open message file: %s\n", file);
1863

    
1864
        if (!is_file_exist(file) || get_file_size(file) <= 0) {
1865
                debug_print("file not found: %s\n", file);
1866
                return;
1867
        }
1868

    
1869
        msginfo = procheader_parse_file(file, flags, FALSE);
1870
        if (msginfo) {
1871
                msginfo->file_path = g_strdup(file);
1872
                msgview = messageview_create_with_new_window();
1873
                messageview_show(msgview, msginfo, FALSE);
1874
                procmsg_msginfo_free(msginfo);
1875
        } else
1876
                debug_print("cannot open message: %s\n", file);
1877
}
1878

    
1879
static void open_message(const gchar *path)
1880
{
1881
        gchar *fid;
1882
        gchar *msg;
1883
        gint num;
1884
        FolderItem *item;
1885
        MsgInfo *msginfo;
1886
        MessageView *msgview;
1887
        gchar *file;
1888

    
1889
        g_return_if_fail(path != NULL);
1890

    
1891
        if (gtkut_window_modal_exist())
1892
                return;
1893

    
1894
        debug_print("open message: %s\n", path);
1895

    
1896
        if (!strncmp(path, "file:", 5)) {
1897
                file = g_filename_from_uri(path, NULL, NULL);
1898
                open_message_file(file);
1899
                g_free(file);
1900
                return;
1901
        } else if (g_path_is_absolute(path)) {
1902
                open_message_file(path);
1903
                return;
1904
        }
1905

    
1906
        /* relative path, or folder identifier */
1907

    
1908
        fid = g_path_get_dirname(path);
1909
        msg = g_path_get_basename(path);
1910
        num = to_number(msg);
1911
        item = folder_find_item_from_identifier(fid);
1912

    
1913
        if (num > 0 && item) {
1914
                debug_print("open folder id: %s (msg %d)\n", fid, num);
1915
                msginfo = folder_item_get_msginfo(item, num);
1916
                if (msginfo) {
1917
                        msgview = messageview_create_with_new_window();
1918
                        messageview_show(msgview, msginfo, FALSE);
1919
                        procmsg_msginfo_free(msginfo);
1920
                        g_free(msg);
1921
                        g_free(fid);
1922
                        return;
1923
                } else
1924
                        debug_print("message %d not found\n", num);
1925
        }
1926

    
1927
        g_free(msg);
1928
        g_free(fid);
1929

    
1930
        /* relative path */
1931

    
1932
        file = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, path, NULL);
1933
        open_message_file(file);
1934
        g_free(file);
1935
}
1936

    
1937
static void send_queue(void)
1938
{
1939
        GList *list;
1940

    
1941
        if (gtkut_window_modal_exist())
1942
                return;
1943
        if (!main_window_toggle_online_if_offline(main_window_get()))
1944
                return;
1945

    
1946
        for (list = folder_get_list(); list != NULL; list = list->next) {
1947
                Folder *folder = list->data;
1948

    
1949
                if (folder->queue) {
1950
                        gint ret;
1951

    
1952
                        ret = send_message_queue_all(folder->queue,
1953
                                                     prefs_common.savemsg,
1954
                                                     prefs_common.filter_sent);
1955
                        statusbar_pop_all();
1956
                        if (ret > 0)
1957
                                folder_item_scan(folder->queue);
1958
                }
1959
        }
1960

    
1961
        folderview_update_all_updated(TRUE);
1962
        main_window_set_menu_sensitive(main_window_get());
1963
        main_window_set_toolbar_sensitive(main_window_get());
1964
}