Statistics
| Revision:

root / src / main.c @ 3284

History | View | Annotate | Download (47.6 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
        gchar *path;
230

    
231
        app_init();
232
        parse_cmd_opt(argc, argv);
233

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

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

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

    
250
        syl_app = syl_app_create();
251

    
252
        gdk_rgb_init();
253
        gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
254
        gtk_widget_set_default_visual(gdk_rgb_get_visual());
255

    
256
        parse_gtkrc_files();
257
        setup_rc_dir();
258

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

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

    
273
        CHDIR_EXIT_IF_FAIL(get_home_dir(), 1);
274

    
275
        prefs_common_read_config();
276
        filter_set_addressbook_func(addressbook_has_address);
277
        filter_read_config();
278
        prefs_actions_read_config();
279
        prefs_display_header_read_config();
280
        colorlabel_read_config();
281

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

    
288
#if defined(G_OS_WIN32) || defined(__APPLE__)
289
        fix_font_setting();
290
#endif
291

    
292
        gtkut_stock_button_set_set_reverse(!prefs_common.comply_gnome_hig);
293

    
294
        check_gpg();
295

    
296
        sock_set_io_timeout(prefs_common.io_timeout_secs);
297

    
298
        gtkut_widget_init();
299

    
300
        path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, "icons", NULL);
301
        if (is_dir_exist(path)) {
302
                debug_print("icon theme dir: %s\n", path);
303
                stock_pixbuf_set_theme_dir(path);
304
        } else {
305
                g_free(path);
306
                if (g_path_is_absolute(THEMEDIR))
307
                        path = g_strconcat(THEMEDIR, NULL);
308
                else
309
                        path = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, THEMEDIR, NULL);
310
                if (is_dir_exist(path)) {
311
                        debug_print("icon theme dir: %s\n", path);
312
                        stock_pixbuf_set_theme_dir(path);
313
                }
314
        }
315
        g_free(path);
316

    
317
#ifdef G_OS_WIN32
318
        stock_pixbuf_gdk(NULL, STOCK_PIXMAP_SYLPHEED_32, &icon);
319
        iconlist = g_list_append(iconlist, icon);
320
        stock_pixbuf_gdk(NULL, STOCK_PIXMAP_SYLPHEED_SMALL, &icon);
321
        iconlist = g_list_append(iconlist, icon);
322
        gtk_window_set_default_icon_list(iconlist);
323
        g_list_free(iconlist);
324
#else
325
        stock_pixbuf_gdk(NULL, STOCK_PIXMAP_SYLPHEED, &icon);
326
        gtk_window_set_default_icon(icon);
327
#endif
328

    
329
        mainwin = main_window_create
330
                (prefs_common.sep_folder | prefs_common.sep_msg << 1);
331
        folderview = mainwin->folderview;
332

    
333
        /* register the callback of socket input */
334
        if (lock_socket > 0) {
335
                lock_ch = g_io_channel_unix_new(lock_socket);
336
                lock_socket_tag = g_io_add_watch(lock_ch,
337
                                                 G_IO_IN|G_IO_PRI|G_IO_ERR,
338
                                                 lock_socket_input_cb, mainwin);
339
        }
340

    
341
        set_log_handlers(TRUE);
342

    
343
        account_read_config_all();
344
        account_set_menu();
345
        main_window_reflect_prefs_all();
346

    
347
        if (folder_read_list() < 0) {
348
                first_run = TRUE;
349
                setup_mailbox();
350
                folder_write_list();
351
        }
352
        if (!account_get_list()) {
353
                new_account = setup_account();
354
        }
355

    
356
        account_set_menu();
357
        main_window_reflect_prefs_all();
358

    
359
        account_set_missing_folder();
360
        folder_set_missing_folders();
361
        folderview_set(folderview);
362
        if (new_account && new_account->folder)
363
                folder_write_list();
364

    
365
        addressbook_read_file();
366

    
367
        register_system_events();
368

    
369
        inc_autocheck_timer_init(mainwin);
370

    
371
        plugin_init();
372

    
373
        g_signal_emit_by_name(syl_app, "init-done");
374

    
375
        if (first_run) {
376
                setup_import_data();
377
                setup_import_addressbook();
378
        }
379

    
380
        remote_command_exec();
381

    
382
#if USE_UPDATE_CHECK
383
        if (prefs_common.auto_update_check)
384
                update_check(FALSE);
385
#endif
386

    
387
        gtk_main();
388
#if USE_THREADS
389
        gdk_threads_leave();
390
#endif
391

    
392
        return 0;
