Statistics
| Revision:

root / src / main.c @ 3397

History | View | Annotate | Download (49.3 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
                suffix = g_strdup("12");
509
        g_free(style);        
510
        g_free(size);
511
#ifdef G_OS_WIN32
512
        str = g_strconcat("MS Gothic ", suffix, NULL);
513
#else /* __APPLE__ */
514
        str = g_strconcat("Hiragino Kaku Gothic Pro ", suffix, NULL);
515
#endif
516

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

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

    
542
        g_free(suffix);
543
}
544
#endif
545

    
546
static void parse_cmd_opt(int argc, char *argv[])
547
{
548
        gint i;
549

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

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

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

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

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

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

    
630
                        if (p && *p != '\0' && *p != '-') {
631
                                /* this must only be done at startup */
632
#ifdef G_OS_WIN32
633
                                gchar *utf8dir;
634

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

    
668
                        g_print(_("Usage: %s [OPTIONS ...] [URL]\n"),
669
                                g_basename(argv[0]));
670

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

    
693
#ifdef G_OS_WIN32
694
                        g_print("\n");
695
                        g_print(_("Press any key..."));
696
                        _getch();
697
#endif
698

    
699
                        cleanup_console();
700
                        exit(1);
701
                } else {
702
                        /* file or URL */
703
                        const gchar *p = argv[i];
704

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

    
719
        if (cmd.attach_files && cmd.compose == FALSE) {
720
                cmd.compose = TRUE;
721
                cmd.compose_mailto = NULL;
722
        }
723

    
724
        cmd.argv0 = g_locale_to_utf8(argv[0], -1, NULL, NULL, NULL);
725
        if (!cmd.argv0)
726
                cmd.argv0 = g_strdup(argv[0]);
727
}
728

    
729
static gint get_queued_message_num(void)
730
{
731
        FolderItem *queue;
732

    
733
        queue = folder_get_default_queue();
734
        if (!queue) return -1;
735

    
736
        folder_item_scan(queue);
737
        return queue->total;
738
}
739

    
740
#if USE_THREADS
741
/* enables recursive locking with gdk_thread_enter / gdk_threads_leave */
742
static GStaticRecMutex syl_mutex = G_STATIC_REC_MUTEX_INIT;
743

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

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

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

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

    
791
#if USE_THREADS
792
        set_event_loop_func(event_loop_iteration_func);
793
#endif
794
        prog_version = PROG_VERSION;
795

    
796
#ifdef G_OS_WIN32
797
        read_ini_file();
798
#endif
799
}
800

    
801
static void parse_gtkrc_files(void)
802
{
803
        gchar *userrc;
804

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

    
818
        userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
819
        gtk_accel_map_load(userrc);
820
        g_free(userrc);
821
}
822

    
823
static void setup_rc_dir(void)
824
{
825
#if !defined(G_OS_WIN32) && !defined(__APPLE__)
826
        CHDIR_EXIT_IF_FAIL(get_home_dir(), 1);
827

    
828
        /* backup if old rc file exists */
829
        if (!cmd.configdir && is_file_exist(RC_DIR)) {
830
                if (rename_force(RC_DIR, RC_DIR ".bak") < 0)
831
                        FILE_OP_ERROR(RC_DIR, "rename");
832
        }
833

    
834
        /* migration from ~/.sylpheed to ~/.sylpheed-2.0 */
835
        if (!cmd.configdir && !is_dir_exist(RC_DIR)) {
836
                const gchar *envstr;
837
                AlertValue val;
838

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

    
860
                if (make_dir(RC_DIR) < 0)
861
                        exit(1);
862
                if (is_dir_exist(OLD_RC_DIR))
863
                        migrate_old_config();
864
        }
865
#endif /* !G_OS_WIN32 && !__APPLE__ */
866

    
867
        syl_setup_rc_dir();
868
}
869

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

    
906
void app_will_restart(gboolean force)
907
{
908
        cmd.restart = TRUE;
909
        app_will_exit(force);
910
        /* canceled */
911
        cmd.restart = FALSE;
912
}
913

    
914
void app_will_exit(gboolean force)
915
{
916
        MainWindow *mainwin;
917
        gchar *filename;
918
        static gboolean on_exit = FALSE;
919
        GList *cur;
920

    
921
        if (on_exit)
922
                return;
923
        on_exit = TRUE;
924

    
925
        mainwin = main_window_get();
926

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

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

    
950
        if (force)
951
                g_signal_emit_by_name(syl_app_get(), "app-force-exit");
952
        g_signal_emit_by_name(syl_app_get(), "app-exit");
953

    
954
        inc_autocheck_timer_remove();
955

    
956
        if (prefs_common.clean_on_exit)
957
                main_window_empty_trash(mainwin,
958
                                        !force && prefs_common.ask_on_clean);
959

    
960
        for (cur = account_get_list(); cur != NULL; cur = cur->next) {
961
                PrefsAccount *ac = (PrefsAccount *)cur->data;
962
                if (ac->protocol == A_IMAP4 && ac->imap_clear_cache_on_exit &&
963
                    ac->folder)
964
                        procmsg_remove_all_cached_messages(FOLDER(ac->folder));
965
        }
966

    
967
        syl_plugin_unload_all();
968

    
969
        trayicon_destroy(mainwin->tray_icon);
970

    
971
        /* save all state before exiting */
972
        summary_write_cache(mainwin->summaryview);
973
        main_window_get_size(mainwin);
974
        main_window_get_position(mainwin);
975
        syl_save_all_state();
976
        addressbook_export_to_file();
977

    
978
        filename = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
979
        gtk_accel_map_save(filename);
980
        g_free(filename);
981

    
982
        /* remove temporary files, close log file, socket cleanup */
983
#if USE_SSL
984
        ssl_done();
985
#endif
986
        syl_cleanup();
987
        lock_socket_remove();
988

    
989
#ifdef USE_UPDATE_CHECK_PLUGIN
990
#ifdef G_OS_WIN32
991
        cur = gtk_window_list_toplevels();
992
        g_list_foreach(cur, (GFunc)gtk_widget_hide, NULL);
993
        g_list_free(cur);
994
        update_check_spawn_plugin_updater();
995
#endif
996
#endif
997

    
998
        cleanup_console();
999

    
1000
        if (gtk_main_level() > 0)
1001
                gtk_main_quit();
1002

    
1003
        if (cmd.restart)
1004
                app_restart();
1005

    
1006
        exit(0);
1007
}
1008

    
1009
#if 0
1010
#if USE_GPGME
1011
static void idle_function_for_gpgme(void)
1012
{
1013
        while (gtk_events_pending())
1014
                gtk_main_iteration();
1015
}
1016
#endif /* USE_GPGME */
1017
#endif /* 0 */
1018

    
1019
static void check_gpg(void)
1020
{
1021
#if USE_GPGME
1022
        const gchar *version;
1023
        gpgme_error_t err = 0;
1024

    
1025
        version = gpgme_check_version("1.0.0");
1026
        if (version) {
1027
                debug_print("GPGME Version: %s\n", version);
1028
                err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
1029
                if (err)
1030
                        debug_print("gpgme_engine_check_version: %s\n",
1031
                                    gpgme_strerror(err));
1032
        }
1033

    
1034
        if (version && !err) {
1035
                /* Also does some gpgme init */
1036
                gpgme_engine_info_t engineInfo;
1037

    
1038
#if HAVE_LOCALE_H
1039
                gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
1040
                gpgme_set_locale(NULL, LC_MESSAGES,
1041
                                 setlocale(LC_MESSAGES, NULL));
1042
#endif
1043

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

    
1055
                procmsg_set_decrypt_message_func
1056
                        (rfc2015_open_message_decrypted);
1057
                procmsg_set_auto_decrypt_message(TRUE);
1058
        } else {
1059
                rfc2015_disable_all();
1060

    
1061
                if (prefs_common.gpg_warning) {
1062
                        AlertValue val;
1063

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

    
1082
static void default_log_func(const gchar *log_domain, GLogLevelFlags log_level,
1083
                             const gchar *message, gpointer user_data)
1084
{
1085
        gchar *prefix = "";
1086
        gchar *file_prefix = "";
1087
        LogType level = LOG_NORMAL;
1088
        gchar *str;
1089
        const gchar *message_;
1090

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

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

    
1138
        g_log_default_handler(log_domain, log_level, message, user_data);
1139
}
1140

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

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

    
1177
#ifdef G_OS_WIN32
1178

    
1179
#if !GTK_CHECK_VERSION(2, 14, 0)
1180
static UINT taskbar_created_msg;
1181
#endif
1182

    
1183
static BOOL WINAPI
1184
ctrl_handler(DWORD dwctrltype)
1185
{
1186
        log_print("ctrl_handler: received %d\n", dwctrltype);
1187
        app_will_exit(TRUE);
1188

    
1189
        return TRUE;
1190
}
1191

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

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

    
1233
        return DefWindowProc(hwnd, message, wparam, lparam);
1234
}
1235

    
1236
static void register_system_events(void)
1237
{
1238
        WNDCLASS wclass;
1239
        static HWND hwnd = NULL;
1240
        static BOOL ctrl_handler_set = FALSE;
1241
        ATOM klass;
1242
        HINSTANCE hmodule = GetModuleHandle(NULL);
1243

    
1244
        if (init_console_done && !ctrl_handler_set) {
1245
                debug_print("register_system_events(): SetConsoleCtrlHandler\n");
1246
                ctrl_handler_set = SetConsoleCtrlHandler(ctrl_handler, TRUE);
1247
                if (!ctrl_handler_set)
1248
                        g_warning("SetConsoleCtrlHandler() failed\n");
1249
        }
1250

    
1251
        if (hwnd)
1252
                return;
1253

    
1254
#if !GTK_CHECK_VERSION(2, 14, 0)
1255
        taskbar_created_msg = RegisterWindowMessage("TaskbarCreated");
1256
#endif
1257

    
1258
        debug_print("register_system_events(): RegisterClass\n");
1259

    
1260
        memset(&wclass, 0, sizeof(WNDCLASS));
1261
        wclass.lpszClassName = "sylpheed-observer";
1262
        wclass.lpfnWndProc   = wndproc;
1263
        wclass.hInstance     = hmodule;
1264

    
1265
        klass = RegisterClass(&wclass);
1266
        if (!klass)
1267
                return;
1268

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

    
1279
        switch (signum) {
1280
        case SIGHUP:
1281
        case SIGINT:
1282
        case SIGTERM:
1283
        case SIGQUIT:
1284
                app_will_exit(TRUE);
1285
                break;
1286
        default:
1287
                break;
1288
        }
1289
}
1290

    
1291
static void register_system_events(void)
1292
{
1293
        struct sigaction sa;
1294

    
1295
        memset(&sa, 0, sizeof(sa));
1296
        sa.sa_handler = sig_handler;
1297
        sa.sa_flags = SA_RESTART;
1298

    
1299
        sigemptyset(&sa.sa_mask);
1300
        sigaddset(&sa.sa_mask, SIGHUP);
1301
        sigaddset(&sa.sa_mask, SIGINT);
1302
        sigaddset(&sa.sa_mask, SIGTERM);
1303
        sigaddset(&sa.sa_mask, SIGQUIT);
1304
        sigaddset(&sa.sa_mask, SIGPIPE);
1305

    
1306
        sigaction(SIGHUP, &sa, NULL);
1307
        sigaction(SIGINT, &sa, NULL);
1308
        sigaction(SIGTERM, &sa, NULL);
1309
        sigaction(SIGQUIT, &sa, NULL);
1310
        sigaction(SIGPIPE, &sa, NULL);
1311
}
1312
#endif
1313

    
1314
#define ADD_SYM(sym)        syl_plugin_add_symbol(#sym, sym)
1315

    
1316
static void plugin_init(void)
1317
{
1318
        MainWindow *mainwin;
1319
        gchar *path;
1320

    
1321
        mainwin = main_window_get();
1322

    
1323
        STATUSBAR_PUSH(mainwin, _("Loading plug-ins..."));
1324

    
1325
        if (syl_plugin_init_lib() != 0) {
1326
                STATUSBAR_POP(mainwin);
1327
                return;
1328
        }
1329

    
1330
        if (cmd.safe_mode) {
1331
                debug_print("plugin_init: safe mode enabled, skipping plug-in loading.\n");
1332
                STATUSBAR_POP(mainwin);
1333
                return;
1334
        }
1335

    
1336
        ADD_SYM(prog_version);
1337
        ADD_SYM(app_will_exit);
1338

    
1339
        ADD_SYM(main_window_lock);
1340
        ADD_SYM(main_window_unlock);
1341
        ADD_SYM(main_window_get);
1342
        ADD_SYM(main_window_popup);
1343

    
1344
        syl_plugin_add_symbol("main_window_menu_factory",
1345
                              mainwin->menu_factory);
1346
        syl_plugin_add_symbol("main_window_statusbar", mainwin->statusbar);
1347

    
1348
        ADD_SYM(folderview_get);
1349
        ADD_SYM(folderview_add_sub_widget);
1350
        ADD_SYM(folderview_select);
1351
        ADD_SYM(folderview_unselect);
1352
        ADD_SYM(folderview_select_next_unread);
1353
        ADD_SYM(folderview_get_selected_item);
1354
        ADD_SYM(folderview_check_new);
1355
        ADD_SYM(folderview_check_new_item);
1356
        ADD_SYM(folderview_check_new_all);
1357
        ADD_SYM(folderview_update_item);
1358
        ADD_SYM(folderview_update_item_foreach);
1359
        ADD_SYM(folderview_update_all_updated);
1360
        ADD_SYM(folderview_check_new_selected);
1361

    
1362
        syl_plugin_add_symbol("folderview_mail_popup_factory",
1363
                              mainwin->folderview->mail_factory);
1364
        syl_plugin_add_symbol("folderview_imap_popup_factory",
1365
                              mainwin->folderview->imap_factory);
1366
        syl_plugin_add_symbol("folderview_news_popup_factory",
1367
                              mainwin->folderview->news_factory);
1368

    
1369
        syl_plugin_add_symbol("summaryview", mainwin->summaryview);
1370
        syl_plugin_add_symbol("summaryview_popup_factory",
1371
                              mainwin->summaryview->popupfactory);
1372

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

    
1394
        ADD_SYM(messageview_create_with_new_window);
1395
        ADD_SYM(messageview_show);
1396

    
1397
        ADD_SYM(compose_new);
1398
        ADD_SYM(compose_entry_set);
1399
        ADD_SYM(compose_entry_append);
1400
        ADD_SYM(compose_entry_get_text);
1401
        ADD_SYM(compose_lock);
1402
        ADD_SYM(compose_unlock);
1403

    
1404
        ADD_SYM(foldersel_folder_sel);
1405
        ADD_SYM(foldersel_folder_sel_full);
1406

    
1407
        ADD_SYM(input_dialog);
1408
        ADD_SYM(input_dialog_with_invisible);
1409

    
1410
        ADD_SYM(manage_window_set_transient);
1411
        ADD_SYM(manage_window_signals_connect);
1412
        ADD_SYM(manage_window_get_focus_window);
1413

    
1414
        ADD_SYM(inc_mail);
1415
        ADD_SYM(inc_is_active);
1416
        ADD_SYM(inc_lock);
1417
        ADD_SYM(inc_unlock);
1418

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

    
1435
        ADD_SYM(alertpanel_full);
1436
        ADD_SYM(alertpanel);
1437
        ADD_SYM(alertpanel_message);
1438
        ADD_SYM(alertpanel_message_with_disable);
1439

    
1440
        ADD_SYM(send_message);
1441
        ADD_SYM(send_message_queue_all);
1442
        ADD_SYM(send_message_set_reply_flag);
1443
        ADD_SYM(send_message_set_forward_flags);
1444

    
1445
        ADD_SYM(notification_window_open);
1446
        ADD_SYM(notification_window_set_message);
1447
        ADD_SYM(notification_window_close);
1448

    
1449
        syl_plugin_signal_connect("plugin-load", G_CALLBACK(load_cb), NULL);
1450

    
1451
        /* loading plug-ins from user plug-in directory */
1452
        path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, PLUGIN_DIR, NULL);
1453
        syl_plugin_load_all(path);
1454
        g_free(path);
1455

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

    
1476
        STATUSBAR_POP(mainwin);
1477
}
1478

    
1479
static gchar *get_socket_name(void)
1480
{
1481
        static gchar *filename = NULL;
1482

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

    
1494
        return filename;
1495
}
1496

    
1497
static gint prohibit_duplicate_launch(void)
1498
{
1499
        gint sock;
1500

    
1501
#ifdef G_OS_WIN32
1502
        HANDLE hmutex;
1503
        const gchar *ins_id = instance_id ? instance_id : "Sylpheed";
1504
        gushort port = cmd.ipcport ? cmd.ipcport : REMOTE_CMD_PORT;
1505

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

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

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

    
1537
        /* remote command mode */
1538

    
1539
        debug_print(_("another Sylpheed is already running.\n"));
1540

    
1541
        if (cmd.receive_all)
1542
                fd_write_all(sock, "receive_all\n", 12);
1543
        else if (cmd.receive)
1544
                fd_write_all(sock, "receive\n", 8);
1545
        else if (cmd.compose && cmd.attach_files) {
1546
                gchar *str, *compose_str;
1547
                gint i;
1548

    
1549
                if (cmd.compose_mailto)
1550
                        compose_str = g_strdup_printf("compose_attach %s\n",
1551
                                                      cmd.compose_mailto);
1552
                else
1553
                        compose_str = g_strdup("compose_attach\n");
1554

    
1555
                fd_write_all(sock, compose_str, strlen(compose_str));
1556
                g_free(compose_str);
1557

    
1558
                for (i = 0; i < cmd.attach_files->len; i++) {
1559
                        str = g_ptr_array_index(cmd.attach_files, i);
1560
                        fd_write_all(sock, str, strlen(str));
1561
                        fd_write_all(sock, "\n", 1);
1562
                }
1563

    
1564
                fd_write_all(sock, ".\n", 2);
1565
        } else if (cmd.compose) {
1566
                gchar *compose_str;
1567

    
1568
                if (cmd.compose_mailto)
1569
                        compose_str = g_strdup_printf
1570
                                ("compose %s\n", cmd.compose_mailto);
1571
                else
1572
                        compose_str = g_strdup("compose\n");
1573

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

    
1585
                command = cmd.status_full ? "status-full\n" : "status\n";
1586
                folders = cmd.status_full ? cmd.status_full_folders :
1587
                        cmd.status_folders;
1588

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

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

    
1613
                fd_write_all(sock, "popup\n", 6);
1614
                if (fd_read(sock, (gchar *)&hwnd, sizeof(hwnd)) == sizeof(hwnd))
1615
                        SetForegroundWindow(hwnd);
1616
#else
1617
                fd_write_all(sock, "popup\n", 6);
1618
#endif
1619
        }
1620

    
1621
        fd_close(sock);
1622
        return -1;
1623
}
1624

    
1625
static gint lock_socket_remove(void)
1626
{
1627
#ifndef G_OS_WIN32
1628
        gchar *filename;
1629
#endif
1630

    
1631
        if (lock_socket < 0) return -1;
1632

    
1633
        if (lock_socket_tag > 0)
1634
                g_source_remove(lock_socket_tag);
1635
        if (lock_ch) {
1636
                g_io_channel_shutdown(lock_ch, FALSE, NULL);
1637
                g_io_channel_unref(lock_ch);
1638
                lock_ch = NULL;
1639
        }
1640

    
1641
#ifndef G_OS_WIN32
1642
        filename = get_socket_name();
1643
        debug_print("lock_socket_remove: removing socket: %s\n", filename);
1644
        g_unlink(filename);
1645
#endif
1646

    
1647
        return 0;
1648
}
1649

    
1650
static GPtrArray *get_folder_item_list(gint sock)
1651
{
1652
        gchar buf[BUFFSIZE];
1653
        FolderItem *item;
1654
        GPtrArray *folders = NULL;
1655

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

    
1668
        return folders;
1669
}
1670

    
1671
static gboolean lock_socket_input_cb(GIOChannel *source, GIOCondition condition,
1672
                                     gpointer data)
1673
{
1674
        MainWindow *mainwin = (MainWindow *)data;
1675
        gint fd, sock;
1676
        gchar buf[BUFFSIZE];
1677

    
1678
#if USE_THREADS
1679
        gdk_threads_enter();
1680
#endif
1681

    
1682
        fd = g_io_channel_unix_get_fd(source);
1683
        sock = fd_accept(fd);
1684
        if (fd_gets(sock, buf, sizeof(buf)) <= 0) {
1685
                fd_close(sock);
1686
#if USE_THREADS
1687
                gdk_threads_leave();
1688
#endif
1689
                return TRUE;
1690
        }
1691

    
1692
        if (!strncmp(buf, "popup", 5)) {
1693
#ifdef G_OS_WIN32
1694
                HWND hwnd;
1695

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

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

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

    
1758
        fd_close(sock);
1759

    
1760
#if USE_THREADS
1761
        gdk_threads_leave();
1762
#endif
1763

    
1764
        return TRUE;
1765
}
1766

    
1767
static void remote_command_exec(void)
1768
{
1769
        MainWindow *mainwin;
1770

    
1771
        mainwin = main_window_get();
1772

    
1773
        if (prefs_common.open_inbox_on_startup) {
1774
                FolderItem *item;
1775
                PrefsAccount *ac;
1776

    
1777
                ac = account_get_default();
1778
                if (!ac)
1779
                        ac = cur_account;
1780
                item = ac && ac->inbox
1781
                        ? folder_find_item_from_identifier(ac->inbox)
1782
                        : folder_get_default_inbox();
1783
                folderview_select(mainwin->folderview, item);
1784
        }
1785

    
1786
        if (!gtkut_window_modal_exist()) {
1787
                if (cmd.compose)
1788
                        open_compose_new(cmd.compose_mailto, cmd.attach_files);
1789

    
1790
                if (cmd.open_msg)
1791
                        open_message(cmd.open_msg);
1792

    
1793
                if (cmd.receive_all)
1794
                        inc_all_account_mail(mainwin, FALSE);
1795
                else if (prefs_common.chk_on_startup)
1796
                        inc_all_account_mail(mainwin, TRUE);
1797
                else if (cmd.receive)
1798
                        inc_mail(mainwin);
1799

    
1800
                if (cmd.send)
1801
                        send_queue();
1802
        }
1803

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

    
1826
#if !defined(G_OS_WIN32) && !defined(__APPLE__)
1827
static void migrate_old_config(void)
1828
{
1829
        GDir *dir;
1830
        const gchar *dir_name;
1831
        GPatternSpec *pspec;
1832

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

    
1839
        debug_print("Migrating old configuration...\n");
1840

    
1841
#define COPY_FILE(rcfile)                                                \
1842
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile)) {        \
1843
                conv_copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile,        \
1844
                               RC_DIR G_DIR_SEPARATOR_S rcfile,                \
1845
                               conv_get_locale_charset_str());                \
1846
        }
1847

    
1848
        COPY_FILE(ACCOUNT_RC);
1849
        COPY_FILE(ACTIONS_RC);
1850
        COPY_FILE(COMMON_RC);
1851
        COPY_FILE(CUSTOM_HEADER_RC);
1852
        COPY_FILE(DISPLAY_HEADER_RC);
1853
        COPY_FILE(FILTER_HEADER_RC);
1854
        COPY_FILE(COMMAND_HISTORY);
1855

    
1856
#undef COPY_FILE
1857

    
1858
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST))
1859
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST,
1860
                          RC_DIR G_DIR_SEPARATOR_S FILTER_LIST, FALSE);
