Statistics
| Revision:

root / src / main.c @ 3395

History | View | Annotate | Download (49.4 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
        gchar *str = NULL;
471
        gchar **strv = NULL;
472
        gchar *style = NULL;
473
        gchar *size = NULL;
474
        gchar *suffix = NULL;
475

    
476
        if (!conv_is_ja_locale())
477
                return;
478

    
479
        if (prefs_common.textfont &&
480
            strcmp(prefs_common.textfont, DEFAULT_MESSAGE_FONT) != 0) {
481
                guint len;
482

    
483
                if (gtkut_font_can_load(prefs_common.textfont)) {
484
                        debug_print("font '%s' load ok\n", prefs_common.textfont);
485
                        return;
486
                }
487
                debug_print("font '%s' load failed\n", prefs_common.textfont);
488
                debug_print("fixing prefs_common.textfont setting\n");
489

    
490
                strv = g_strsplit(prefs_common.textfont, " ", -1);
491
                len = g_strv_length(strv);
492
                if (len > 0) {
493
                        if (g_ascii_isdigit(strv[len - 1][0]))
494
                                size = g_strdup(strv[len - 1]);
495
                        if (len > 2) {
496
                                if (g_ascii_strcasecmp(strv[len - 2], "Bold") == 0)
497
                                        style = g_strdup(strv[len - 2]);
498
                        }
499
                }
500
                g_strfreev(strv);
501
        }
502

    
503
        if (style && size)
504
                suffix = g_strconcat(style, " ", size, NULL);
505
        else if (size)
506
                suffix = g_strdup(size);
507
        else
508
#ifdef G_OS_WIN32
509
                suffix = g_strdup("12");
510
#else /* __APPLE__ */
511
                suffix = g_strdup("13");
512
#endif
513
        g_free(style);        
514
        g_free(size);
515
#ifdef G_OS_WIN32
516
        str = g_strconcat("MS Gothic ", suffix, NULL);
517
#else /* __APPLE__ */
518
        str = g_strconcat("Hiragino Kaku Gothic Pro Light ", suffix, NULL);
519
#endif
520

    
521
        if (!gtkut_font_can_load(str)) {
522
#ifdef G_OS_WIN32
523
                debug_print("font '%s' load failed\n", str);
524
                g_free(str);
525
                str = g_strconcat("\xef\xbc\xad\xef\xbc\xb3 \xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf ", suffix, NULL);
526
                if (!gtkut_font_can_load(str)) {
527
                        debug_print("font '%s' load failed\n", str);
528
                        g_free(str);
529
                        str = NULL;
530
                }
531
#else /* __APPLE__ */
532
                debug_print("font '%s' load failed\n", str);
533
                g_free(str);
534
                str = NULL;
535
#endif
536
        }
537

    
538
        if (str) {
539
                debug_print("font '%s' load ok\n", str);
540
                g_free(prefs_common.textfont);
541
                prefs_common.textfont = g_strdup(str);
542
                g_free(str);
543
        } else
544
                g_warning("failed to load text font!");
545

    
546
        g_free(suffix);
547
}
548
#endif
549

    
550
static void parse_cmd_opt(int argc, char *argv[])
551
{
552
        gint i;
553

    
554
        for (i = 1; i < argc; i++) {
555
                if (!strncmp(argv[i], "--debug", 7)) {
556
                        init_console();
557
                        set_debug_mode(TRUE);
558
                } else if (!strncmp(argv[i], "--receive-all", 13))
559
                        cmd.receive_all = TRUE;
560
                else if (!strncmp(argv[i], "--receive", 9))
561
                        cmd.receive = TRUE;
562
                else if (!strncmp(argv[i], "--compose", 9)) {
563
                        const gchar *p = argv[i + 1];
564

    
565
                        cmd.compose = TRUE;
566
                        cmd.compose_mailto = NULL;
567
                        if (p && *p != '\0' && *p != '-') {
568
                                if (!strncmp(p, "mailto:", 7))
569
                                        cmd.compose_mailto = p + 7;
570
                                else
571
                                        cmd.compose_mailto = p;
572
                                i++;
573
                        }
574
                } else if (!strncmp(argv[i], "--attach", 8)) {
575
                        const gchar *p = argv[i + 1];
576
                        gchar *file;
577

    
578
                        while (p && *p != '\0' && *p != '-') {
579
                                if (!cmd.attach_files)
580
                                        cmd.attach_files = g_ptr_array_new();
581
                                if (!g_path_is_absolute(p))
582
                                        file = g_strconcat(get_startup_dir(),
583
                                                           G_DIR_SEPARATOR_S,
584
                                                           p, NULL);
585
                                else
586
                                        file = g_strdup(p);
587
                                g_ptr_array_add(cmd.attach_files, file);
588
                                i++;
589
                                p = argv[i + 1];
590
                        }
591
                } else if (!strncmp(argv[i], "--send", 6)) {
592
                        cmd.send = TRUE;
593
                } else if (!strncmp(argv[i], "--version", 9)) {
594
                        puts("Sylpheed version " VERSION);
595
                        exit(0);
596
                } else if (!strncmp(argv[i], "--status-full", 13)) {
597
                        const gchar *p = argv[i + 1];
598

    
599
                        cmd.status_full = TRUE;
600
                        while (p && *p != '\0' && *p != '-') {
601
                                if (!cmd.status_full_folders)
602
                                        cmd.status_full_folders =
603
                                                g_ptr_array_new();
604
                                g_ptr_array_add(cmd.status_full_folders,
605
                                                g_strdup(p));
606
                                i++;
607
                                p = argv[i + 1];
608
                        }
609
                } else if (!strncmp(argv[i], "--status", 8)) {
610
                        const gchar *p = argv[i + 1];
611

    
612
                        cmd.status = TRUE;
613
                        while (p && *p != '\0' && *p != '-') {
614
                                if (!cmd.status_folders)
615
                                        cmd.status_folders = g_ptr_array_new();
616
                                g_ptr_array_add(cmd.status_folders,
617
                                                g_strdup(p));
618
                                i++;
619
                                p = argv[i + 1];
620
                        }
621
                } else if (!strncmp(argv[i], "--open", 6)) {
622
                        const gchar *p = argv[i + 1];
623

    
624
                        if (p && *p != '\0' && *p != '-') {
625
                                if (cmd.open_msg)
626
                                        g_free(cmd.open_msg);
627
                                cmd.open_msg = g_locale_to_utf8
628
                                        (p, -1, NULL, NULL, NULL);
629
                                i++;
630
                        }
631
                } else if (!strncmp(argv[i], "--configdir", 11)) {
632
                        const gchar *p = argv[i + 1];
633

    
634
                        if (p && *p != '\0' && *p != '-') {
635
                                /* this must only be done at startup */
636
#ifdef G_OS_WIN32
637
                                gchar *utf8dir;
638

    
639
                                utf8dir = g_locale_to_utf8
640
                                        (p, -1, NULL, NULL, NULL);
641
                                if (utf8dir) {
642
                                        set_rc_dir(utf8dir);
643
                                        g_free(utf8dir);
644
                                } else
645
                                        set_rc_dir(p);
646
#else
647
                                set_rc_dir(p);
648
#endif
649
                                cmd.configdir = TRUE;
650
                                i++;
651
                        }
652
#ifdef G_OS_WIN32
653
                } else if (!strncmp(argv[i], "--ipcport", 9)) {
654
                        if (argv[i + 1]) {
655
                                cmd.ipcport = atoi(argv[i + 1]);
656
                                i++;
657
                        }
658
#endif
659
                } else if (!strncmp(argv[i], "--instance-id", 13)) {
660
                        if (argv[i + 1]) {
661
                                instance_id = g_locale_to_utf8
662
                                        (argv[i + 1], -1, NULL, NULL, NULL);
663
                                i++;
664
                        }
665
                } else if (!strncmp(argv[i], "--safe-mode", 11)) {
666
                        cmd.safe_mode = TRUE;
667
                } else if (!strncmp(argv[i], "--exit", 6)) {
668
                        cmd.exit = TRUE;
669
                } else if (!strncmp(argv[i], "--help", 6)) {
670
                        init_console();
671

    
672
                        g_print(_("Usage: %s [OPTIONS ...] [URL]\n"),
673
                                g_basename(argv[0]));
674

    
675
                        g_print("%s\n", _("  --compose [mailto URL] open composition window"));
676
                        g_print("%s\n", _("  --attach file1 [file2]...\n"
677
                                "                         open composition window with specified files\n"
678
                                "                         attached"));
679
                        g_print("%s\n", _("  --receive              receive new messages"));
680
                        g_print("%s\n", _("  --receive-all          receive new messages of all accounts"));
681
                        g_print("%s\n", _("  --send                 send all queued messages"));
682
                        g_print("%s\n", _("  --status [folder]...   show the total number of messages"));
683
                        g_print("%s\n", _("  --status-full [folder]...\n"
684
                                "                         show the status of each folder"));
685
                        g_print("%s\n", _("  --open folderid/msgnum open existing message in a new window"));
686
                        g_print("%s\n", _("  --open <file URL>      open an rfc822 message file in a new window"));
687
                        g_print("%s\n", _("  --configdir dirname    specify directory which stores configuration files"));
688
#ifdef G_OS_WIN32
689
                        g_print("%s\n", _("  --ipcport portnum      specify port for IPC remote commands"));
690
#endif
691
                        g_print("%s\n", _("  --exit                 exit Sylpheed"));
692
                        g_print("%s\n", _("  --debug                debug mode"));
693
                        g_print("%s\n", _("  --safe-mode            safe mode"));
694
                        g_print("%s\n", _("  --help                 display this help and exit"));
695
                        g_print("%s\n", _("  --version              output version information and exit"));
696

    
697
#ifdef G_OS_WIN32
698
                        g_print("\n");
699
                        g_print(_("Press any key..."));
700
                        _getch();
701
#endif
702

    
703
                        cleanup_console();
704
                        exit(1);
705
                } else {
706
                        /* file or URL */
707
                        const gchar *p = argv[i];
708

    
709
                        if (p && *p != '\0') {
710
                                if (!strncmp(p, "mailto:", 7)) {
711
                                        cmd.compose = TRUE;
712
                                        cmd.compose_mailto = p + 7;
713
                                } else {
714
                                        if (cmd.open_msg)
715
                                                g_free(cmd.open_msg);
716
                                        cmd.open_msg = g_locale_to_utf8
717
                                                (p, -1, NULL, NULL, NULL);
718
                                }
719
                        }
720
                }
721
        }
722

    
723
        if (cmd.attach_files && cmd.compose == FALSE) {
724
                cmd.compose = TRUE;
725
                cmd.compose_mailto = NULL;
726
        }
727

    
728
        cmd.argv0 = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
729
        if (!cmd.argv0)
730
                cmd.argv0 = g_strdup(argv[0]);
731
}
732

    
733
static gint get_queued_message_num(void)
734
{
735
        FolderItem *queue;
736

    
737
        queue = folder_get_default_queue();
738
        if (!queue) return -1;
739

    
740
        folder_item_scan(queue);
741
        return queue->total;
742
}
743

    
744
#if USE_THREADS
745
/* enables recursive locking with gdk_thread_enter / gdk_threads_leave */
746
static GStaticRecMutex syl_mutex = G_STATIC_REC_MUTEX_INIT;
747

    
748
static void thread_enter_func(void)
749
{
750
        g_static_rec_mutex_lock(&syl_mutex);
751
#if 0
752
        syl_mutex_lock_count++;
753
        if (syl_mutex_lock_count > 1)
754
                g_print("enter: syl_mutex_lock_count: %d\n", syl_mutex_lock_count);
755
#endif
756
}
757

    
758
static void thread_leave_func(void)
759
{
760
#if 0
761
        syl_mutex_lock_count--;
762
        if (syl_mutex_lock_count > 0)
763
                g_print("leave: syl_mutex_lock_count: %d\n", syl_mutex_lock_count);
764
#endif
765
        g_static_rec_mutex_unlock(&syl_mutex);
766
}
767

    
768
static void event_loop_iteration_func(void)
769
{
770
        if (g_thread_self() != main_thread) {
771
                g_fprintf(stderr, "event_loop_iteration_func called from non-main thread (%p)\n", g_thread_self());
772
                g_usleep(10000);
773
                return;
774
        }
775
        gtk_main_iteration();
776
}
777
#endif
778

    
779
static void app_init(void)
780
{
781
#if USE_THREADS
782
        if (!g_thread_supported())
783
                g_thread_init(NULL);
784
        if (!g_thread_supported())
785
                g_error("g_thread is not supported by glib.");
786
        else {
787
                gdk_threads_set_lock_functions(thread_enter_func,
788
                                               thread_leave_func);
789
                gdk_threads_init();
790
                main_thread = g_thread_self();
791
        }
792
#endif
793
        syl_init();
794

    
795
#if USE_THREADS
796
        set_event_loop_func(event_loop_iteration_func);
797
#endif
798
        prog_version = PROG_VERSION;
799

    
800
#ifdef G_OS_WIN32
801
        read_ini_file();
802
#endif
803
}
804

    
805
static void parse_gtkrc_files(void)
806
{
807
        gchar *userrc;
808

    
809
        /* parse gtkrc files */
810
        userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtkrc-2.0",
811
                             NULL);