393
}
394

    
395
static void init_console(void)
396
{
397
#ifdef G_OS_WIN32
398
        gint fd;
399
        FILE *fp;
400

    
401
        if (init_console_done)
402
                return;
403

    
404
        if (!AllocConsole()) {
405
                g_warning("AllocConsole() failed\n");
406
                return;
407
        }
408

    
409
        fd = _open_osfhandle((glong)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
410
        _dup2(fd, 1);
411
        fp = _fdopen(fd, "w");
412
        *stdout = *fp;
413
        setvbuf(stdout, NULL, _IONBF, 0);
414
        fd = _open_osfhandle((glong)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT);
415
        _dup2(fd, 2);
416
        fp = _fdopen(fd, "w");
417
        *stderr = *fp;
418
        setvbuf(stderr, NULL, _IONBF, 0);
419

    
420
        init_console_done = TRUE;
421
#endif
422
}
423

    
424
static void cleanup_console(void)
425
{
426
#ifdef G_OS_WIN32
427
        FreeConsole();
428
#endif
429
}
430

    
431
#ifdef G_OS_WIN32
432
static void read_ini_file(void)
433
{
434
        static gushort ipcport = REMOTE_CMD_PORT;
435
        static gchar *confdir = NULL;
436

    
437
        static PrefParam param[] = {
438
                {"ipcport", "50215", &ipcport, P_USHORT},
439
                {"configdir", NULL, &confdir, P_STRING},
440

    
441
                {NULL, NULL, NULL, P_OTHER}
442
        };
443

    
444
        gchar *file;
445

    
446
        file = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, "sylpheed.ini",
447
                           NULL);
448
        if (!is_file_exist(file)) {
449
                g_free(file);
450
                return;
451
        }
452

    
453
        prefs_read_config(param, "Sylpheed", file,
454
                          conv_get_locale_charset_str());
455
        g_free(file);
456

    
457
        cmd.ipcport = ipcport;
458
        if (confdir) {
459
                set_rc_dir(confdir);
460
                g_free(confdir);
461
                confdir = NULL;
462
                cmd.configdir = TRUE;
463
        }
464
}
465
#endif /* G_OS_WIN32 */
466

    
467
#if defined(G_OS_WIN32) || defined(__APPLE__)
468
static void fix_font_setting(void)
469
{
470
        const gchar *str = NULL;
471

    
472
        if (!conv_is_ja_locale())
473
                return;
474

    
475
        if (prefs_common.textfont &&
476
            strcmp(prefs_common.textfont, DEFAULT_MESSAGE_FONT) != 0) {
477
                if (gtkut_font_can_load(prefs_common.textfont)) {
478
                        debug_print("font '%s' load ok\n", prefs_common.textfont);
479
                        return;
480
                }
481
                debug_print("font '%s' load failed\n", prefs_common.textfont);
482
        }
483

    
484
        debug_print("fixing prefs_common.textfont setting\n");
485

    
486
#ifdef G_OS_WIN32
487
        str = "MS Gothic 12";
488
#else /* __APPLE__ */
489
        str = "Hiragino Kaku Gothic Pro Light 13";
490
#endif
491

    
492
        if (!gtkut_font_can_load(str)) {
493
#ifdef G_OS_WIN32
494
                debug_print("font '%s' load failed\n", str);
495
                str = "\xef\xbc\xad\xef\xbc\xb3 \xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf 12";
496
                if (!gtkut_font_can_load(str)) {
497
                        debug_print("font '%s' load failed\n", str);
498
                        str = NULL;
499
                }
500
#else /* __APPLE__ */
501
                debug_print("font '%s' load failed\n", str);
502
                str = NULL;
503
#endif
504
        }
505

    
506
        if (str) {
507
                debug_print("font '%s' load ok\n", str);
508
                g_free(prefs_common.textfont);
509
                prefs_common.textfont = g_strdup(str);
510
        } else
511
                g_warning("failed to load text font!");
512
}
513
#endif
514

    
515
static void parse_cmd_opt(int argc, char *argv[])
516
{
517
        gint i;
518

    
519
        for (i = 1; i < argc; i++) {
520
                if (!strncmp(argv[i], "--debug", 7)) {
521
                        init_console();
522
                        set_debug_mode(TRUE);
523
                } else if (!strncmp(argv[i], "--receive-all", 13))
524
                        cmd.receive_all = TRUE;
525
                else if (!strncmp(argv[i], "--receive", 9))
526
                        cmd.receive = TRUE;
527
                else if (!strncmp(argv[i], "--compose", 9)) {
528
                        const gchar *p = argv[i + 1];
529

    
530
                        cmd.compose = TRUE;
531
                        cmd.compose_mailto = NULL;
532
                        if (p && *p != '\0' && *p != '-') {
533
                                if (!strncmp(p, "mailto:", 7))
534
                                        cmd.compose_mailto = p + 7;
535
                                else
536
                                        cmd.compose_mailto = p;
537
                                i++;
538
                        }
539
                } else if (!strncmp(argv[i], "--attach", 8)) {
540
                        const gchar *p = argv[i + 1];
541
                        gchar *file;
542

    
543
                        while (p && *p != '\0' && *p != '-') {
544
                                if (!cmd.attach_files)
545
                                        cmd.attach_files = g_ptr_array_new();
546
                                if (!g_path_is_absolute(p))
547
                                        file = g_strconcat(get_startup_dir(),
548
                                                           G_DIR_SEPARATOR_S,
549
                                                           p, NULL);
550
                                else
551
                                        file = g_strdup(p);
552
                                g_ptr_array_add(cmd.attach_files, file);
553
                                i++;
554
                                p = argv[i + 1];
555
                        }
556
                } else if (!strncmp(argv[i], "--send", 6)) {
557
                        cmd.send = TRUE;
558
                } else if (!strncmp(argv[i], "--version", 9)) {
559
                        puts("Sylpheed version " VERSION);
560
                        exit(0);
561
                } else if (!strncmp(argv[i], "--status-full", 13)) {
562
                        const gchar *p = argv[i + 1];
563

    
564
                        cmd.status_full = TRUE;
565
                        while (p && *p != '\0' && *p != '-') {
566
                                if (!cmd.status_full_folders)
567
                                        cmd.status_full_folders =
568
                                                g_ptr_array_new();
569
                                g_ptr_array_add(cmd.status_full_folders,
570
                                                g_strdup(p));
571
                                i++;
572
                                p = argv[i + 1];
573
                        }
574
                } else if (!strncmp(argv[i], "--status", 8)) {
575
                        const gchar *p = argv[i + 1];
576

    
577
                        cmd.status = TRUE;
578
                        while (p && *p != '\0' && *p != '-') {
579
                                if (!cmd.status_folders)
580
                                        cmd.status_folders = g_ptr_array_new();
581
                                g_ptr_array_add(cmd.status_folders,
582
                                                g_strdup(p));
583
                                i++;
584
                                p = argv[i + 1];
585
                        }
586
                } else if (!strncmp(argv[i], "--open", 6)) {
587
                        const gchar *p = argv[i + 1];
588

    
589
                        if (p && *p != '\0' && *p != '-') {
590
                                if (cmd.open_msg)
591
                                        g_free(cmd.open_msg);
592
                                cmd.open_msg = g_locale_to_utf8
593
                                        (p, -1, NULL, NULL, NULL);
594
                                i++;
595
                        }
596
                } else if (!strncmp(argv[i], "--configdir", 11)) {
597
                        const gchar *p = argv[i + 1];
598

    
599
                        if (p && *p != '\0' && *p != '-') {
600
                                /* this must only be done at startup */
601
#ifdef G_OS_WIN32
602
                                gchar *utf8dir;
603

    
604
                                utf8dir = g_locale_to_utf8
605
                                        (p, -1, NULL, NULL, NULL);
606
                                if (utf8dir) {
607
                                        set_rc_dir(utf8dir);
608
                                        g_free(utf8dir);
609
                                } else
610
                                        set_rc_dir(p);
611
#else
612
                                set_rc_dir(p);
613
#endif
614
                                cmd.configdir = TRUE;
615
                                i++;
616
                        }
617
#ifdef G_OS_WIN32
618
                } else if (!strncmp(argv[i], "--ipcport", 9)) {
619
                        if (argv[i + 1]) {
620
                                cmd.ipcport = atoi(argv[i + 1]);
621
                                i++;
622
                        }
623
#endif
624
                } else if (!strncmp(argv[i], "--instance-id", 13)) {
625
                        if (argv[i + 1]) {
626
                                instance_id = g_locale_to_utf8
627
                                        (argv[i + 1], -1, NULL, NULL, NULL);
628
                                i++;
629
                        }
630
                } else if (!strncmp(argv[i], "--safe-mode", 11)) {
631
                        cmd.safe_mode = TRUE;
632
                } else if (!strncmp(argv[i], "--exit", 6)) {
633
                        cmd.exit = TRUE;
634
                } else if (!strncmp(argv[i], "--help", 6)) {
635
                        init_console();
636

    
637
                        g_print(_("Usage: %s [OPTIONS ...] [URL]\n"),
638
                                g_basename(argv[0]));
639

    
640
                        g_print("%s\n", _("  --compose [mailto URL] open composition window"));
641
                        g_print("%s\n", _("  --attach file1 [file2]...\n"
642
                                "                         open composition window with specified files\n"
643
                                "                         attached"));
644
                        g_print("%s\n", _("  --receive              receive new messages"));
645
                        g_print("%s\n", _("  --receive-all          receive new messages of all accounts"));
646
                        g_print("%s\n", _("  --send                 send all queued messages"));
647
                        g_print("%s\n", _("  --status [folder]...   show the total number of messages"));
648
                        g_print("%s\n", _("  --status-full [folder]...\n"
649
                                "                         show the status of each folder"));
650
                        g_print("%s\n", _("  --open folderid/msgnum open existing message in a new window"));
651
                        g_print("%s\n", _("  --open <file URL>      open an rfc822 message file in a new window"));
652
                        g_print("%s\n", _("  --configdir dirname    specify directory which stores configuration files"));
653
#ifdef G_OS_WIN32
654
                        g_print("%s\n", _("  --ipcport portnum      specify port for IPC remote commands"));
655
#endif
656
                        g_print("%s\n", _("  --exit                 exit Sylpheed"));
657
                        g_print("%s\n", _("  --debug                debug mode"));
658
                        g_print("%s\n", _("  --safe-mode            safe mode"));
659
                        g_print("%s\n", _("  --help                 display this help and exit"));
660
                        g_print("%s\n", _("  --version              output version information and exit"));
661

    
662
#ifdef G_OS_WIN32
663
                        g_print("\n");
664
                        g_print(_("Press any key..."));
665
                        _getch();
666
#endif
667

    
668
                        cleanup_console();
669
                        exit(1);
670
                } else {
671
                        /* file or URL */
672
                        const gchar *p = argv[i];
673

    
674
                        if (p && *p != '\0') {
675
                                if (!strncmp(p, "mailto:", 7)) {
676
                                        cmd.compose = TRUE;
677
                                        cmd.compose_mailto = p + 7;
678
                                } else {
679
                                        if (cmd.open_msg)
680
                                                g_free(cmd.open_msg);
681
                                        cmd.open_msg = g_locale_to_utf8
682
                                                (p, -1, NULL, NULL, NULL);
683
                                }
684
                        }
685
                }
686
        }
687

    
688
        if (cmd.attach_files && cmd.compose == FALSE) {
689
                cmd.compose = TRUE;
690
                cmd.compose_mailto = NULL;
691
        }
692

    
693
        cmd.argv0 = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
694
        if (!cmd.argv0)
695
                cmd.argv0 = g_strdup(argv[0]);
696
}
697

    
698
static gint get_queued_message_num(void)
699
{
700
        FolderItem *queue;
701

    
702
        queue = folder_get_default_queue();
703
        if (!queue) return -1;
704

    
705
        folder_item_scan(queue);
706
        return queue->total;
707
}
708

    
709
#if USE_THREADS
710
/* enables recursive locking with gdk_thread_enter / gdk_threads_leave */
711
static GStaticRecMutex syl_mutex = G_STATIC_REC_MUTEX_INIT;
712

    
713
static void thread_enter_func(void)
714
{
715
        g_static_rec_mutex_lock(&syl_mutex);
716
#if 0
717
        syl_mutex_lock_count++;
718
        if (syl_mutex_lock_count > 1)
719
                g_print("enter: syl_mutex_lock_count: %d\n", syl_mutex_lock_count);
720
#endif
721
}
722

    
723
static void thread_leave_func(void)
724
{
725
#if 0
726
        syl_mutex_lock_count--;
727
        if (syl_mutex_lock_count > 0)
728
                g_print("leave: syl_mutex_lock_count: %d\n", syl_mutex_lock_count);
729
#endif
730
        g_static_rec_mutex_unlock(&syl_mutex);
731
}
732

    
733
static void event_loop_iteration_func(void)
734
{
735
        if (g_thread_self() != main_thread) {
736
                g_fprintf(stderr, "event_loop_iteration_func called from non-main thread (%p)\n", g_thread_self());
737
                g_usleep(10000);
738
                return;
739
        }
740
        gtk_main_iteration();
741
}
742
#endif
743

    
744
static void app_init(void)
745
{
746
#if USE_THREADS
747
        if (!g_thread_supported())
748
                g_thread_init(NULL);
749
        if (!g_thread_supported())
750
                g_error("g_thread is not supported by glib.");
751
        else {
752
                gdk_threads_set_lock_functions(thread_enter_func,
753
                                               thread_leave_func);
754
                gdk_threads_init();
755
                main_thread = g_thread_self();
756
        }
757
#endif
758
        syl_init();
759

    
760
#if USE_THREADS
761
        set_event_loop_func(event_loop_iteration_func);
762
#endif
763
        prog_version = PROG_VERSION;
764

    
765
#ifdef G_OS_WIN32
766
        read_ini_file();
767
#endif
768
}
769

    
770
static void parse_gtkrc_files(void)
771
{
772
        gchar *userrc;
773

    
774
        /* parse gtkrc files */
775
        userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtkrc-2.0",
776
                             NULL);