1861
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST))
1862
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST,
1863
                          RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST, FALSE);
1864
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types"))
1865
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types",
1866
                          RC_DIR G_DIR_SEPARATOR_S "mime.types", FALSE);
1867

    
1868
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR))
1869
                conv_copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1870
                              RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1871
                              conv_get_locale_charset_str());
1872
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR))
1873
                copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR,
1874
                         RC_DIR G_DIR_SEPARATOR_S UIDL_DIR);
1875

    
1876
        if (!is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S ADDRESSBOOK_INDEX_FILE))
1877
                return;
1878

    
1879
        if ((dir = g_dir_open(OLD_RC_DIR, 0, NULL)) == NULL) {
1880
                g_warning("failed to open directory: %s\n", OLD_RC_DIR);
1881
                return;
1882
        }
1883

    
1884
        pspec = g_pattern_spec_new("addrbook-*.xml");
1885

    
1886
        while ((dir_name = g_dir_read_name(dir)) != NULL) {
1887
                if (g_pattern_match_string(pspec, dir_name)) {
1888
                        gchar *old_file;
1889
                        gchar *new_file;
1890

    
1891
                        old_file = g_strconcat(OLD_RC_DIR G_DIR_SEPARATOR_S,
1892
                                               dir_name, NULL);
1893
                        new_file = g_strconcat(RC_DIR G_DIR_SEPARATOR_S,
1894
                                               dir_name, NULL);
1895
                        copy_file(old_file, new_file, FALSE);
1896
                        g_free(new_file);
1897
                        g_free(old_file);
1898
                }
1899
        }