812
        gtk_rc_parse(userrc);
813
        g_free(userrc);
814
        userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtk",
815
                             G_DIR_SEPARATOR_S, "gtkrc-2.0", NULL);
816
        gtk_rc_parse(userrc);
817
        g_free(userrc);
818
        userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, "gtkrc", NULL);
819
        gtk_rc_parse(userrc);
820
        g_free(userrc);
821

    
822
        userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
823
        gtk_accel_map_load(userrc);
824
        g_free(userrc);
825
}
826

    
827
static void setup_rc_dir(void)
828
{
829
#if !defined(G_OS_WIN32) && !defined(__APPLE__)
830
        CHDIR_EXIT_IF_FAIL(get_home_dir(), 1);
831

    
832
        /* backup if old rc file exists */
833
        if (!cmd.configdir && is_file_exist(RC_DIR)) {
834
                if (rename_force(RC_DIR, RC_DIR ".bak") < 0)
835
                        FILE_OP_ERROR(RC_DIR, "rename");
836
        }
837

    
838
        /* migration from ~/.sylpheed to ~/.sylpheed-2.0 */
839
        if (!cmd.configdir && !is_dir_exist(RC_DIR)) {
840
                const gchar *envstr;
841
                AlertValue val;
842

    
843
                /* check for filename encoding */
844
                if (conv_get_locale_charset() != C_UTF_8) {
845
                        envstr = g_getenv("G_FILENAME_ENCODING");
846
                        if (!envstr)
847
                                envstr = g_getenv("G_BROKEN_FILENAMES");
848
                        if (!envstr) {
849
                                val = alertpanel(_("Filename encoding"),
850
                                                 _("The locale encoding is not UTF-8, but the environmental variable G_FILENAME_ENCODING is not set.\n"
851
                                                   "If the locale encoding is used for file name or directory name, it will not work correctly.\n"
852
                                                   "In that case, you must set the following environmental variable (see README for detail):\n"
853
                                                   "\n"
854
                                                   "\tG_FILENAME_ENCODING=@locale\n"
855
                                                   "\n"
856
                                                   "Continue?"),
857
                                                 GTK_STOCK_OK, GTK_STOCK_QUIT,
858
                                                 NULL);
859
                                if (G_ALERTDEFAULT != val)
860
                                        exit(1);
861
                        }
862
                }
863

    
864
                if (make_dir(RC_DIR) < 0)
865
                        exit(1);
866
                if (is_dir_exist(OLD_RC_DIR))
867
                        migrate_old_config();
868
        }
869
#endif /* !G_OS_WIN32 && !__APPLE__ */
870

    
871
        syl_setup_rc_dir();
872
}
873

    
874
static void app_restart(void)
875
{
876
        gchar *cmdline;
877
        GError *error = NULL;
878
#ifdef G_OS_WIN32
879
        if (cmd.configdir) {
880
                cmdline = g_strdup_printf("\"%s\"%s --configdir \"%s\" --ipcport %d",
881
                                          cmd.argv0,
882
                                          get_debug_mode() ? " --debug" : "",
883
                                          get_rc_dir(),
884
                                          cmd.ipcport);
885
        } else {
886
                cmdline = g_strdup_printf("\"%s\"%s --ipcport %d",
887
                                          cmd.argv0,
888
                                          get_debug_mode() ? " --debug" : "",
889
                                          cmd.ipcport);
890
        }
891
#else
892
        if (cmd.configdir) {
893
                cmdline = g_strdup_printf("\"%s\"%s --configdir \"%s\"",
894
                                          cmd.argv0,
895
                                          get_debug_mode() ? " --debug" : "",
896
                                          get_rc_dir());
897
        } else {
898
                cmdline = g_strdup_printf("\"%s\"%s",
899
                                          cmd.argv0,
900
                                          get_debug_mode() ? " --debug" : "");
901
        }
902
#endif
903
        if (!g_spawn_command_line_async(cmdline, &error)) {
904
                alertpanel_error("restart failed\n'%s'\n%s", cmdline, error->message);
905
                g_error_free(error);
906
        }
907
        g_free(cmdline);
908
}
909

    
910
void app_will_restart(gboolean force)
911
{
912
        cmd.restart = TRUE;
913
        app_will_exit(force);
914
        /* canceled */
915
        cmd.restart = FALSE;
916
}
917

    
918
void app_will_exit(gboolean force)
919
{
920
        MainWindow *mainwin;
921
        gchar *filename;
922
        static gboolean on_exit = FALSE;
923
        GList *cur;
924

    
925
        if (on_exit)
926
                return;
927
        on_exit = TRUE;
928

    
929
        mainwin = main_window_get();
930

    
931
        if (!force && compose_get_compose_list()) {
932
                if (alertpanel(_("Notice"),
933
                               _("Composing message exists. Really quit?"),
934
                               GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL)
935
                    != G_ALERTDEFAULT) {
936
                        on_exit = FALSE;
937
                        return;
938
                }
939
                manage_window_focus_in(mainwin->window, NULL, NULL);
940
        }
941

    
942
        if (!force &&
943
            prefs_common.warn_queued_on_exit && get_queued_message_num() > 0) {
944
                if (alertpanel(_("Queued messages"),
945
                               _("Some unsent messages are queued. Exit now?"),
946
                               GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL)
947
                    != G_ALERTDEFAULT) {
948
                        on_exit = FALSE;
949
                        return;
950
                }
951
                manage_window_focus_in(mainwin->window, NULL, NULL);
952
        }
953

    
954
        if (force)
955
                g_signal_emit_by_name(syl_app_get(), "app-force-exit");
956
        g_signal_emit_by_name(syl_app_get(), "app-exit");
957

    
958
        inc_autocheck_timer_remove();
959

    
960
        if (prefs_common.clean_on_exit)
961
                main_window_empty_trash(mainwin,
962
                                        !force && prefs_common.ask_on_clean);
963

    
964
        for (cur = account_get_list(); cur != NULL; cur = cur->next) {
965
                PrefsAccount *ac = (PrefsAccount *)cur->data;
966
                if (ac->protocol == A_IMAP4 && ac->imap_clear_cache_on_exit &&
967
                    ac->folder)
968
                        procmsg_remove_all_cached_messages(FOLDER(ac->folder));
969
        }
970

    
971
        syl_plugin_unload_all();
972

    
973
        trayicon_destroy(mainwin->tray_icon);
974

    
975
        /* save all state before exiting */
976
        summary_write_cache(mainwin->summaryview);
977
        main_window_get_size(mainwin);
978
        main_window_get_position(mainwin);
979
        syl_save_all_state();
980
        addressbook_export_to_file();
981

    
982
        filename = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
983
        gtk_accel_map_save(filename);
984
        g_free(filename);
985

    
986
        /* remove temporary files, close log file, socket cleanup */
987
#if USE_SSL
988
        ssl_done();
989
#endif
990
        syl_cleanup();
991
        lock_socket_remove();
992

    
993
#ifdef USE_UPDATE_CHECK_PLUGIN
994
#ifdef G_OS_WIN32
995
        cur = gtk_window_list_toplevels();
996
        g_list_foreach(cur, (GFunc)gtk_widget_hide, NULL);
997
        g_list_free(cur);
998
        update_check_spawn_plugin_updater();
999
#endif
1000
#endif
1001

    
1002
        cleanup_console();
1003

    
1004
        if (gtk_main_level() > 0)
1005
                gtk_main_quit();
1006

    
1007
        if (cmd.restart)
1008
                app_restart();
1009

    
1010
        exit(0);
1011
}
1012

    
1013
#if 0
1014
#if USE_GPGME
1015
static void idle_function_for_gpgme(void)
1016
{
1017
        while (gtk_events_pending())
1018
                gtk_main_iteration();
1019
}
1020
#endif /* USE_GPGME */
1021
#endif /* 0 */
1022

    
1023
static void check_gpg(void)
1024
{
1025
#if USE_GPGME
1026
        const gchar *version;
1027
        gpgme_error_t err = 0;
1028

    
1029
        version = gpgme_check_version("1.0.0");
1030
        if (version) {
1031
                debug_print("GPGME Version: %s\n", version);
1032
                err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
1033
                if (err)
1034
                        debug_print("gpgme_engine_check_version: %s\n",
1035
                                    gpgme_strerror(err));
1036
        }
1037

    
1038
        if (version && !err) {
1039
                /* Also does some gpgme init */
1040
                gpgme_engine_info_t engineInfo;
1041

    
1042
#if HAVE_LOCALE_H
1043
                gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
1044
                gpgme_set_locale(NULL, LC_MESSAGES,
1045
                                 setlocale(LC_MESSAGES, NULL));
1046
#endif
1047

    
1048
                if (!gpgme_get_engine_info(&engineInfo)) {
1049
                        while (engineInfo) {
1050
                                debug_print("GPGME Protocol: %s\n      Version: %s\n",
1051
                                            gpgme_get_protocol_name
1052
                                                (engineInfo->protocol),
1053
                                            engineInfo->version ?
1054
                                            engineInfo->version : "(unknown)");
1055
                                engineInfo = engineInfo->next;
1056
                        }
1057
                }
1058

    
1059
                procmsg_set_decrypt_message_func
1060
                        (rfc2015_open_message_decrypted);
1061
                procmsg_set_auto_decrypt_message(TRUE);
1062
        } else {
1063
                rfc2015_disable_all();
1064

    
1065
                if (prefs_common.gpg_warning) {
1066
                        AlertValue val;
1067

    
1068
                        val = alertpanel_message_with_disable
1069
                                (_("Warning"),
1070
                                 _("GnuPG is not installed properly, or its version is too old.\n"
1071
                                   "OpenPGP support disabled."),
1072
                                 ALERT_WARNING);
1073
                        if (val & G_ALERTDISABLE)
1074
                                prefs_common.gpg_warning = FALSE;
1075
                }
1076
        }
1077
        /* FIXME: This function went away.  We can either block until gpgme
1078
         * operations finish (currently implemented) or register callbacks
1079
         * with the gtk main loop via the gpgme io callback interface instead.
1080
         *
1081
         * gpgme_register_idle(idle_function_for_gpgme);
1082
         */
1083
#endif
1084
}
1085

    
1086
static void default_log_func(const gchar *log_domain, GLogLevelFlags log_level,
1087
                             const gchar *message, gpointer user_data)