777
        gtk_rc_parse(userrc);
778
        g_free(userrc);
779
        userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtk",
780
                             G_DIR_SEPARATOR_S, "gtkrc-2.0", NULL);
781
        gtk_rc_parse(userrc);
782
        g_free(userrc);
783
        userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, "gtkrc", NULL);
784
        gtk_rc_parse(userrc);
785
        g_free(userrc);
786

    
787
        userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
788
        gtk_accel_map_load(userrc);
789
        g_free(userrc);
790
}
791

    
792
static void setup_rc_dir(void)
793
{
794
#if !defined(G_OS_WIN32) && !defined(__APPLE__)
795
        CHDIR_EXIT_IF_FAIL(get_home_dir(), 1);
796

    
797
        /* backup if old rc file exists */
798
        if (!cmd.configdir && is_file_exist(RC_DIR)) {
799
                if (rename_force(RC_DIR, RC_DIR ".bak") < 0)
800
                        FILE_OP_ERROR(RC_DIR, "rename");
801
        }
802

    
803
        /* migration from ~/.sylpheed to ~/.sylpheed-2.0 */
804
        if (!cmd.configdir && !is_dir_exist(RC_DIR)) {
805
                const gchar *envstr;
806
                AlertValue val;
807

    
808
                /* check for filename encoding */
809
                if (conv_get_locale_charset() != C_UTF_8) {
810
                        envstr = g_getenv("G_FILENAME_ENCODING");
811
                        if (!envstr)
812
                                envstr = g_getenv("G_BROKEN_FILENAMES");
813
                        if (!envstr) {
814
                                val = alertpanel(_("Filename encoding"),
815
                                                 _("The locale encoding is not UTF-8, but the environmental variable G_FILENAME_ENCODING is not set.\n"
816
                                                   "If the locale encoding is used for file name or directory name, it will not work correctly.\n"
817
                                                   "In that case, you must set the following environmental variable (see README for detail):\n"
818
                                                   "\n"
819
                                                   "\tG_FILENAME_ENCODING=@locale\n"
820
                                                   "\n"
821
                                                   "Continue?"),
822
                                                 GTK_STOCK_OK, GTK_STOCK_QUIT,
823
                                                 NULL);
824
                                if (G_ALERTDEFAULT != val)
825
                                        exit(1);
826
                        }
827
                }
828

    
829
                if (make_dir(RC_DIR) < 0)
830
                        exit(1);
831
                if (is_dir_exist(OLD_RC_DIR))
832
                        migrate_old_config();
833
        }
834
#endif /* !G_OS_WIN32 && !__APPLE__ */
835

    
836
        syl_setup_rc_dir();
837
}
838

    
839
static void app_restart(void)
840
{
841
        gchar *cmdline;
842
        GError *error = NULL;
843
#ifdef G_OS_WIN32
844
        if (cmd.configdir) {
845
                cmdline = g_strdup_printf("\"%s\"%s --configdir \"%s\" --ipcport %d",
846
                                          cmd.argv0,
847
                                          get_debug_mode() ? " --debug" : "",
848
                                          get_rc_dir(),
849
                                          cmd.ipcport);
850
        } else {
851
                cmdline = g_strdup_printf("\"%s\"%s --ipcport %d",
852
                                          cmd.argv0,
853
                                          get_debug_mode() ? " --debug" : "",
854
                                          cmd.ipcport);
855
        }
856
#else
857
        if (cmd.configdir) {
858
                cmdline = g_strdup_printf("\"%s\"%s --configdir \"%s\"",
859
                                          cmd.argv0,
860
                                          get_debug_mode() ? " --debug" : "",
861
                                          get_rc_dir());
862
        } else {
863
                cmdline = g_strdup_printf("\"%s\"%s",
864
                                          cmd.argv0,
865
                                          get_debug_mode() ? " --debug" : "");
866
        }
867
#endif
868
        if (!g_spawn_command_line_async(cmdline, &error)) {
869
                alertpanel_error("restart failed\n'%s'\n%s", cmdline, error->message);
870
                g_error_free(error);
871
        }
872
        g_free(cmdline);
873
}
874

    
875
void app_will_restart(gboolean force)
876
{
877
        cmd.restart = TRUE;
878
        app_will_exit(force);
879
        /* canceled */
880
        cmd.restart = FALSE;
881
}
882

    
883
void app_will_exit(gboolean force)
884
{
885
        MainWindow *mainwin;
886
        gchar *filename;
887
        static gboolean on_exit = FALSE;
888
        GList *cur;
889

    
890
        if (on_exit)
891
                return;
892
        on_exit = TRUE;
893

    
894
        mainwin = main_window_get();
895

    
896
        if (!force && compose_get_compose_list()) {
897
                if (alertpanel(_("Notice"),
898
                               _("Composing message exists. Really quit?"),
899
                               GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL)
900
                    != G_ALERTDEFAULT) {
901
                        on_exit = FALSE;
902
                        return;
903
                }
904
                manage_window_focus_in(mainwin->window, NULL, NULL);
905
        }
906

    
907
        if (!force &&
908
            prefs_common.warn_queued_on_exit && get_queued_message_num() > 0) {
909
                if (alertpanel(_("Queued messages"),
910
                               _("Some unsent messages are queued. Exit now?"),
911
                               GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL)
912
                    != G_ALERTDEFAULT) {
913
                        on_exit = FALSE;
914
                        return;
915
                }
916
                manage_window_focus_in(mainwin->window, NULL, NULL);
917
        }
918

    
919
        if (force)
920
                g_signal_emit_by_name(syl_app_get(), "app-force-exit");
921
        g_signal_emit_by_name(syl_app_get(), "app-exit");
922

    
923
        inc_autocheck_timer_remove();
924

    
925
        if (prefs_common.clean_on_exit)
926
                main_window_empty_trash(mainwin,
927
                                        !force && prefs_common.ask_on_clean);
928

    
929
        for (cur = account_get_list(); cur != NULL; cur = cur->next) {
930
                PrefsAccount *ac = (PrefsAccount *)cur->data;
931
                if (ac->protocol == A_IMAP4 && ac->imap_clear_cache_on_exit &&
932
                    ac->folder)
933
                        procmsg_remove_all_cached_messages(FOLDER(ac->folder));
934
        }
935

    
936
        syl_plugin_unload_all();
937

    
938
        trayicon_destroy(mainwin->tray_icon);
939

    
940
        /* save all state before exiting */
941
        summary_write_cache(mainwin->summaryview);
942
        main_window_get_size(mainwin);
943
        main_window_get_position(mainwin);
944
        syl_save_all_state();
945
        addressbook_export_to_file();
946

    
947
        filename = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
948
        gtk_accel_map_save(filename);
949
        g_free(filename);
950

    
951
        /* remove temporary files, close log file, socket cleanup */
952
#if USE_SSL
953
        ssl_done();
954
#endif
955
        syl_cleanup();
956
        lock_socket_remove();
957

    
958
#ifdef USE_UPDATE_CHECK_PLUGIN
959
#ifdef G_OS_WIN32
960
        cur = gtk_window_list_toplevels();
961
        g_list_foreach(cur, (GFunc)gtk_widget_hide, NULL);
962
        g_list_free(cur);
963
        update_check_spawn_plugin_updater();
964
#endif
965
#endif
966

    
967
        cleanup_console();
968

    
969
        if (gtk_main_level() > 0)
970
                gtk_main_quit();
971

    
972
        if (cmd.restart)
973
                app_restart();
974

    
975
        exit(0);
976
}
977

    
978
#if 0
979
#if USE_GPGME
980
static void idle_function_for_gpgme(void)
981
{
982
        while (gtk_events_pending())
983
                gtk_main_iteration();
984
}
985
#endif /* USE_GPGME */
986
#endif /* 0 */
987

    
988
static void check_gpg(void)
989
{
990
#if USE_GPGME
991
        const gchar *version;
992
        gpgme_error_t err = 0;
993

    
994
        version = gpgme_check_version("1.0.0");
995
        if (version) {
996
                debug_print("GPGME Version: %s\n", version);
997
                err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
998
                if (err)
999
                        debug_print("gpgme_engine_check_version: %s\n",
1000
                                    gpgme_strerror(err));
1001
        }
1002

    
1003
        if (version && !err) {
1004
                /* Also does some gpgme init */
1005
                gpgme_engine_info_t engineInfo;
1006

    
1007
#if HAVE_LOCALE_H
1008
                gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
1009
                gpgme_set_locale(NULL, LC_MESSAGES,
1010
                                 setlocale(LC_MESSAGES, NULL));
1011
#endif
1012

    
1013
                if (!gpgme_get_engine_info(&engineInfo)) {
1014
                        while (engineInfo) {
1015
                                debug_print("GPGME Protocol: %s\n      Version: %s\n",
1016
                                            gpgme_get_protocol_name
1017
                                                (engineInfo->protocol),
1018
                                            engineInfo->version ?
1019
                                            engineInfo->version : "(unknown)");
1020
                                engineInfo = engineInfo->next;
1021
                        }
1022
                }
1023

    
1024
                procmsg_set_decrypt_message_func
1025
                        (rfc2015_open_message_decrypted);
1026
                procmsg_set_auto_decrypt_message(TRUE);
1027
        } else {
1028
                rfc2015_disable_all();
1029

    
1030
                if (prefs_common.gpg_warning) {
1031
                        AlertValue val;
1032

    
1033
                        val = alertpanel_message_with_disable
1034
                                (_("Warning"),
1035
                                 _("GnuPG is not installed properly, or its version is too old.\n"
1036
                                   "OpenPGP support disabled."),
1037
                                 ALERT_WARNING);
1038
                        if (val & G_ALERTDISABLE)
1039
                                prefs_common.gpg_warning = FALSE;
1040
                }
1041
        }
1042
        /* FIXME: This function went away.  We can either block until gpgme
1043
         * operations finish (currently implemented) or register callbacks
1044
         * with the gtk main loop via the gpgme io callback interface instead.
1045
         *
1046
         * gpgme_register_idle(idle_function_for_gpgme);
1047
         */
1048
#endif
1049
}
1050

    
1051
static void default_log_func(const gchar *log_domain, GLogLevelFlags log_level,
1052
                             const gchar *message, gpointer user_data)