1900

    
1901
        g_pattern_spec_free(pspec);
1902
        g_dir_close(dir);
1903
}
1904
#endif /* !G_OS_WIN32 && !__APPLE__ */
1905

    
1906
static void open_compose_new(const gchar *address, GPtrArray *attach_files)
1907
{
1908
        gchar *utf8addr = NULL;
1909
#ifdef G_OS_WIN32
1910
        GPtrArray *utf8files = NULL;
1911
#endif
1912

    
1913
        if (gtkut_window_modal_exist())
1914
                return;
1915

    
1916
        if (address) {
1917
                utf8addr = g_locale_to_utf8(address, -1, NULL, NULL, NULL);
1918
                if (utf8addr)
1919
                        g_strstrip(utf8addr);
1920
                debug_print("open compose: %s\n", utf8addr ? utf8addr : "");
1921
        }
1922

    
1923
#ifdef G_OS_WIN32
1924
        if (attach_files) {
1925
                gint i;
1926
                gchar *file, *utf8file;
1927

    
1928
                utf8files = g_ptr_array_new();
1929
                for (i = 0; i < attach_files->len; i++) {
1930
                        file = g_ptr_array_index(attach_files, i);
1931
                        utf8file = g_locale_to_utf8(file, -1, NULL, NULL, NULL);
1932
                        if (utf8file)
1933
                                g_ptr_array_add(utf8files, utf8file);
1934
                }
1935
        }
1936

    
1937
        compose_new(NULL, NULL, utf8addr, utf8files);
1938
        if (utf8files) {
1939
                ptr_array_free_strings(utf8files);
1940
                g_ptr_array_free(utf8files, TRUE);
1941
        }
1942
#else
1943
        compose_new(NULL, NULL, utf8addr, attach_files);
1944
#endif
1945

    
1946
        g_free(utf8addr);
1947
}
1948

    
1949
static void open_message_file(const gchar *file)
1950
{
1951
        MsgInfo *msginfo;
1952
        MsgFlags flags = {0};
1953
        MessageView *msgview;
1954

    
1955
        g_return_if_fail(file != NULL);
1956

    
1957
        debug_print("open message file: %s\n", file);
1958

    
1959
        if (!is_file_exist(file) || get_file_size(file) <= 0) {
1960
                debug_print("file not found: %s\n", file);
1961
                return;
1962
        }
1963

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

    
1974
static void open_message(const gchar *path)
1975
{
1976
        gchar *fid;
1977
        gchar *msg;
1978
        gint num;
1979
        FolderItem *item;
1980
        MsgInfo *msginfo;
1981
        MessageView *msgview;
1982
        gchar *file;
1983

    
1984
        g_return_if_fail(path != NULL);
1985

    
1986
        if (gtkut_window_modal_exist())
1987
                return;
1988

    
1989
        debug_print("open message: %s\n", path);
1990

    
1991
        if (!strncmp(path, "file:", 5)) {
1992
                file = g_filename_from_uri(path, NULL, NULL);
1993
                open_message_file(file);
1994
                g_free(file);
1995
                return;
1996
        } else if (g_path_is_absolute(path)) {
1997
                open_message_file(path);
1998
                return;
1999
        }
2000

    
2001
        /* relative path, or folder identifier */
2002

    
2003
        fid = g_path_get_dirname(path);
2004
        msg = g_path_get_basename(path);
2005
        num = to_number(msg);
2006
        item = folder_find_item_from_identifier(fid);
2007

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

    
2022
        g_free(msg);
2023
        g_free(fid);
2024

    
2025
        /* relative path */
2026

    
2027
        file = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, path, NULL);
2028
        open_message_file(file);
2029
        g_free(file);
2030
}
2031

    
2032
static void send_queue(void)
2033
{
2034
        GList *list;
2035

    
2036
        if (gtkut_window_modal_exist())
2037
                return;
2038
        if (!main_window_toggle_online_if_offline(main_window_get()))
2039
                return;
2040

    
2041
        for (list = folder_get_list(); list != NULL; list = list->next) {
2042
                Folder *folder = list->data;
2043

    
2044
                if (folder->queue) {
2045
                        gint ret;
2046

    
2047
                        ret = send_message_queue_all(folder->queue,
2048
                                                     prefs_common.savemsg,
2049
                                                     prefs_common.filter_sent);
2050
                        statusbar_pop_all();
2051
                        if (ret > 0)
2052
                                folder_item_scan(folder->queue);
2053
                }
2054
        }
2055

    
2056
        folderview_update_all_updated(TRUE);
2057
        main_window_set_menu_sensitive(main_window_get());
2058
        main_window_set_toolbar_sensitive(main_window_get());
2059
}