1088
{
1089
        gchar *prefix = "";
1090
        gchar *file_prefix = "";
1091
        LogType level = LOG_NORMAL;
1092
        gchar *str;
1093
        const gchar *message_;
1094

    
1095
        switch (log_level) {
1096
        case G_LOG_LEVEL_ERROR:
1097
                prefix = "ERROR";
1098
                file_prefix = "*** ";
1099
                level = LOG_ERROR;
1100
                break;
1101
        case G_LOG_LEVEL_CRITICAL:
1102
                prefix = "CRITICAL";
1103
                file_prefix = "** ";
1104
                level = LOG_WARN;
1105
                break;
1106
        case G_LOG_LEVEL_WARNING:
1107
                prefix = "WARNING";
1108
                file_prefix = "** ";
1109
                level = LOG_WARN;
1110
                break;
1111
        case G_LOG_LEVEL_MESSAGE:
1112
                prefix = "Message";
1113
                file_prefix = "* ";
1114
                level = LOG_MSG;
1115
                break;
1116
        case G_LOG_LEVEL_INFO:
1117
                prefix = "INFO";
1118
                file_prefix = "* ";
1119
                level = LOG_MSG;
1120
                break;
1121
        case G_LOG_LEVEL_DEBUG:
1122
                prefix = "DEBUG";
1123
                break;
1124
        default:
1125
                prefix = "LOG";
1126
                break;
1127
        }
1128

    
1129
        if (!message)
1130
                message_ = "(NULL) message";
1131
        else
1132
                message_ = message;
1133
        if (log_domain)
1134
                str = g_strconcat(log_domain, "-", prefix, ": ", message_, "\n",
1135
                                  NULL);
1136
        else
1137
                str = g_strconcat(prefix, ": ", message_, "\n", NULL);
1138
        log_window_append(str, level);
1139
        log_write(str, file_prefix);
1140
        g_free(str);
1141

    
1142
        g_log_default_handler(log_domain, log_level, message, user_data);
1143
}
1144

    
1145
static void set_log_handlers(gboolean enable)
1146
{
1147
#if GLIB_CHECK_VERSION(2, 6, 0)
1148
        if (enable)
1149
                g_log_set_default_handler(default_log_func, NULL);
1150
        else
1151
                g_log_set_default_handler(g_log_default_handler, NULL);
1152
#else
1153
        static guint handler_id[4] = {0, 0, 0, 0};
1154

    
1155
        if (enable) {
1156
                handler_id[0] = g_log_set_handler
1157
                        ("GLib", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1158
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1159
                handler_id[1] = g_log_set_handler
1160
                        ("Gtk", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1161
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1162
                handler_id[2] = g_log_set_handler
1163
                        ("LibSylph", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1164
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1165
                handler_id[3] = g_log_set_handler
1166
                        ("Sylpheed", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
1167
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
1168
        } else {
1169
                g_log_remove_handler("GLib", handler_id[0]);
1170
                g_log_remove_handler("Gtk", handler_id[1]);
1171
                g_log_remove_handler("LibSylph", handler_id[2]);
1172
                g_log_remove_handler("Sylpheed", handler_id[3]);
1173
                handler_id[0] = 0;
1174
                handler_id[1] = 0;
1175
                handler_id[2] = 0;
1176
                handler_id[3] = 0;
1177
        }
1178
#endif
1179
}
1180

    
1181
#ifdef G_OS_WIN32
1182

    
1183
#if !GTK_CHECK_VERSION(2, 14, 0)
1184
static UINT taskbar_created_msg;
1185
#endif
1186

    
1187
static BOOL WINAPI
1188
ctrl_handler(DWORD dwctrltype)
1189
{
1190
        log_print("ctrl_handler: received %d\n", dwctrltype);
1191
        app_will_exit(TRUE);
1192

    
1193
        return TRUE;
1194
}
1195

    
1196
static LRESULT CALLBACK
1197
wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
1198
{
1199
        switch (message) {
1200
        case WM_POWERBROADCAST:
1201
                debug_print("WM_POWERBROADCAST received: wparam = %d\n",
1202
                            wparam);
1203
                if (wparam == PBT_APMSUSPEND || wparam == PBT_APMSTANDBY) {
1204
                        debug_print("suspend now\n");
1205
                        inc_autocheck_timer_remove();
1206
                } else if (wparam == PBT_APMRESUMESUSPEND ||
1207
                           wparam == PBT_APMRESUMESTANDBY) {
1208
                        debug_print("resume now\n");
1209
                        inc_autocheck_timer_set();
1210
                }
1211
                break;
1212
        case WM_ENDSESSION:
1213
                if (wparam == 1) {
1214
                        log_print("WM_ENDSESSION received: system is quitting\n");
1215
                        app_will_exit(TRUE);
1216
                }
1217
                break;
1218
        default:
1219
#if !GTK_CHECK_VERSION(2, 14, 0)
1220
                if (message == taskbar_created_msg) {
1221
                        debug_print("TaskbarCreated received\n");
1222

    
1223
                        /* recreate tray icon */
1224
                        {
1225
                                MainWindow *mainwin = main_window_get();
1226
                                if (mainwin && mainwin->tray_icon &&
1227
                                    gtk_status_icon_get_visible(mainwin->tray_icon->status_icon)) {
1228
                                        trayicon_hide(mainwin->tray_icon);
1229
                                        trayicon_show(mainwin->tray_icon);
1230
                                }
1231
                        }
1232
                }
1233
#endif
1234
                break;
1235
        }
1236

    
1237
        return DefWindowProc(hwnd, message, wparam, lparam);
1238
}
1239

    
1240
static void register_system_events(void)
1241
{
1242
        WNDCLASS wclass;
1243
        static HWND hwnd = NULL;
1244
        static BOOL ctrl_handler_set = FALSE;
1245
        ATOM klass;
1246
        HINSTANCE hmodule = GetModuleHandle(NULL);
1247

    
1248
        if (init_console_done && !ctrl_handler_set) {
1249
                debug_print("register_system_events(): SetConsoleCtrlHandler\n");
1250
                ctrl_handler_set = SetConsoleCtrlHandler(ctrl_handler, TRUE);
1251
                if (!ctrl_handler_set)
1252
                        g_warning("SetConsoleCtrlHandler() failed\n");
1253
        }
1254

    
1255
        if (hwnd)
1256
                return;
1257

    
1258
#if !GTK_CHECK_VERSION(2, 14, 0)
1259
        taskbar_created_msg = RegisterWindowMessage("TaskbarCreated");
1260
#endif
1261

    
1262
        debug_print("register_system_events(): RegisterClass\n");
1263

    
1264
        memset(&wclass, 0, sizeof(WNDCLASS));
1265
        wclass.lpszClassName = "sylpheed-observer";
1266
        wclass.lpfnWndProc   = wndproc;
1267
        wclass.hInstance     = hmodule;
1268

    
1269
        klass = RegisterClass(&wclass);
1270
        if (!klass)
1271
                return;
1272

    
1273
        hwnd = CreateWindow(MAKEINTRESOURCE(klass), NULL, WS_POPUP,
1274
                            0, 0, 1, 1, NULL, NULL, hmodule, NULL);
1275
        if (!hwnd)
1276
                UnregisterClass(MAKEINTRESOURCE(klass), hmodule);
1277
}
1278
#else /* G_OS_WIN32 */
1279
static void sig_handler(gint signum)
1280
{
1281
        debug_print("signal %d received\n", signum);
1282

    
1283
        switch (signum) {
1284
        case SIGHUP:
1285
        case SIGINT:
1286
        case SIGTERM:
1287
        case SIGQUIT:
1288
                app_will_exit(TRUE);
1289
                break;
1290
        default:
1291
                break;
1292
        }
1293
}
1294

    
1295
static void register_system_events(void)
1296
{
1297
        struct sigaction sa;
1298

    
1299
        memset(&sa, 0, sizeof(sa));
1300
        sa.sa_handler = sig_handler;
1301
        sa.sa_flags = SA_RESTART;
1302

    
1303
        sigemptyset(&sa.sa_mask);
1304
        sigaddset(&sa.sa_mask, SIGHUP);
1305
        sigaddset(&sa.sa_mask, SIGINT);
1306
        sigaddset(&sa.sa_mask, SIGTERM);
1307
        sigaddset(&sa.sa_mask, SIGQUIT);
1308
        sigaddset(&sa.sa_mask, SIGPIPE);
1309

    
1310
        sigaction(SIGHUP, &sa, NULL);
1311
        sigaction(SIGINT, &sa, NULL);
1312
        sigaction(SIGTERM, &sa, NULL);
1313
        sigaction(SIGQUIT, &sa, NULL);
1314
        sigaction(SIGPIPE, &sa, NULL);
1315
}
1316
#endif
1317

    
1318
#define ADD_SYM(sym)        syl_plugin_add_symbol(#sym, sym)
1319

    
1320
static void plugin_init(void)
1321
{
1322
        MainWindow *mainwin;
1323
        gchar *path;
1324

    
1325
        mainwin = main_window_get();
1326

    
1327
        STATUSBAR_PUSH(mainwin, _("Loading plug-ins..."));
1328

    
1329
        if (syl_plugin_init_lib() != 0) {
1330
                STATUSBAR_POP(mainwin);
1331
                return;
1332
        }
1333

    
1334
        if (cmd.safe_mode) {
1335
                debug_print("plugin_init: safe mode enabled, skipping plug-in loading.\n");
1336
                STATUSBAR_POP(mainwin);
1337
                return;
1338
        }
1339

    
1340
        ADD_SYM(prog_version);
1341
        ADD_SYM(app_will_exit);
1342

    
1343
        ADD_SYM(main_window_lock);
1344
        ADD_SYM(main_window_unlock);
1345
        ADD_SYM(main_window_get);
1346
        ADD_SYM(main_window_popup);
1347

    
1348
        syl_plugin_add_symbol("main_window_menu_factory",
1349
                              mainwin->menu_factory);
1350
        syl_plugin_add_symbol("main_window_statusbar", mainwin->statusbar);
1351

    
1352
        ADD_SYM(folderview_get);
1353
        ADD_SYM(folderview_add_sub_widget);
1354
        ADD_SYM(folderview_select);
1355
        ADD_SYM(folderview_unselect);
1356
        ADD_SYM(folderview_select_next_unread);
1357
        ADD_SYM(folderview_get_selected_item);
1358
        ADD_SYM(folderview_check_new);
1359
        ADD_SYM(folderview_check_new_item);
1360
        ADD_SYM(folderview_check_new_all);
1361
        ADD_SYM(folderview_update_item);
1362
        ADD_SYM(folderview_update_item_foreach);
1363
        ADD_SYM(folderview_update_all_updated);
1364
        ADD_SYM(folderview_check_new_selected);
1365

    
1366
        syl_plugin_add_symbol("folderview_mail_popup_factory",
1367
                              mainwin->folderview->mail_factory);
1368
        syl_plugin_add_symbol("folderview_imap_popup_factory",
1369
                              mainwin->folderview->imap_factory);
1370
        syl_plugin_add_symbol("folderview_news_popup_factory",
1371
                              mainwin->folderview->news_factory);
1372

    
1373
        syl_plugin_add_symbol("summaryview", mainwin->summaryview);
1374
        syl_plugin_add_symbol("summaryview_popup_factory",
1375
                              mainwin->summaryview->popupfactory);
1376

    
1377
        ADD_SYM(summary_select_by_msgnum);
1378
        ADD_SYM(summary_select_by_msginfo);
1379
        ADD_SYM(summary_lock);
1380
        ADD_SYM(summary_unlock);
1381
        ADD_SYM(summary_is_locked);
1382
        ADD_SYM(summary_is_read_locked);
1383
        ADD_SYM(summary_write_lock);
1384
        ADD_SYM(summary_write_unlock);
1385
        ADD_SYM(summary_is_write_locked);
1386
        ADD_SYM(summary_get_current_folder);
1387
        ADD_SYM(summary_get_selection_type);
1388
        ADD_SYM(summary_get_selected_msg_list);
1389
        ADD_SYM(summary_get_msg_list);
1390
        ADD_SYM(summary_show_queued_msgs);
1391
        ADD_SYM(summary_redisplay_msg);
1392
        ADD_SYM(summary_open_msg);
1393
        ADD_SYM(summary_view_source);
1394
        ADD_SYM(summary_reedit);
1395
        ADD_SYM(summary_update_selected_rows);
1396
        ADD_SYM(summary_update_by_msgnum);
1397

    
1398
        ADD_SYM(messageview_create_with_new_window);
1399
        ADD_SYM(messageview_show);
1400

    
1401
        ADD_SYM(compose_new);
1402
        ADD_SYM(compose_entry_set);
1403
        ADD_SYM(compose_entry_append);
1404
        ADD_SYM(compose_entry_get_text);
1405
        ADD_SYM(compose_lock);
1406
        ADD_SYM(compose_unlock);
1407

    
1408
        ADD_SYM(foldersel_folder_sel);
1409
        ADD_SYM(foldersel_folder_sel_full);
1410

    
1411
        ADD_SYM(input_dialog);
1412
        ADD_SYM(input_dialog_with_invisible);
1413

    
1414
        ADD_SYM(manage_window_set_transient);
1415
        ADD_SYM(manage_window_signals_connect);
1416
        ADD_SYM(manage_window_get_focus_window);
1417

    
1418
        ADD_SYM(inc_mail);
1419
        ADD_SYM(inc_is_active);
1420
        ADD_SYM(inc_lock);
1421
        ADD_SYM(inc_unlock);
1422

    
1423
#if USE_UPDATE_CHECK
1424
        ADD_SYM(update_check);
1425
        ADD_SYM(update_check_set_check_url);
1426
        ADD_SYM(update_check_get_check_url);
1427
        ADD_SYM(update_check_set_download_url);
1428
        ADD_SYM(update_check_get_download_url);
1429
        ADD_SYM(update_check_set_jump_url);
1430
        ADD_SYM(update_check_get_jump_url);
1431
#ifdef USE_UPDATE_CHECK_PLUGIN
1432
        ADD_SYM(update_check_set_check_plugin_url);
1433
        ADD_SYM(update_check_get_check_plugin_url);
1434
        ADD_SYM(update_check_set_jump_plugin_url);
1435
        ADD_SYM(update_check_get_jump_plugin_url);
1436
#endif /* USE_UPDATE_CHECK_PLUGIN */
1437
#endif
1438

    
1439
        ADD_SYM(alertpanel_full);
1440
        ADD_SYM(alertpanel);
1441
        ADD_SYM(alertpanel_message);
1442
        ADD_SYM(alertpanel_message_with_disable);
1443

    
1444
        ADD_SYM(send_message);
1445
        ADD_SYM(send_message_queue_all);
1446
        ADD_SYM(send_message_set_reply_flag);
1447
        ADD_SYM(send_message_set_forward_flags);
1448

    
1449
        ADD_SYM(notification_window_open);
1450
        ADD_SYM(notification_window_set_message);
1451
        ADD_SYM(notification_window_close);
1452

    
1453
        syl_plugin_signal_connect("plugin-load", G_CALLBACK(load_cb), NULL);
1454

    
1455
        /* loading plug-ins from user plug-in directory */
1456
        path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, PLUGIN_DIR, NULL);
1457
        syl_plugin_load_all(path);
1458
        g_free(path);
1459

    
1460
        /* loading plug-ins from system plug-in directory */
1461
#ifdef G_OS_WIN32
1462
        path = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, PLUGIN_DIR,
1463
                           NULL);
1464
        syl_plugin_load_all(path);
1465
        g_free(path);
1466
#elif defined(__APPLE__)
1467
        path = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S,
1468
                           "Contents" G_DIR_SEPARATOR_S
1469
                           "Resources" G_DIR_SEPARATOR_S
1470
                           "lib" G_DIR_SEPARATOR_S
1471
                           "sylpheed" G_DIR_SEPARATOR_S
1472
                           PLUGIN_DIR,
1473
                           NULL);
1474
        syl_plugin_load_all(path);
1475
        g_free(path);
1476
#else
1477
        syl_plugin_load_all(PLUGINDIR);
1478
#endif
1479

    
1480
        STATUSBAR_POP(mainwin);
1481
}
1482

    
1483
static gchar *get_socket_name(void)
1484
{
1485
        static gchar *filename = NULL;
1486

    
1487
        if (filename == NULL) {
1488
                filename = g_strdup_printf("%s%c%s-%d",
1489
                                           g_get_tmp_dir(), G_DIR_SEPARATOR,
1490
                                           instance_id ? instance_id : "sylpheed",
1491
#if HAVE_GETUID
1492
                                           getuid());
1493
#else
1494
                                           0);
1495
#endif
1496
        }
1497

    
1498
        return filename;
1499
}
1500

    
1501
static gint prohibit_duplicate_launch(void)
1502
{
1503
        gint sock;
1504

    
1505
#ifdef G_OS_WIN32
1506
        HANDLE hmutex;
1507
        const gchar *ins_id = instance_id ? instance_id : "Sylpheed";
1508
        gushort port = cmd.ipcport ? cmd.ipcport : REMOTE_CMD_PORT;
1509

    
1510
        debug_print("prohibit_duplicate_launch: checking mutex: %s\n", ins_id);
1511
        hmutex = CreateMutexA(NULL, FALSE, ins_id);
1512
        if (!hmutex) {
1513
                g_warning("cannot create Mutex: %s\n", ins_id);
1514
                return -1;
1515
        }
1516
        if (GetLastError() != ERROR_ALREADY_EXISTS) {
1517
                debug_print("prohibit_duplicate_launch: creating socket: port %d\n", port);
1518
                sock = fd_open_inet(port);
1519
                if (sock < 0)
1520
                        return 0;
1521
                return sock;
1522
        }
1523

    
1524
        debug_print("prohibit_duplicate_launch: connecting to socket: port %d\n", port);
1525
        sock = fd_connect_inet(port);
1526
        if (sock < 0)
1527
                return -1;
1528
#else
1529
        gchar *path;
1530

    
1531
        path = get_socket_name();
1532
        debug_print("prohibit_duplicate_launch: checking socket: %s\n", path);
1533
        sock = fd_connect_unix(path);
1534
        if (sock < 0) {
1535
                debug_print("prohibit_duplicate_launch: creating socket: %s\n", path);
1536
                g_unlink(path);
1537
                return fd_open_unix(path);
1538
        }
1539
#endif
1540

    
1541
        /* remote command mode */
1542

    
1543
        debug_print(_("another Sylpheed is already running.\n"));
1544

    
1545
        if (cmd.receive_all)
1546
                fd_write_all(sock, "receive_all\n", 12);
1547
        else if (cmd.receive)
1548
                fd_write_all(sock, "receive\n", 8);
1549
        else if (cmd.compose && cmd.attach_files) {
1550
                gchar *str, *compose_str;
1551
                gint i;
1552

    
1553
                if (cmd.compose_mailto)
1554
                        compose_str = g_strdup_printf("compose_attach %s\n",
1555
                                                      cmd.compose_mailto);
1556
                else
1557
                        compose_str = g_strdup("compose_attach\n");
1558

    
1559
                fd_write_all(sock, compose_str, strlen(compose_str));
1560
                g_free(compose_str);
1561

    
1562
                for (i = 0; i < cmd.attach_files->len; i++) {
1563
                        str = g_ptr_array_index(cmd.attach_files, i);
1564
                        fd_write_all(sock, str, strlen(str));
1565
                        fd_write_all(sock, "\n", 1);
1566
                }
1567

    
1568
                fd_write_all(sock, ".\n", 2);
1569
        } else if (cmd.compose) {
1570
                gchar *compose_str;
1571

    
1572
                if (cmd.compose_mailto)
1573
                        compose_str = g_strdup_printf
1574
                                ("compose %s\n", cmd.compose_mailto);
1575
                else
1576
                        compose_str = g_strdup("compose\n");
1577

    
1578
                fd_write_all(sock, compose_str, strlen(compose_str));
1579
                g_free(compose_str);
1580
        } else if (cmd.send) {
1581
                fd_write_all(sock, "send\n", 5);
1582
        } else if (cmd.status || cmd.status_full) {
1583
                gchar buf[BUFFSIZE];
1584
                gint i;
1585
                const gchar *command;
1586
                GPtrArray *folders;
1587
                gchar *folder;
1588

    
1589
                command = cmd.status_full ? "status-full\n" : "status\n";
1590
                folders = cmd.status_full ? cmd.status_full_folders :
1591
                        cmd.status_folders;
1592

    
1593
                fd_write_all(sock, command, strlen(command));
1594
                for (i = 0; folders && i < folders->len; ++i) {
1595
                        folder = g_ptr_array_index(folders, i);
1596
                        fd_write_all(sock, folder, strlen(folder));
1597
                        fd_write_all(sock, "\n", 1);
1598
                }
1599
                fd_write_all(sock, ".\n", 2);
1600
                for (;;) {
1601
                        if (fd_gets(sock, buf, sizeof(buf)) <= 0) break;
1602
                        if (!strncmp(buf, ".\n", 2)) break;
1603
                        fputs(buf, stdout);
1604
                }
1605
        } else if (cmd.open_msg) {
1606
                gchar *str;
1607

    
1608
                str = g_strdup_printf("open %s\n", cmd.open_msg);
1609
                fd_write_all(sock, str, strlen(str));
1610
                g_free(str);
1611
        } else if (cmd.exit) {
1612
                fd_write_all(sock, "exit\n", 5);
1613
        } else {
1614
#ifdef G_OS_WIN32
1615
                HWND hwnd;
1616

    
1617
                fd_write_all(sock, "popup\n", 6);
1618
                if (fd_read(sock, (gchar *)&hwnd, sizeof(hwnd)) == sizeof(hwnd))
1619
                        SetForegroundWindow(hwnd);
1620
#else
1621
                fd_write_all(sock, "popup\n", 6);
1622
#endif
1623
        }
1624

    
1625
        fd_close(sock);
1626
        return -1;
1627
}
1628

    
1629
static gint lock_socket_remove(void)
1630
{
1631
#ifndef G_OS_WIN32
1632
        gchar *filename;
1633
#endif
1634

    
1635
        if (lock_socket < 0) return -1;
1636

    
1637
        if (lock_socket_tag > 0)
1638
                g_source_remove(lock_socket_tag);
1639
        if (lock_ch) {
1640
                g_io_channel_shutdown(lock_ch, FALSE, NULL);
1641
                g_io_channel_unref(lock_ch);
1642
                lock_ch = NULL;
1643
        }
1644

    
1645
#ifndef G_OS_WIN32
1646
        filename = get_socket_name();
1647
        debug_print("lock_socket_remove: removing socket: %s\n", filename);
1648
        g_unlink(filename);
1649
#endif
1650

    
1651
        return 0;
1652
}
1653

    
1654
static GPtrArray *get_folder_item_list(gint sock)
1655
{
1656
        gchar buf[BUFFSIZE];
1657
        FolderItem *item;
1658
        GPtrArray *folders = NULL;
1659

    
1660
        for (;;) {
1661
                if (fd_gets(sock, buf, sizeof(buf)) <= 0) break;
1662
                if (!strncmp(buf, ".\n", 2)) break;
1663
                strretchomp(buf);
1664
                if (!folders) folders = g_ptr_array_new();
1665
                item = folder_find_item_from_identifier(buf);
1666
                if (item)
1667
                        g_ptr_array_add(folders, item);
1668
                else
1669
                        g_warning("no such folder: %s\n", buf);
1670
        }
1671

    
1672
        return folders;
1673
}
1674

    
1675
static gboolean lock_socket_input_cb(GIOChannel *source, GIOCondition condition,
1676
                                     gpointer data)