1053
{
1054
        gchar *prefix = "";
1055
        gchar *file_prefix = "";
1056
        LogType level = LOG_NORMAL;
1057
        gchar *str;
1058
        const gchar *message_;
1059

    
1060
        switch (log_level) {
1061
        case G_LOG_LEVEL_ERROR:
1062
                prefix = "ERROR";
1063
                file_prefix = "*** ";
1064
                level = LOG_ERROR;
1065
                break;
1066
        case G_LOG_LEVEL_CRITICAL:
1067
                prefix = "CRITICAL";
1068
                file_prefix = "** ";
1069
                level = LOG_WARN;
1070
                break;
1071
        case G_LOG_LEVEL_WARNING:
1072
                prefix = "WARNING";
1073
                file_prefix = "** ";
1074
                level = LOG_WARN;
1075
                break;
1076
        case G_LOG_LEVEL_MESSAGE:
1077
                prefix = "Message";
1078
                file_prefix = "* ";
1079
                level = LOG_MSG;
1080
                break;
1081
        case G_LOG_LEVEL_INFO:
1082
                prefix = "INFO";
1083
                file_prefix = "* ";
1084
                level = LOG_MSG;
1085
                break;
1086
        case G_LOG_LEVEL_DEBUG:
1087
                prefix = "DEBUG";
1088
                break;
1089
        default:
1090
                prefix = "LOG";
1091
                break;
1092
        }
1093

    
1094
        if (!message)
1095
                message_ = "(NULL) message";
1096
        else
1097
                message_ = message;
1098
        if (log_domain)
1099
                str = g_strconcat(log_domain, "-", prefix, ": ", message_, "\n",
1100
                                  NULL);
1101
        else
1102
                str = g_strconcat(prefix, ": ", message_, "\n", NULL);
1103
        log_window_append(str, level);
1104
        log_write(str, file_prefix);
1105
        g_free(str);
1106

    
1107
        g_log_default_handler(log_domain, log_level, message, user_data);
1108
}
1109

    
1110
static void set_log_handlers(gboolean enable)
1111
{
1112
#if GLIB_CHECK_VERSION(2, 6, 0)
1113
        if (enable)
1114
                g_log_set_default_handler(default_log_func, NULL);
1115
        else
1116
                g_log_set_default_handler(g_log_default_handler, NULL);
1117
#else
1118
        static guint handler_id[4] = {0, 0, 0, 0};
1119

    
1120
        if (enable) {
1121
                handler_id[0] = g_log_set_handler
1122
                        ("GLib", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1123
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1124
                handler_id[1] = g_log_set_handler
1125
                        ("Gtk", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1126
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1127
                handler_id[2] = g_log_set_handler
1128
                        ("LibSylph", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1129
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1130
                handler_id[3] = g_log_set_handler
1131
                        ("Sylpheed", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1132
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1133
        } else {
1134
                g_log_remove_handler("GLib", handler_id[0]);
1135
                g_log_remove_handler("Gtk", handler_id[1]);
1136
                g_log_remove_handler("LibSylph", handler_id[2]);
1137
                g_log_remove_handler("Sylpheed", handler_id[3]);
1138
                handler_id[0] = 0;
1139
                handler_id[1] = 0;
1140
                handler_id[2] = 0;
1141
                handler_id[3] = 0;
1142
        }
1143
#endif
1144
}
1145

    
1146
#ifdef G_OS_WIN32
1147
static BOOL WINAPI
1148
ctrl_handler(DWORD dwctrltype)
1149
{
1150
        log_print("ctrl_handler: received %d\n", dwctrltype);
1151
        app_will_exit(TRUE);
1152

    
1153
        return TRUE;
1154
}
1155

    
1156
static LRESULT CALLBACK
1157
wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
1158
{
1159
        switch (message) {
1160
        case WM_POWERBROADCAST:
1161
                debug_print("WM_POWERBROADCAST received: wparam = %d\n",
1162
                            wparam);
1163
                if (wparam == PBT_APMSUSPEND || wparam == PBT_APMSTANDBY) {
1164
                        debug_print("suspend now\n");
1165
                        inc_autocheck_timer_remove();
1166
                } else if (wparam == PBT_APMRESUMESUSPEND ||
1167
                           wparam == PBT_APMRESUMESTANDBY) {
1168
                        debug_print("resume now\n");
1169
                        inc_autocheck_timer_set();
1170
                }
1171
                break;
1172
        case WM_ENDSESSION:
1173
                if (wparam == 1) {
1174
                        log_print("WM_ENDSESSION received: system is quitting\n");
1175
                        app_will_exit(TRUE);
1176
                }
1177
                break;
1178
        default:
1179
                break;
1180
        }
1181

    
1182
        return DefWindowProc(hwnd, message, wparam, lparam);
1183
}
1184

    
1185
static void register_system_events(void)
1186
{
1187
        WNDCLASS wclass;
1188
        static HWND hwnd = NULL;
1189
        static BOOL ctrl_handler_set = FALSE;
1190
        ATOM klass;
1191
        HINSTANCE hmodule = GetModuleHandle(NULL);
1192

    
1193
        if (init_console_done && !ctrl_handler_set) {
1194
                debug_print("register_system_events(): SetConsoleCtrlHandler\n");
1195
                ctrl_handler_set = SetConsoleCtrlHandler(ctrl_handler, TRUE);
1196
                if (!ctrl_handler_set)
1197
                        g_warning("SetConsoleCtrlHandler() failed\n");
1198
        }
1199

    
1200
        if (hwnd)
1201
                return;
1202

    
1203
        debug_print("register_system_events(): RegisterClass\n");
1204

    
1205
        memset(&wclass, 0, sizeof(WNDCLASS));
1206
        wclass.lpszClassName = "sylpheed-observer";
1207
        wclass.lpfnWndProc   = wndproc;
1208
        wclass.hInstance     = hmodule;
1209

    
1210
        klass = RegisterClass(&wclass);
1211
        if (!klass)
1212
                return;
1213

    
1214
        hwnd = CreateWindow(MAKEINTRESOURCE(klass), NULL, WS_POPUP,
1215
                            0, 0, 1, 1, NULL, NULL, hmodule, NULL);
1216
        if (!hwnd)
1217
                UnregisterClass(MAKEINTRESOURCE(klass), hmodule);
1218
}
1219
#else /* G_OS_WIN32 */
1220
static void sig_handler(gint signum)
1221
{
1222
        debug_print("signal %d received\n", signum);
1223

    
1224
        switch (signum) {
1225
        case SIGHUP:
1226
        case SIGINT:
1227
        case SIGTERM:
1228
        case SIGQUIT:
1229
                app_will_exit(TRUE);
1230
                break;
1231
        default:
1232
                break;
1233
        }
1234
}
1235

    
1236
static void register_system_events(void)
1237
{
1238
        struct sigaction sa;
1239

    
1240
        memset(&sa, 0, sizeof(sa));
1241
        sa.sa_handler = sig_handler;
1242
        sa.sa_flags = SA_RESTART;
1243

    
1244
        sigemptyset(&sa.sa_mask);
1245
        sigaddset(&sa.sa_mask, SIGHUP);
1246
        sigaddset(&sa.sa_mask, SIGINT);
1247
        sigaddset(&sa.sa_mask, SIGTERM);
1248
        sigaddset(&sa.sa_mask, SIGQUIT);
1249
        sigaddset(&sa.sa_mask, SIGPIPE);
1250

    
1251
        sigaction(SIGHUP, &sa, NULL);
1252
        sigaction(SIGINT, &sa, NULL);
1253
        sigaction(SIGTERM, &sa, NULL);
1254
        sigaction(SIGQUIT, &sa, NULL);
1255
        sigaction(SIGPIPE, &sa, NULL);
1256
}
1257
#endif
1258

    
1259
#define ADD_SYM(sym)        syl_plugin_add_symbol(#sym, sym)
1260

    
1261
static void plugin_init(void)
1262
{
1263
        MainWindow *mainwin;
1264
        gchar *path;
1265

    
1266
        mainwin = main_window_get();
1267

    
1268
        STATUSBAR_PUSH(mainwin, _("Loading plug-ins..."));
1269

    
1270
        if (syl_plugin_init_lib() != 0) {
1271
                STATUSBAR_POP(mainwin);
1272
                return;
1273
        }
1274

    
1275
        if (cmd.safe_mode) {
1276
                debug_print("plugin_init: safe mode enabled, skipping plug-in loading.\n");
1277
                STATUSBAR_POP(mainwin);
1278
                return;
1279
        }
1280

    
1281
        ADD_SYM(prog_version);
1282
        ADD_SYM(app_will_exit);
1283

    
1284
        ADD_SYM(main_window_lock);
1285
        ADD_SYM(main_window_unlock);
1286
        ADD_SYM(main_window_get);
1287
        ADD_SYM(main_window_popup);
1288

    
1289
        syl_plugin_add_symbol("main_window_menu_factory",
1290
                              mainwin->menu_factory);
1291
        syl_plugin_add_symbol("main_window_statusbar", mainwin->statusbar);
1292

    
1293
        ADD_SYM(folderview_get);
1294
        ADD_SYM(folderview_add_sub_widget);
1295
        ADD_SYM(folderview_select);
1296
        ADD_SYM(folderview_unselect);
1297
        ADD_SYM(folderview_select_next_unread);
1298
        ADD_SYM(folderview_get_selected_item);
1299
        ADD_SYM(folderview_check_new);
1300
        ADD_SYM(folderview_check_new_item);
1301
        ADD_SYM(folderview_check_new_all);
1302
        ADD_SYM(folderview_update_item);
1303
        ADD_SYM(folderview_update_item_foreach);
1304
        ADD_SYM(folderview_update_all_updated);
1305
        ADD_SYM(folderview_check_new_selected);
1306

    
1307
        syl_plugin_add_symbol("folderview_mail_popup_factory",
1308
                              mainwin->folderview->mail_factory);
1309
        syl_plugin_add_symbol("folderview_imap_popup_factory",
1310
                              mainwin->folderview->imap_factory);
1311
        syl_plugin_add_symbol("folderview_news_popup_factory",
1312
                              mainwin->folderview->news_factory);
1313

    
1314
        syl_plugin_add_symbol("summaryview", mainwin->summaryview);
1315
        syl_plugin_add_symbol("summaryview_popup_factory",
1316
                              mainwin->summaryview->popupfactory);
1317

    
1318
        ADD_SYM(summary_select_by_msgnum);
1319
        ADD_SYM(summary_select_by_msginfo);
1320
        ADD_SYM(summary_lock);
1321
        ADD_SYM(summary_unlock);
1322
        ADD_SYM(summary_is_locked);
1323
        ADD_SYM(summary_is_read_locked);
1324
        ADD_SYM(summary_write_lock);
1325
        ADD_SYM(summary_write_unlock);
1326
        ADD_SYM(summary_is_write_locked);
1327
        ADD_SYM(summary_get_current_folder);
1328
        ADD_SYM(summary_get_selection_type);
1329
        ADD_SYM(summary_get_selected_msg_list);
1330
        ADD_SYM(summary_get_msg_list);
1331
        ADD_SYM(summary_show_queued_msgs);
1332
        ADD_SYM(summary_redisplay_msg);
1333
        ADD_SYM(summary_open_msg);
1334
        ADD_SYM(summary_view_source);
1335
        ADD_SYM(summary_reedit);
1336
        ADD_SYM(summary_update_selected_rows);
1337
        ADD_SYM(summary_update_by_msgnum);
1338

    
1339
        ADD_SYM(messageview_create_with_new_window);
1340
        ADD_SYM(messageview_show);
1341

    
1342
        ADD_SYM(compose_new);
1343
        ADD_SYM(compose_entry_set);
1344
        ADD_SYM(compose_entry_append);
1345
        ADD_SYM(compose_entry_get_text);
1346
        ADD_SYM(compose_lock);
1347
        ADD_SYM(compose_unlock);
1348

    
1349
        ADD_SYM(foldersel_folder_sel);
1350
        ADD_SYM(foldersel_folder_sel_full);
1351

    
1352
        ADD_SYM(input_dialog);
1353
        ADD_SYM(input_dialog_with_invisible);
1354

    
1355
        ADD_SYM(manage_window_set_transient);
1356
        ADD_SYM(manage_window_signals_connect);
1357
        ADD_SYM(manage_window_get_focus_window);
1358

    
1359
        ADD_SYM(inc_mail);
1360
        ADD_SYM(inc_is_active);
1361
        ADD_SYM(inc_lock);
1362
        ADD_SYM(inc_unlock);
1363

    
1364
#if USE_UPDATE_CHECK
1365
        ADD_SYM(update_check);
1366
        ADD_SYM(update_check_set_check_url);
1367
        ADD_SYM(update_check_get_check_url);
1368
        ADD_SYM(update_check_set_download_url);
1369
        ADD_SYM(update_check_get_download_url);
1370
        ADD_SYM(update_check_set_jump_url);
1371
        ADD_SYM(update_check_get_jump_url);
1372
#ifdef USE_UPDATE_CHECK_PLUGIN
1373
        ADD_SYM(update_check_set_check_plugin_url);
1374
        ADD_SYM(update_check_get_check_plugin_url);
1375
        ADD_SYM(update_check_set_jump_plugin_url);
1376
        ADD_SYM(update_check_get_jump_plugin_url);
1377
#endif /* USE_UPDATE_CHECK_PLUGIN */
1378
#endif
1379

    
1380
        ADD_SYM(alertpanel_full);
1381
        ADD_SYM(alertpanel);
1382
        ADD_SYM(alertpanel_message);
1383
        ADD_SYM(alertpanel_message_with_disable);
1384

    
1385
        ADD_SYM(send_message);
1386
        ADD_SYM(send_message_queue_all);
1387
        ADD_SYM(send_message_set_reply_flag);
1388
        ADD_SYM(send_message_set_forward_flags);
1389

    
1390
        ADD_SYM(notification_window_open);
1391
        ADD_SYM(notification_window_set_message);
1392
        ADD_SYM(notification_window_close);
1393

    
1394
        syl_plugin_signal_connect("plugin-load", G_CALLBACK(load_cb), NULL);
1395

    
1396
        /* loading plug-ins from user plug-in directory */
1397
        path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, PLUGIN_DIR, NULL);
1398
        syl_plugin_load_all(path);
1399
        g_free(path);
1400

    
1401
        /* loading plug-ins from system plug-in directory */
1402
#ifdef G_OS_WIN32
1403
        path = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, PLUGIN_DIR,
1404
                           NULL);
1405
        syl_plugin_load_all(path);
1406
        g_free(path);
1407
#else
1408
        syl_plugin_load_all(PLUGINDIR);
1409
#endif
1410

    
1411
        STATUSBAR_POP(mainwin);
1412
}
1413

    
1414
static gchar *get_socket_name(void)
1415
{
1416
        static gchar *filename = NULL;
1417

    
1418
        if (filename == NULL) {
1419
                filename = g_strdup_printf("%s%c%s-%d",
1420
                                           g_get_tmp_dir(), G_DIR_SEPARATOR,
1421
                                           instance_id ? instance_id : "sylpheed",
1422
#if HAVE_GETUID
1423
                                           getuid());
1424
#else
1425
                                           0);
1426
#endif
1427
        }
1428

    
1429
        return filename;
1430
}
1431

    
1432
static gint prohibit_duplicate_launch(void)
1433
{
1434
        gint sock;
1435

    
1436
#ifdef G_OS_WIN32
1437
        HANDLE hmutex;
1438
        const gchar *ins_id = instance_id ? instance_id : "Sylpheed";
1439
        gushort port = cmd.ipcport ? cmd.ipcport : REMOTE_CMD_PORT;
1440

    
1441
        debug_print("prohibit_duplicate_launch: checking mutex: %s\n", ins_id);
1442
        hmutex = CreateMutexA(NULL, FALSE, ins_id);
1443
        if (!hmutex) {
1444
                g_warning("cannot create Mutex: %s\n", ins_id);
1445
                return -1;
1446
        }
1447
        if (GetLastError() != ERROR_ALREADY_EXISTS) {
1448
                debug_print("prohibit_duplicate_launch: creating socket: port %d\n", port);
1449
                sock = fd_open_inet(port);
1450
                if (sock < 0)
1451
                        return 0;
1452
                return sock;
1453
        }
1454

    
1455
        debug_print("prohibit_duplicate_launch: connecting to socket: port %d\n", port);
1456
        sock = fd_connect_inet(port);
1457
        if (sock < 0)
1458
                return -1;
1459
#else
1460
        gchar *path;
1461

    
1462
        path = get_socket_name();
1463
        debug_print("prohibit_duplicate_launch: checking socket: %s\n", path);
1464
        sock = fd_connect_unix(path);
1465
        if (sock < 0) {
1466
                debug_print("prohibit_duplicate_launch: creating socket: %s\n", path);
1467
                g_unlink(path);
1468
                return fd_open_unix(path);
1469
        }
1470
#endif
1471

    
1472
        /* remote command mode */
1473

    
1474
        debug_print(_("another Sylpheed is already running.\n"));
1475

    
1476
        if (cmd.receive_all)
1477
                fd_write_all(sock, "receive_all\n", 12);
1478
        else if (cmd.receive)
1479
                fd_write_all(sock, "receive\n", 8);
1480
        else if (cmd.compose && cmd.attach_files) {
1481
                gchar *str, *compose_str;
1482
                gint i;
1483

    
1484
                if (cmd.compose_mailto)
1485
                        compose_str = g_strdup_printf("compose_attach %s\n",
1486
                                                      cmd.compose_mailto);
1487
                else
1488
                        compose_str = g_strdup("compose_attach\n");
1489

    
1490
                fd_write_all(sock, compose_str, strlen(compose_str));
1491
                g_free(compose_str);
1492

    
1493
                for (i = 0; i < cmd.attach_files->len; i++) {
1494
                        str = g_ptr_array_index(cmd.attach_files, i);
1495
                        fd_write_all(sock, str, strlen(str));
1496
                        fd_write_all(sock, "\n", 1);
1497
                }
1498

    
1499
                fd_write_all(sock, ".\n", 2);
1500
        } else if (cmd.compose) {
1501
                gchar *compose_str;
1502

    
1503
                if (cmd.compose_mailto)
1504
                        compose_str = g_strdup_printf
1505
                                ("compose %s\n", cmd.compose_mailto);
1506
                else
1507
                        compose_str = g_strdup("compose\n");
1508

    
1509
                fd_write_all(sock, compose_str, strlen(compose_str));
1510
                g_free(compose_str);
1511
        } else if (cmd.send) {
1512
                fd_write_all(sock, "send\n", 5);
1513
        } else if (cmd.status || cmd.status_full) {
1514
                gchar buf[BUFFSIZE];
1515
                gint i;
1516
                const gchar *command;
1517
                GPtrArray *folders;
1518
                gchar *folder;
1519

    
1520
                command = cmd.status_full ? "status-full\n" : "status\n";
1521
                folders = cmd.status_full ? cmd.status_full_folders :
1522
                        cmd.status_folders;
1523

    
1524
                fd_write_all(sock, command, strlen(command));
1525
                for (i = 0; folders && i < folders->len; ++i) {
1526
                        folder = g_ptr_array_index(folders, i);
1527
                        fd_write_all(sock, folder, strlen(folder));
1528
                        fd_write_all(sock, "\n", 1);
1529
                }
1530
                fd_write_all(sock, ".\n", 2);
1531
                for (;;) {
1532
                        fd_gets(sock, buf, sizeof(buf));
1533
                        if (!strncmp(buf, ".\n", 2)) break;
1534
                        fputs(buf, stdout);
1535
                }
1536
        } else if (cmd.open_msg) {
1537
                gchar *str;
1538

    
1539
                str = g_strdup_printf("open %s\n", cmd.open_msg);
1540
                fd_write_all(sock, str, strlen(str));
1541
                g_free(str);
1542
        } else if (cmd.exit) {
1543
                fd_write_all(sock, "exit\n", 5);
1544
        } else {
1545
#ifdef G_OS_WIN32
1546
                HWND hwnd;
1547

    
1548
                fd_write_all(sock, "popup\n", 6);
1549
                if (fd_read(sock, (gchar *)&hwnd, sizeof(hwnd)) == sizeof(hwnd))
1550
                        SetForegroundWindow(hwnd);
1551
#else
1552
                fd_write_all(sock, "popup\n", 6);
1553
#endif
1554
        }
1555

    
1556
        fd_close(sock);
1557
        return -1;
1558
}
1559

    
1560
static gint lock_socket_remove(void)
1561
{
1562
#ifndef G_OS_WIN32
1563
        gchar *filename;
1564
#endif
1565

    
1566
        if (lock_socket < 0) return -1;
1567

    
1568
        if (lock_socket_tag > 0)
1569
                g_source_remove(lock_socket_tag);
1570
        if (lock_ch) {
1571
                g_io_channel_shutdown(lock_ch, FALSE, NULL);
1572
                g_io_channel_unref(lock_ch);
1573
                lock_ch = NULL;
1574
        }
1575

    
1576
#ifndef G_OS_WIN32
1577
        filename = get_socket_name();
1578
        debug_print("lock_socket_remove: removing socket: %s\n", filename);
1579
        g_unlink(filename);
1580
#endif
1581

    
1582
        return 0;
1583
}
1584

    
1585
static GPtrArray *get_folder_item_list(gint sock)
1586
{
1587
        gchar buf[BUFFSIZE];
1588
        FolderItem *item;
1589
        GPtrArray *folders = NULL;
1590

    
1591
        for (;;) {
1592
                fd_gets(sock, buf, sizeof(buf));
1593
                if (!strncmp(buf, ".\n", 2)) break;
1594
                strretchomp(buf);
1595
                if (!folders) folders = g_ptr_array_new();
1596
                item = folder_find_item_from_identifier(buf);
1597
                if (item)
1598
                        g_ptr_array_add(folders, item);
1599
                else
1600
                        g_warning("no such folder: %s\n", buf);
1601
        }
1602

    
1603
        return folders;
1604
}
1605

    
1606
static gboolean lock_socket_input_cb(GIOChannel *source, GIOCondition condition,
1607
                                     gpointer data)
1608
{
1609
        MainWindow *mainwin = (MainWindow *)data;
1610
        gint fd, sock;
1611
        gchar buf[BUFFSIZE];
1612

    
1613
#if USE_THREADS
1614
        gdk_threads_enter();
1615
#endif
1616

    
1617
        fd = g_io_channel_unix_get_fd(source);
1618
        sock = fd_accept(fd);
1619
        fd_gets(sock, buf, sizeof(buf));
1620

    
1621
        if (!strncmp(buf, "popup", 5)) {
1622
#ifdef G_OS_WIN32
1623
                HWND hwnd;
1624

    
1625
                hwnd = (HWND)gdk_win32_drawable_get_handle
1626
                        (GDK_DRAWABLE(mainwin->window->window));
1627
                fd_write(sock, (gchar *)&hwnd, sizeof(hwnd));
1628
                if (mainwin->window_hidden)
1629
                        main_window_popup(mainwin);
1630
#else
1631
                main_window_popup(mainwin);
1632
#endif
1633
        } else if (!strncmp(buf, "receive_all", 11)) {
1634
                main_window_popup(mainwin);
1635
                if (!gtkut_window_modal_exist())
1636
                        inc_all_account_mail(mainwin, FALSE);
1637
        } else if (!strncmp(buf, "receive", 7)) {
1638
                main_window_popup(mainwin);
1639
                if (!gtkut_window_modal_exist())
1640
                        inc_mail(mainwin);
1641
        } else if (!strncmp(buf, "compose_attach", 14)) {
1642
                GPtrArray *files;
1643
                gchar *mailto;
1644

    
1645
                mailto = g_strdup(buf + strlen("compose_attach") + 1);
1646
                files = g_ptr_array_new();
1647
                while (fd_gets(sock, buf, sizeof(buf)) > 0) {
1648
                        if (buf[0] == '.' && buf[1] == '\n') break;
1649
                        strretchomp(buf);
1650
                        g_ptr_array_add(files, g_strdup(buf));
1651
                }
1652
                open_compose_new(mailto, files);
1653
                ptr_array_free_strings(files);
1654
                g_ptr_array_free(files, TRUE);
1655
                g_free(mailto);
1656
        } else if (!strncmp(buf, "compose", 7)) {
1657
                open_compose_new(buf + strlen("compose") + 1, NULL);
1658
        } else if (!strncmp(buf, "send", 4)) {
1659
                send_queue();
1660
        } else if (!strncmp(buf, "status-full", 11) ||
1661
                   !strncmp(buf, "status", 6)) {
1662
                gchar *status;
1663
                GPtrArray *folders;
1664

    
1665
                folders = get_folder_item_list(sock);
1666
                status = folder_get_status
1667
                        (folders, !strncmp(buf, "status-full", 11));
1668
                fd_write_all(sock, status, strlen(status));
1669
                fd_write_all(sock, ".\n", 2);
1670
                g_free(status);
1671
                if (folders) g_ptr_array_free(folders, TRUE);
1672
        } else if (!strncmp(buf, "open", 4)) {
1673
                strretchomp(buf);
1674
                if (strlen(buf) < 6 || buf[4] != ' ') {
1675
                        fd_close(sock);
1676
#if USE_THREADS
1677
                        gdk_threads_leave();
1678
#endif
1679
                        return TRUE;
1680
                }
1681
                open_message(buf + 5);
1682
        } else if (!strncmp(buf, "exit", 4)) {
1683
                fd_close(sock);
1684
                app_will_exit(TRUE);
1685
        }
1686

    
1687
        fd_close(sock);
1688

    
1689
#if USE_THREADS
1690
        gdk_threads_leave();
1691
#endif
1692

    
1693
        return TRUE;
1694
}
1695

    
1696
static void remote_command_exec(void)
1697
{
1698
        MainWindow *mainwin;
1699

    
1700
        mainwin = main_window_get();
1701

    
1702
        if (prefs_common.open_inbox_on_startup) {
1703
                FolderItem *item;
1704
                PrefsAccount *ac;
1705

    
1706
                ac = account_get_default();
1707
                if (!ac)
1708
                        ac = cur_account;
1709
                item = ac && ac->inbox
1710
                        ? folder_find_item_from_identifier(ac->inbox)
1711
                        : folder_get_default_inbox();
1712
                folderview_select(mainwin->folderview, item);
1713
        }
1714

    
1715
        if (!gtkut_window_modal_exist()) {
1716
                if (cmd.compose)
1717
                        open_compose_new(cmd.compose_mailto, cmd.attach_files);
1718

    
1719
                if (cmd.open_msg)
1720
                        open_message(cmd.open_msg);
1721

    
1722
                if (cmd.receive_all)
1723
                        inc_all_account_mail(mainwin, FALSE);
1724
                else if (prefs_common.chk_on_startup)
1725
                        inc_all_account_mail(mainwin, TRUE);
1726
                else if (cmd.receive)
1727
                        inc_mail(mainwin);
1728

    
1729
                if (cmd.send)
1730
                        send_queue();
1731
        }
1732

    
1733
        if (cmd.attach_files) {
1734
                ptr_array_free_strings(cmd.attach_files);
1735
                g_ptr_array_free(cmd.attach_files, TRUE);
1736
                cmd.attach_files = NULL;
1737
        }
1738
        if (cmd.status_folders) {
1739
                g_ptr_array_free(cmd.status_folders, TRUE);
1740
                cmd.status_folders = NULL;
1741
        }
1742
        if (cmd.status_full_folders) {
1743
                g_ptr_array_free(cmd.status_full_folders, TRUE);
1744
                cmd.status_full_folders = NULL;
1745
        }
1746
        if (cmd.open_msg) {
1747
                g_free(cmd.open_msg);
1748
                cmd.open_msg = NULL;
1749
        }
1750
        if (cmd.exit) {
1751
                app_will_exit(TRUE);
1752
        }
1753
}
1754

    
1755
#if !defined(G_OS_WIN32) && !defined(__APPLE__)
1756
static void migrate_old_config(void)
1757
{
1758
        GDir *dir;
1759
        const gchar *dir_name;
1760
        GPatternSpec *pspec;
1761

    
1762
        if (alertpanel(_("Migration of configuration"),
1763
                       _("The previous version of configuration found.\n"
1764
                         "Do you want to migrate it?"),
1765
                       GTK_STOCK_YES, GTK_STOCK_NO, NULL) != G_ALERTDEFAULT)
1766
                return;
1767

    
1768
        debug_print("Migrating old configuration...\n");
1769

    
1770
#define COPY_FILE(rcfile)                                                \
1771
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile)) {        \
1772
                conv_copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile,        \
1773
                               RC_DIR G_DIR_SEPARATOR_S rcfile,                \
1774
                               conv_get_locale_charset_str());                \
1775
        }
1776

    
1777
        COPY_FILE(ACCOUNT_RC);
1778
        COPY_FILE(ACTIONS_RC);
1779
        COPY_FILE(COMMON_RC);
1780
        COPY_FILE(CUSTOM_HEADER_RC);
1781
        COPY_FILE(DISPLAY_HEADER_RC);
1782
        COPY_FILE(FILTER_HEADER_RC);
1783
        COPY_FILE(COMMAND_HISTORY);
1784

    
1785
#undef COPY_FILE
1786

    
1787
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST))
1788
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST,
1789
                          RC_DIR G_DIR_SEPARATOR_S FILTER_LIST, FALSE);
1790
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST))
1791
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST,
1792
                          RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST, FALSE);
1793
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types"))
1794
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types",
1795
                          RC_DIR G_DIR_SEPARATOR_S "mime.types", FALSE);
1796

    
1797
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR))
1798
                conv_copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1799
                              RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1800
                              conv_get_locale_charset_str());
1801
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR))
1802
                copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR,
1803
                         RC_DIR G_DIR_SEPARATOR_S UIDL_DIR);
1804

    
1805
        if (!is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S ADDRESSBOOK_INDEX_FILE))
1806
                return;
1807

    
1808
        if ((dir = g_dir_open(OLD_RC_DIR, 0, NULL)) == NULL) {
1809
                g_warning("failed to open directory: %s\n", OLD_RC_DIR);
1810
                return;
1811
        }