1677
{
1678
        MainWindow *mainwin = (MainWindow *)data;
1679
        gint fd, sock;
1680
        gchar buf[BUFFSIZE];
1681

    
1682
#if USE_THREADS
1683
        gdk_threads_enter();
1684
#endif
1685

    
1686
        fd = g_io_channel_unix_get_fd(source);
1687
        sock = fd_accept(fd);
1688
        if (fd_gets(sock, buf, sizeof(buf)) <= 0) {
1689
                fd_close(sock);
1690
#if USE_THREADS
1691
                gdk_threads_leave();
1692
#endif
1693
                return TRUE;
1694
        }
1695

    
1696
        if (!strncmp(buf, "popup", 5)) {
1697
#ifdef G_OS_WIN32
1698
                HWND hwnd;
1699

    
1700
                hwnd = (HWND)gdk_win32_drawable_get_handle
1701
                        (GDK_DRAWABLE(mainwin->window->window));
1702
                fd_write(sock, (gchar *)&hwnd, sizeof(hwnd));
1703
                if (mainwin->window_hidden)
1704
                        main_window_popup(mainwin);
1705
#else
1706
                main_window_popup(mainwin);
1707
#endif
1708
        } else if (!strncmp(buf, "receive_all", 11)) {
1709
                main_window_popup(mainwin);
1710
                if (!gtkut_window_modal_exist())
1711
                        inc_all_account_mail(mainwin, FALSE);
1712
        } else if (!strncmp(buf, "receive", 7)) {
1713
                main_window_popup(mainwin);
1714
                if (!gtkut_window_modal_exist())
1715
                        inc_mail(mainwin);
1716
        } else if (!strncmp(buf, "compose_attach", 14)) {
1717
                GPtrArray *files;
1718
                gchar *mailto;
1719

    
1720
                mailto = g_strdup(buf + strlen("compose_attach") + 1);
1721
                files = g_ptr_array_new();
1722
                while (fd_gets(sock, buf, sizeof(buf)) > 0) {
1723
                        if (buf[0] == '.' && buf[1] == '\n') break;
1724
                        strretchomp(buf);
1725
                        g_ptr_array_add(files, g_strdup(buf));
1726
                }
1727
                open_compose_new(mailto, files);
1728
                ptr_array_free_strings(files);
1729
                g_ptr_array_free(files, TRUE);
1730
                g_free(mailto);
1731
        } else if (!strncmp(buf, "compose", 7)) {
1732
                open_compose_new(buf + strlen("compose") + 1, NULL);
1733
        } else if (!strncmp(buf, "send", 4)) {
1734
                send_queue();
1735
        } else if (!strncmp(buf, "status-full", 11) ||
1736
                   !strncmp(buf, "status", 6)) {
1737
                gchar *status;
1738
                GPtrArray *folders;
1739

    
1740
                folders = get_folder_item_list(sock);
1741
                status = folder_get_status
1742
                        (folders, !strncmp(buf, "status-full", 11));
1743
                fd_write_all(sock, status, strlen(status));
1744
                fd_write_all(sock, ".\n", 2);
1745
                g_free(status);
1746
                if (folders) g_ptr_array_free(folders, TRUE);
1747
        } else if (!strncmp(buf, "open", 4)) {
1748
                strretchomp(buf);
1749
                if (strlen(buf) < 6 || buf[4] != ' ') {
1750
                        fd_close(sock);
1751
#if USE_THREADS
1752
                        gdk_threads_leave();
1753
#endif
1754
                        return TRUE;
1755
                }
1756
                open_message(buf + 5);
1757
        } else if (!strncmp(buf, "exit", 4)) {
1758
                fd_close(sock);
1759
                app_will_exit(TRUE);
1760
        }
1761

    
1762
        fd_close(sock);
1763

    
1764
#if USE_THREADS
1765
        gdk_threads_leave();
1766
#endif
1767

    
1768
        return TRUE;
1769
}
1770

    
1771
static void remote_command_exec(void)
1772
{
1773
        MainWindow *mainwin;
1774

    
1775
        mainwin = main_window_get();
1776

    
1777
        if (prefs_common.open_inbox_on_startup) {
1778
                FolderItem *item;
1779
                PrefsAccount *ac;
1780

    
1781
                ac = account_get_default();
1782
                if (!ac)
1783
                        ac = cur_account;
1784
                item = ac && ac->inbox
1785
                        ? folder_find_item_from_identifier(ac->inbox)
1786
                        : folder_get_default_inbox();
1787
                folderview_select(mainwin->folderview, item);
1788
        }
1789

    
1790
        if (!gtkut_window_modal_exist()) {
1791
                if (cmd.compose)
1792
                        open_compose_new(cmd.compose_mailto, cmd.attach_files);
1793

    
1794
                if (cmd.open_msg)
1795
                        open_message(cmd.open_msg);
1796

    
1797
                if (cmd.receive_all)
1798
                        inc_all_account_mail(mainwin, FALSE);
1799
                else if (prefs_common.chk_on_startup)
1800
                        inc_all_account_mail(mainwin, TRUE);
1801
                else if (cmd.receive)
1802
                        inc_mail(mainwin);
1803

    
1804
                if (cmd.send)
1805
                        send_queue();
1806
        }
1807

    
1808
        if (cmd.attach_files) {
1809
                ptr_array_free_strings(cmd.attach_files);
1810
                g_ptr_array_free(cmd.attach_files, TRUE);
1811
                cmd.attach_files = NULL;
1812
        }
1813
        if (cmd.status_folders) {
1814
                g_ptr_array_free(cmd.status_folders, TRUE);
1815
                cmd.status_folders = NULL;
1816
        }
1817
        if (cmd.status_full_folders) {
1818
                g_ptr_array_free(cmd.status_full_folders, TRUE);
1819
                cmd.status_full_folders = NULL;
1820
        }
1821
        if (cmd.open_msg) {
1822
                g_free(cmd.open_msg);
1823
                cmd.open_msg = NULL;
1824
        }
1825
        if (cmd.exit) {
1826
                app_will_exit(TRUE);
1827
        }
1828
}
1829

    
1830
#if !defined(G_OS_WIN32) && !defined(__APPLE__)
1831
static void migrate_old_config(void)
1832
{
1833
        GDir *dir;
1834
        const gchar *dir_name;
1835
        GPatternSpec *pspec;
1836

    
1837
        if (alertpanel(_("Migration of configuration"),
1838
                       _("The previous version of configuration found.\n"
1839
                         "Do you want to migrate it?"),
1840
                       GTK_STOCK_YES, GTK_STOCK_NO, NULL) != G_ALERTDEFAULT)
1841
                return;
1842

    
1843
        debug_print("Migrating old configuration...\n");
1844

    
1845
#define COPY_FILE(rcfile)                                                \
1846
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile)) {        \
1847
                conv_copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile,        \
1848
                               RC_DIR G_DIR_SEPARATOR_S rcfile,                \
1849
                               conv_get_locale_charset_str());                \