1812

    
1813
        pspec = g_pattern_spec_new("addrbook-*.xml");
1814

    
1815
        while ((dir_name = g_dir_read_name(dir)) != NULL) {
1816
                if (g_pattern_match_string(pspec, dir_name)) {
1817
                        gchar *old_file;
1818
                        gchar *new_file;
1819

    
1820
                        old_file = g_strconcat(OLD_RC_DIR G_DIR_SEPARATOR_S,
1821
                                               dir_name, NULL);
1822
                        new_file = g_strconcat(RC_DIR G_DIR_SEPARATOR_S,
1823
                                               dir_name, NULL);
1824
                        copy_file(old_file, new_file, FALSE);
1825
                        g_free(new_file);
1826
                        g_free(old_file);
1827
                }
1828
        }
1829

    
1830
        g_pattern_spec_free(pspec);
1831
        g_dir_close(dir);
1832
}
1833
#endif /* !G_OS_WIN32 && !__APPLE__ */
1834

    
1835
static void open_compose_new(const gchar *address, GPtrArray *attach_files)
1836
{
1837
        gchar *utf8addr = NULL;
1838
#ifdef G_OS_WIN32
1839
        GPtrArray *utf8files = NULL;
1840
#endif
1841

    
1842
        if (gtkut_window_modal_exist())
1843
                return;
1844

    
1845
        if (address) {
1846
                utf8addr = g_locale_to_utf8(address, -1, NULL, NULL, NULL);
1847
                if (utf8addr)
1848
                        g_strstrip(utf8addr);
1849
                debug_print("open compose: %s\n", utf8addr ? utf8addr : "");
1850
        }
1851

    
1852
#ifdef G_OS_WIN32
1853
        if (attach_files) {
1854
                gint i;
1855
                gchar *file, *utf8file;
1856

    
1857
                utf8files = g_ptr_array_new();
1858
                for (i = 0; i < attach_files->len; i++) {
1859
                        file = g_ptr_array_index(attach_files, i);
1860
                        utf8file = g_locale_to_utf8(file, -1, NULL, NULL, NULL);
1861
                        if (utf8file)
1862
                                g_ptr_array_add(utf8files, utf8file);
1863
                }
1864
        }
1865

    
1866
        compose_new(NULL, NULL, utf8addr, utf8files);
1867
        if (utf8files) {
1868
                ptr_array_free_strings(utf8files);
1869
                g_ptr_array_free(utf8files, TRUE);
1870
        }
1871
#else
1872
        compose_new(NULL, NULL, utf8addr, attach_files);
1873
#endif
1874

    
1875
        g_free(utf8addr);
1876
}
1877

    
1878
static void open_message_file(const gchar *file)
1879
{
1880
        MsgInfo *msginfo;
1881
        MsgFlags flags = {0};
1882
        MessageView *msgview;
1883

    
1884
        g_return_if_fail(file != NULL);
1885

    
1886
        debug_print("open message file: %s\n", file);
1887

    
1888
        if (!is_file_exist(file) || get_file_size(file) <= 0) {
1889
                debug_print("file not found: %s\n", file);
1890
                return;
1891
        }
1892

    
1893
        msginfo = procheader_parse_file(file, flags, FALSE);
1894
        if (msginfo) {
1895
                msginfo->file_path = g_strdup(file);
1896
                msgview = messageview_create_with_new_window();
1897
                messageview_show(msgview, msginfo, FALSE);
1898
                procmsg_msginfo_free(msginfo);
1899
        } else
1900
                debug_print("cannot open message: %s\n", file);
1901
}
1902

    
1903
static void open_message(const gchar *path)
1904
{
1905
        gchar *fid;
1906
        gchar *msg;
1907
        gint num;
1908
        FolderItem *item;
1909
        MsgInfo *msginfo;
1910
        MessageView *msgview;
1911
        gchar *file;
1912

    
1913
        g_return_if_fail(path != NULL);
1914

    
1915
        if (gtkut_window_modal_exist())
1916
                return;
1917

    
1918
        debug_print("open message: %s\n", path);
1919

    
1920
        if (!strncmp(path, "file:", 5)) {
1921
                file = g_filename_from_uri(path, NULL, NULL);
1922
                open_message_file(file);
1923
                g_free(file);
1924
                return;
1925
        } else if (g_path_is_absolute(path)) {
1926
                open_message_file(path);
1927
                return;
1928
        }
1929

    
1930
        /* relative path, or folder identifier */
1931

    
1932
        fid = g_path_get_dirname(path);
1933
        msg = g_path_get_basename(path);
1934
        num = to_number(msg);
1935
        item = folder_find_item_from_identifier(fid);
1936

    
1937
        if (num > 0 && item) {
1938
                debug_print("open folder id: %s (msg %d)\n", fid, num);
1939
                msginfo = folder_item_get_msginfo(item, num);
1940
                if (msginfo) {
1941
                        msgview = messageview_create_with_new_window();
1942
                        messageview_show(msgview, msginfo, FALSE);
1943
                        procmsg_msginfo_free(msginfo);
1944
                        g_free(msg);
1945
                        g_free(fid);
1946
                        return;
1947
                } else
1948
                        debug_print("message %d not found\n", num);
1949
        }
1950

    
1951
        g_free(msg);
1952
        g_free(fid);
1953

    
1954
        /* relative path */
1955

    
1956
        file = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, path, NULL);
1957
        open_message_file(file);
1958
        g_free(file);
1959
}
1960

    
1961
static void send_queue(void)
1962
{
1963
        GList *list;
1964

    
1965
        if (gtkut_window_modal_exist())
1966
                return;
1967
        if (!main_window_toggle_online_if_offline(main_window_get()))
1968
                return;
1969

    
1970
        for (list = folder_get_list(); list != NULL; list = list->next) {
1971
                Folder *folder = list->data;
1972

    
1973
                if (folder->queue) {
1974
                        gint ret;
1975

    
1976
                        ret = send_message_queue_all(folder->queue,
1977
                                                     prefs_common.savemsg,
1978
                                                     prefs_common.filter_sent);
1979
                        statusbar_pop_all();
1980
                        if (ret > 0)
1981
                                folder_item_scan(folder->queue);
1982
                }
1983
        }
1984

    
1985
        folderview_update_all_updated(TRUE);
1986
        main_window_set_menu_sensitive(main_window_get());
1987
        main_window_set_toolbar_sensitive(main_window_get());
1988
}