1850
        }
1851

    
1852
        COPY_FILE(ACCOUNT_RC);
1853
        COPY_FILE(ACTIONS_RC);
1854
        COPY_FILE(COMMON_RC);
1855
        COPY_FILE(CUSTOM_HEADER_RC);
1856
        COPY_FILE(DISPLAY_HEADER_RC);
1857
        COPY_FILE(FILTER_HEADER_RC);
1858
        COPY_FILE(COMMAND_HISTORY);
1859

    
1860
#undef COPY_FILE
1861

    
1862
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST))
1863
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST,
1864
                          RC_DIR G_DIR_SEPARATOR_S FILTER_LIST, FALSE);
1865
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST))
1866
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST,
1867
                          RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST, FALSE);
1868
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types"))
1869
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types",
1870
                          RC_DIR G_DIR_SEPARATOR_S "mime.types", FALSE);
1871

    
1872
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR))
1873
                conv_copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1874
                              RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1875
                              conv_get_locale_charset_str());
1876
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR))
1877
                copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR,
1878
                         RC_DIR G_DIR_SEPARATOR_S UIDL_DIR);
1879

    
1880
        if (!is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S ADDRESSBOOK_INDEX_FILE))
1881
                return;
1882

    
1883
        if ((dir = g_dir_open(OLD_RC_DIR, 0, NULL)) == NULL) {
1884
                g_warning("failed to open directory: %s\n", OLD_RC_DIR);
1885
                return;
1886
        }
1887

    
1888
        pspec = g_pattern_spec_new("addrbook-*.xml");
1889

    
1890
        while ((dir_name = g_dir_read_name(dir)) != NULL) {
1891
                if (g_pattern_match_string(pspec, dir_name)) {
1892
                        gchar *old_file;
1893
                        gchar *new_file;
1894

    
1895
                        old_file = g_strconcat(OLD_RC_DIR G_DIR_SEPARATOR_S,
1896
                                               dir_name, NULL);
1897
                        new_file = g_strconcat(RC_DIR G_DIR_SEPARATOR_S,
1898
                                               dir_name, NULL);
1899
                        copy_file(old_file, new_file, FALSE);
1900
                        g_free(new_file);
1901
                        g_free(old_file);
1902
                }
1903
        }
1904

    
1905
        g_pattern_spec_free(pspec);
1906
        g_dir_close(dir);
1907
}
1908
#endif /* !G_OS_WIN32 && !__APPLE__ */
1909

    
1910
static void open_compose_new(const gchar *address, GPtrArray *attach_files)
1911
{
1912
        gchar *utf8addr = NULL;
1913
#ifdef G_OS_WIN32
1914
        GPtrArray *utf8files = NULL;
1915
#endif
1916

    
1917
        if (gtkut_window_modal_exist())
1918
                return;
1919

    
1920
        if (address) {
1921
                utf8addr = g_locale_to_utf8(address, -1, NULL, NULL, NULL);
1922
                if (utf8addr)
1923
                        g_strstrip(utf8addr);
1924
                debug_print("open compose: %s\n", utf8addr ? utf8addr : "");
1925
        }
1926

    
1927
#ifdef G_OS_WIN32
1928
        if (attach_files) {
1929
                gint i;
1930
                gchar *file, *utf8file;
1931

    
1932
                utf8files = g_ptr_array_new();
1933
                for (i = 0; i < attach_files->len; i++) {
1934
                        file = g_ptr_array_index(attach_files, i);
1935
                        utf8file = g_locale_to_utf8(file, -1, NULL, NULL, NULL);
1936
                        if (utf8file)
1937
                                g_ptr_array_add(utf8files, utf8file);
1938
                }
1939
        }
1940

    
1941
        compose_new(NULL, NULL, utf8addr, utf8files);
1942
        if (utf8files) {
1943
                ptr_array_free_strings(utf8files);
1944
                g_ptr_array_free(utf8files, TRUE);
1945
        }
1946
#else
1947
        compose_new(NULL, NULL, utf8addr, attach_files);
1948
#endif
1949

    
1950
        g_free(utf8addr);
1951
}
1952

    
1953
static void open_message_file(const gchar *file)
1954
{
1955
        MsgInfo *msginfo;
1956
        MsgFlags flags = {0};
1957
        MessageView *msgview;
1958

    
1959
        g_return_if_fail(file != NULL);
1960

    
1961
        debug_print("open message file: %s\n", file);
1962

    
1963
        if (!is_file_exist(file) || get_file_size(file) <= 0) {
1964
                debug_print("file not found: %s\n", file);
1965
                return;
1966
        }
1967

    
1968
        msginfo = procheader_parse_file(file, flags, FALSE);
1969
        if (msginfo) {
1970
                msginfo->file_path = g_strdup(file);
1971
                msgview = messageview_create_with_new_window();
1972
                messageview_show(msgview, msginfo, FALSE);
1973
                procmsg_msginfo_free(msginfo);
1974
        } else
1975
                debug_print("cannot open message: %s\n", file);
1976
}
1977

    
1978
static void open_message(const gchar *path)
1979
{
1980
        gchar *fid;
1981
        gchar *msg;
1982
        gint num;
1983
        FolderItem *item;
1984
        MsgInfo *msginfo;
1985
        MessageView *msgview;
1986
        gchar *file;
1987

    
1988
        g_return_if_fail(path != NULL);
1989

    
1990
        if (gtkut_window_modal_exist())
1991
                return;
1992

    
1993
        debug_print("open message: %s\n", path);
1994

    
1995
        if (!strncmp(path, "file:", 5)) {
1996
                file = g_filename_from_uri(path, NULL, NULL);
1997
                open_message_file(file);
1998
                g_free(file);
1999
                return;
2000
        } else if (g_path_is_absolute(path)) {
2001
                open_message_file(path);
2002
                return;
2003
        }
2004

    
2005
        /* relative path, or folder identifier */
2006

    
2007
        fid = g_path_get_dirname(path);
2008
        msg = g_path_get_basename(path);
2009
        num = to_number(msg);
2010
        item = folder_find_item_from_identifier(fid);
2011

    
2012
        if (num > 0 && item) {
2013
                debug_print("open folder id: %s (msg %d)\n", fid, num);
2014
                msginfo = folder_item_get_msginfo(item, num);
2015
                if (msginfo) {
2016
                        msgview = messageview_create_with_new_window();
2017
                        messageview_show(msgview, msginfo, FALSE);
2018
                        procmsg_msginfo_free(msginfo);
2019
                        g_free(msg);
2020
                        g_free(fid);
2021
                        return;
2022
                } else
2023
                        debug_print("message %d not found\n", num);
2024
        }
2025

    
2026
        g_free(msg);
2027
        g_free(fid);
2028

    
2029
        /* relative path */
2030

    
2031
        file = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, path, NULL);
2032
        open_message_file(file);
2033
        g_free(file);
2034
}
2035

    
2036
static void send_queue(void)
2037
{
2038
        GList *list;
2039

    
2040
        if (gtkut_window_modal_exist())
2041
                return;
2042
        if (!main_window_toggle_online_if_offline(main_window_get()))
2043
                return;
2044

    
2045
        for (list = folder_get_list(); list != NULL; list = list->next) {
2046
                Folder *folder = list->data;
2047

    
2048
                if (folder->queue) {
2049
                        gint ret;
2050

    
2051
                        ret = send_message_queue_all(folder->queue,
2052
                                                     prefs_common.savemsg,
2053
                                                     prefs_common.filter_sent);
2054
                        statusbar_pop_all();
2055
                        if (ret > 0)
2056
                                folder_item_scan(folder->queue);
2057
                }
2058
        }
2059

    
2060
        folderview_update_all_updated(TRUE);
2061
        main_window_set_menu_sensitive(main_window_get());
2062
        main_window_set_toolbar_sensitive(main_window_get());
2063
}