Statistics
| Revision:

root / src / main.c @ 3317

History | View | Annotate | Download (48.6 KB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2013 Hiroyuki Yamamoto
4
 *
5
 * This program is free software; you can redistribute it and/or modify
6
 * it under the terms of the GNU General Public License as published by
7
 * the Free Software Foundation; either version 2 of the License, or
8
 * (at your option) any later version.
9
 *
10
 * This program is distributed in the hope that it will be useful,
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
 * GNU General Public License for more details.
14
 *
15
 * You should have received a copy of the GNU General Public License
16
 * along with this program; if not, write to the Free Software
17
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18
 */
19

    
20
#ifdef HAVE_CONFIG_H
21
#  include "config.h"
22
#endif
23

    
24
#include "defs.h"
25

    
26
#include <glib.h>
27
#include <glib/gi18n.h>
28
#include <gtk/gtkmain.h>
29
#include <gtk/gtkrc.h>
30
#include <gtk/gtkstock.h>
31
#include <gtk/gtkaccelmap.h>
32

    
33
#include <stdio.h>
34
#include <stdlib.h>
35
#include <string.h>
36
#include <ctype.h>
37
#include <unistd.h>
38
#include <time.h>
39
#include <sys/stat.h>
40
#include <sys/types.h>
41
#ifdef G_OS_UNIX
42
#  include <signal.h>
43
#endif
44

    
45
#if HAVE_LOCALE_H
46
#  include <locale.h>
47
#endif
48

    
49
#if USE_GPGME
50
#  include <gpgme.h>
51
#endif
52

    
53
#include "main.h"
54
#include "mainwindow.h"
55
#include "folderview.h"
56
#include "summaryview.h"
57
#include "prefs_common.h"
58
#include "prefs_account.h"
59
#include "prefs_actions.h"
60
#include "prefs_display_header.h"
61
#include "account.h"
62
#include "account_dialog.h"
63
#include "procmsg.h"
64
#include "procheader.h"
65
#include "filter.h"
66
#include "send_message.h"
67
#include "inc.h"
68
#include "manage_window.h"
69
#include "alertpanel.h"
70
#include "inputdialog.h"
71
#include "statusbar.h"
72
#include "addressbook.h"
73
#include "addrindex.h"
74
#include "compose.h"
75
#include "logwindow.h"
76
#include "folder.h"
77
#include "setup.h"
78
#include "sylmain.h"
79
#include "utils.h"
80
#include "gtkutils.h"
81
#include "socket.h"
82
#include "stock_pixmap.h"
83
#include "trayicon.h"
84
#include "notificationwindow.h"
85
#include "plugin.h"
86
#include "plugin_manager.h"
87
#include "foldersel.h"
88
#include "update_check.h"
89
#include "colorlabel.h"
90

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

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

    
106
#include "version.h"
107

    
108
gchar *prog_version;
109

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

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

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

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

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

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

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

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

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

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

    
180
static void remote_command_exec                (void);
181

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

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

    
190
static void send_queue                        (void);
191

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

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

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

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

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

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

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

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

    
250
        syl_app = syl_app_create();
251

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

    
256
        parse_gtkrc_files();
257
        setup_rc_dir();
258

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

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

    
273
        CHDIR_EXIT_IF_FAIL(get_home_dir(), 1);
274

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

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

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

    
292
        gtkut_stock_button_set_set_reverse(!prefs_common.comply_gnome_hig);
293

    
294
        check_gpg();
295

    
296
        sock_set_io_timeout(prefs_common.io_timeout_secs);
297

    
298
        gtkut_widget_init();
299

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

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

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

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

    
341
        set_log_handlers(TRUE);
342

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

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

    
356
        account_set_menu();
357
        main_window_reflect_prefs_all();
358

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

    
365
        addressbook_read_file();
366

    
367
        register_system_events();
368

    
369
        inc_autocheck_timer_init(mainwin);
370

    
371
        plugin_init();
372

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

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

    
380
        remote_command_exec();
381

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

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

    
392
        return 0;
393
}
394

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

    
401
        if (init_console_done)
402
                return;
403

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

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

    
420
        init_console_done = TRUE;
421
#endif
422
}
423

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

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

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

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

    
444
        gchar *file;
445

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
836
        syl_setup_rc_dir();
837
}
838

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

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

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

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

    
894
        mainwin = main_window_get();
895

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

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

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

    
923
        inc_autocheck_timer_remove();
924

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

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

    
936
        syl_plugin_unload_all();
937

    
938
        trayicon_destroy(mainwin->tray_icon);
939

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

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

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

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

    
967
        cleanup_console();
968

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

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

    
975
        exit(0);
976
}
977

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

    
1146
#ifdef G_OS_WIN32
1147

    
1148
#if !GTK_CHECK_VERSION(2, 14, 0)
1149
static UINT taskbar_created_msg;
1150
#endif
1151

    
1152
static BOOL WINAPI
1153
ctrl_handler(DWORD dwctrltype)
1154
{
1155
        log_print("ctrl_handler: received %d\n", dwctrltype);
1156
        app_will_exit(TRUE);
1157

    
1158
        return TRUE;
1159
}
1160

    
1161
static LRESULT CALLBACK
1162
wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
1163
{
1164
        switch (message) {
1165
        case WM_POWERBROADCAST:
1166
                debug_print("WM_POWERBROADCAST received: wparam = %d\n",
1167
                            wparam);
1168
                if (wparam == PBT_APMSUSPEND || wparam == PBT_APMSTANDBY) {
1169
                        debug_print("suspend now\n");
1170
                        inc_autocheck_timer_remove();
1171
                } else if (wparam == PBT_APMRESUMESUSPEND ||
1172
                           wparam == PBT_APMRESUMESTANDBY) {
1173
                        debug_print("resume now\n");
1174
                        inc_autocheck_timer_set();
1175
                }
1176
                break;
1177
        case WM_ENDSESSION:
1178
                if (wparam == 1) {
1179
                        log_print("WM_ENDSESSION received: system is quitting\n");
1180
                        app_will_exit(TRUE);
1181
                }
1182
                break;
1183
        default:
1184
#if !GTK_CHECK_VERSION(2, 14, 0)
1185
                if (message == taskbar_created_msg) {
1186
                        debug_print("TaskbarCreated received\n");
1187

    
1188
                        /* recreate tray icon */
1189
                        {
1190
                                MainWindow *mainwin = main_window_get();
1191
                                if (mainwin && mainwin->tray_icon &&
1192
                                    gtk_status_icon_get_visible(mainwin->tray_icon->status_icon)) {
1193
                                        trayicon_hide(mainwin->tray_icon);
1194
                                        trayicon_show(mainwin->tray_icon);
1195
                                }
1196
                        }
1197
                }
1198
#endif
1199
                break;
1200
        }
1201

    
1202
        return DefWindowProc(hwnd, message, wparam, lparam);
1203
}
1204

    
1205
static void register_system_events(void)
1206
{
1207
        WNDCLASS wclass;
1208
        static HWND hwnd = NULL;
1209
        static BOOL ctrl_handler_set = FALSE;
1210
        ATOM klass;
1211
        HINSTANCE hmodule = GetModuleHandle(NULL);
1212

    
1213
        if (init_console_done && !ctrl_handler_set) {
1214
                debug_print("register_system_events(): SetConsoleCtrlHandler\n");
1215
                ctrl_handler_set = SetConsoleCtrlHandler(ctrl_handler, TRUE);
1216
                if (!ctrl_handler_set)
1217
                        g_warning("SetConsoleCtrlHandler() failed\n");
1218
        }
1219

    
1220
        if (hwnd)
1221
                return;
1222

    
1223
#if !GTK_CHECK_VERSION(2, 14, 0)
1224
        taskbar_created_msg = RegisterWindowMessage("TaskbarCreated");
1225
#endif
1226

    
1227
        debug_print("register_system_events(): RegisterClass\n");
1228

    
1229
        memset(&wclass, 0, sizeof(WNDCLASS));
1230
        wclass.lpszClassName = "sylpheed-observer";
1231
        wclass.lpfnWndProc   = wndproc;
1232
        wclass.hInstance     = hmodule;
1233

    
1234
        klass = RegisterClass(&wclass);
1235
        if (!klass)
1236
                return;
1237

    
1238
        hwnd = CreateWindow(MAKEINTRESOURCE(klass), NULL, WS_POPUP,
1239
                            0, 0, 1, 1, NULL, NULL, hmodule, NULL);
1240
        if (!hwnd)
1241
                UnregisterClass(MAKEINTRESOURCE(klass), hmodule);
1242
}
1243
#else /* G_OS_WIN32 */
1244
static void sig_handler(gint signum)
1245
{
1246
        debug_print("signal %d received\n", signum);
1247

    
1248
        switch (signum) {
1249
        case SIGHUP:
1250
        case SIGINT:
1251
        case SIGTERM:
1252
        case SIGQUIT:
1253
                app_will_exit(TRUE);
1254
                break;
1255
        default:
1256
                break;
1257
        }
1258
}
1259

    
1260
static void register_system_events(void)
1261
{
1262
        struct sigaction sa;
1263

    
1264
        memset(&sa, 0, sizeof(sa));
1265
        sa.sa_handler = sig_handler;
1266
        sa.sa_flags = SA_RESTART;
1267

    
1268
        sigemptyset(&sa.sa_mask);
1269
        sigaddset(&sa.sa_mask, SIGHUP);
1270
        sigaddset(&sa.sa_mask, SIGINT);
1271
        sigaddset(&sa.sa_mask, SIGTERM);
1272
        sigaddset(&sa.sa_mask, SIGQUIT);
1273
        sigaddset(&sa.sa_mask, SIGPIPE);
1274

    
1275
        sigaction(SIGHUP, &sa, NULL);
1276
        sigaction(SIGINT, &sa, NULL);
1277
        sigaction(SIGTERM, &sa, NULL);
1278
        sigaction(SIGQUIT, &sa, NULL);
1279
        sigaction(SIGPIPE, &sa, NULL);
1280
}
1281
#endif
1282

    
1283
#define ADD_SYM(sym)        syl_plugin_add_symbol(#sym, sym)
1284

    
1285
static void plugin_init(void)
1286
{
1287
        MainWindow *mainwin;
1288
        gchar *path;
1289

    
1290
        mainwin = main_window_get();
1291

    
1292
        STATUSBAR_PUSH(mainwin, _("Loading plug-ins..."));
1293

    
1294
        if (syl_plugin_init_lib() != 0) {
1295
                STATUSBAR_POP(mainwin);
1296
                return;
1297
        }
1298

    
1299
        if (cmd.safe_mode) {
1300
                debug_print("plugin_init: safe mode enabled, skipping plug-in loading.\n");
1301
                STATUSBAR_POP(mainwin);
1302
                return;
1303
        }
1304

    
1305
        ADD_SYM(prog_version);
1306
        ADD_SYM(app_will_exit);
1307

    
1308
        ADD_SYM(main_window_lock);
1309
        ADD_SYM(main_window_unlock);
1310
        ADD_SYM(main_window_get);
1311
        ADD_SYM(main_window_popup);
1312

    
1313
        syl_plugin_add_symbol("main_window_menu_factory",
1314
                              mainwin->menu_factory);
1315
        syl_plugin_add_symbol("main_window_statusbar", mainwin->statusbar);
1316

    
1317
        ADD_SYM(folderview_get);
1318
        ADD_SYM(folderview_add_sub_widget);
1319
        ADD_SYM(folderview_select);
1320
        ADD_SYM(folderview_unselect);
1321
        ADD_SYM(folderview_select_next_unread);
1322
        ADD_SYM(folderview_get_selected_item);
1323
        ADD_SYM(folderview_check_new);
1324
        ADD_SYM(folderview_check_new_item);
1325
        ADD_SYM(folderview_check_new_all);
1326
        ADD_SYM(folderview_update_item);
1327
        ADD_SYM(folderview_update_item_foreach);
1328
        ADD_SYM(folderview_update_all_updated);
1329
        ADD_SYM(folderview_check_new_selected);
1330

    
1331
        syl_plugin_add_symbol("folderview_mail_popup_factory",
1332
                              mainwin->folderview->mail_factory);
1333
        syl_plugin_add_symbol("folderview_imap_popup_factory",
1334
                              mainwin->folderview->imap_factory);
1335
        syl_plugin_add_symbol("folderview_news_popup_factory",
1336
                              mainwin->folderview->news_factory);
1337

    
1338
        syl_plugin_add_symbol("summaryview", mainwin->summaryview);
1339
        syl_plugin_add_symbol("summaryview_popup_factory",
1340
                              mainwin->summaryview->popupfactory);
1341

    
1342
        ADD_SYM(summary_select_by_msgnum);
1343
        ADD_SYM(summary_select_by_msginfo);
1344
        ADD_SYM(summary_lock);
1345
        ADD_SYM(summary_unlock);
1346
        ADD_SYM(summary_is_locked);
1347
        ADD_SYM(summary_is_read_locked);
1348
        ADD_SYM(summary_write_lock);
1349
        ADD_SYM(summary_write_unlock);
1350
        ADD_SYM(summary_is_write_locked);
1351
        ADD_SYM(summary_get_current_folder);
1352
        ADD_SYM(summary_get_selection_type);
1353
        ADD_SYM(summary_get_selected_msg_list);
1354
        ADD_SYM(summary_get_msg_list);
1355
        ADD_SYM(summary_show_queued_msgs);
1356
        ADD_SYM(summary_redisplay_msg);
1357
        ADD_SYM(summary_open_msg);
1358
        ADD_SYM(summary_view_source);
1359
        ADD_SYM(summary_reedit);
1360
        ADD_SYM(summary_update_selected_rows);
1361
        ADD_SYM(summary_update_by_msgnum);
1362

    
1363
        ADD_SYM(messageview_create_with_new_window);
1364
        ADD_SYM(messageview_show);
1365

    
1366
        ADD_SYM(compose_new);
1367
        ADD_SYM(compose_entry_set);
1368
        ADD_SYM(compose_entry_append);
1369
        ADD_SYM(compose_entry_get_text);
1370
        ADD_SYM(compose_lock);
1371
        ADD_SYM(compose_unlock);
1372

    
1373
        ADD_SYM(foldersel_folder_sel);
1374
        ADD_SYM(foldersel_folder_sel_full);
1375

    
1376
        ADD_SYM(input_dialog);
1377
        ADD_SYM(input_dialog_with_invisible);
1378

    
1379
        ADD_SYM(manage_window_set_transient);
1380
        ADD_SYM(manage_window_signals_connect);
1381
        ADD_SYM(manage_window_get_focus_window);
1382

    
1383
        ADD_SYM(inc_mail);
1384
        ADD_SYM(inc_is_active);
1385
        ADD_SYM(inc_lock);
1386
        ADD_SYM(inc_unlock);
1387

    
1388
#if USE_UPDATE_CHECK
1389
        ADD_SYM(update_check);
1390
        ADD_SYM(update_check_set_check_url);
1391
        ADD_SYM(update_check_get_check_url);
1392
        ADD_SYM(update_check_set_download_url);
1393
        ADD_SYM(update_check_get_download_url);
1394
        ADD_SYM(update_check_set_jump_url);
1395
        ADD_SYM(update_check_get_jump_url);
1396
#ifdef USE_UPDATE_CHECK_PLUGIN
1397
        ADD_SYM(update_check_set_check_plugin_url);
1398
        ADD_SYM(update_check_get_check_plugin_url);
1399
        ADD_SYM(update_check_set_jump_plugin_url);
1400
        ADD_SYM(update_check_get_jump_plugin_url);
1401
#endif /* USE_UPDATE_CHECK_PLUGIN */
1402
#endif
1403

    
1404
        ADD_SYM(alertpanel_full);
1405
        ADD_SYM(alertpanel);
1406
        ADD_SYM(alertpanel_message);
1407
        ADD_SYM(alertpanel_message_with_disable);
1408

    
1409
        ADD_SYM(send_message);
1410
        ADD_SYM(send_message_queue_all);
1411
        ADD_SYM(send_message_set_reply_flag);
1412
        ADD_SYM(send_message_set_forward_flags);
1413

    
1414
        ADD_SYM(notification_window_open);
1415
        ADD_SYM(notification_window_set_message);
1416
        ADD_SYM(notification_window_close);
1417

    
1418
        syl_plugin_signal_connect("plugin-load", G_CALLBACK(load_cb), NULL);
1419

    
1420
        /* loading plug-ins from user plug-in directory */
1421
        path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, PLUGIN_DIR, NULL);
1422
        syl_plugin_load_all(path);
1423
        g_free(path);
1424

    
1425
        /* loading plug-ins from system plug-in directory */
1426
#ifdef G_OS_WIN32
1427
        path = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, PLUGIN_DIR,
1428
                           NULL);
1429
        syl_plugin_load_all(path);
1430
        g_free(path);
1431
#elif defined(__APPLE__)
1432
        path = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S,
1433
                           "Contents" G_DIR_SEPARATOR_S
1434
                           "Resources" G_DIR_SEPARATOR_S
1435
                           "lib" G_DIR_SEPARATOR_S
1436
                           "sylpheed" G_DIR_SEPARATOR_S
1437
                           PLUGIN_DIR,
1438
                           NULL);
1439
        syl_plugin_load_all(path);
1440
        g_free(path);
1441
#else
1442
        syl_plugin_load_all(PLUGINDIR);
1443
#endif
1444

    
1445
        STATUSBAR_POP(mainwin);
1446
}
1447

    
1448
static gchar *get_socket_name(void)
1449
{
1450
        static gchar *filename = NULL;
1451

    
1452
        if (filename == NULL) {
1453
                filename = g_strdup_printf("%s%c%s-%d",
1454
                                           g_get_tmp_dir(), G_DIR_SEPARATOR,
1455
                                           instance_id ? instance_id : "sylpheed",
1456
#if HAVE_GETUID
1457
                                           getuid());
1458
#else
1459
                                           0);
1460
#endif
1461
        }
1462

    
1463
        return filename;
1464
}
1465

    
1466
static gint prohibit_duplicate_launch(void)
1467
{
1468
        gint sock;
1469

    
1470
#ifdef G_OS_WIN32
1471
        HANDLE hmutex;
1472
        const gchar *ins_id = instance_id ? instance_id : "Sylpheed";
1473
        gushort port = cmd.ipcport ? cmd.ipcport : REMOTE_CMD_PORT;
1474

    
1475
        debug_print("prohibit_duplicate_launch: checking mutex: %s\n", ins_id);
1476
        hmutex = CreateMutexA(NULL, FALSE, ins_id);
1477
        if (!hmutex) {
1478
                g_warning("cannot create Mutex: %s\n", ins_id);
1479
                return -1;
1480
        }
1481
        if (GetLastError() != ERROR_ALREADY_EXISTS) {
1482
                debug_print("prohibit_duplicate_launch: creating socket: port %d\n", port);
1483
                sock = fd_open_inet(port);
1484
                if (sock < 0)
1485
                        return 0;
1486
                return sock;
1487
        }
1488

    
1489
        debug_print("prohibit_duplicate_launch: connecting to socket: port %d\n", port);
1490
        sock = fd_connect_inet(port);
1491
        if (sock < 0)
1492
                return -1;
1493
#else
1494
        gchar *path;
1495

    
1496
        path = get_socket_name();
1497
        debug_print("prohibit_duplicate_launch: checking socket: %s\n", path);
1498
        sock = fd_connect_unix(path);
1499
        if (sock < 0) {
1500
                debug_print("prohibit_duplicate_launch: creating socket: %s\n", path);
1501
                g_unlink(path);
1502
                return fd_open_unix(path);
1503
        }
1504
#endif
1505

    
1506
        /* remote command mode */
1507

    
1508
        debug_print(_("another Sylpheed is already running.\n"));
1509

    
1510
        if (cmd.receive_all)
1511
                fd_write_all(sock, "receive_all\n", 12);
1512
        else if (cmd.receive)
1513
                fd_write_all(sock, "receive\n", 8);
1514
        else if (cmd.compose && cmd.attach_files) {
1515
                gchar *str, *compose_str;
1516
                gint i;
1517

    
1518
                if (cmd.compose_mailto)
1519
                        compose_str = g_strdup_printf("compose_attach %s\n",
1520
                                                      cmd.compose_mailto);
1521
                else
1522
                        compose_str = g_strdup("compose_attach\n");
1523

    
1524
                fd_write_all(sock, compose_str, strlen(compose_str));
1525
                g_free(compose_str);
1526

    
1527
                for (i = 0; i < cmd.attach_files->len; i++) {
1528
                        str = g_ptr_array_index(cmd.attach_files, i);
1529
                        fd_write_all(sock, str, strlen(str));
1530
                        fd_write_all(sock, "\n", 1);
1531
                }
1532

    
1533
                fd_write_all(sock, ".\n", 2);
1534
        } else if (cmd.compose) {
1535
                gchar *compose_str;
1536

    
1537
                if (cmd.compose_mailto)
1538
                        compose_str = g_strdup_printf
1539
                                ("compose %s\n", cmd.compose_mailto);
1540
                else
1541
                        compose_str = g_strdup("compose\n");
1542

    
1543
                fd_write_all(sock, compose_str, strlen(compose_str));
1544
                g_free(compose_str);
1545
        } else if (cmd.send) {
1546
                fd_write_all(sock, "send\n", 5);
1547
        } else if (cmd.status || cmd.status_full) {
1548
                gchar buf[BUFFSIZE];
1549
                gint i;
1550
                const gchar *command;
1551
                GPtrArray *folders;
1552
                gchar *folder;
1553

    
1554
                command = cmd.status_full ? "status-full\n" : "status\n";
1555
                folders = cmd.status_full ? cmd.status_full_folders :
1556
                        cmd.status_folders;
1557

    
1558
                fd_write_all(sock, command, strlen(command));
1559
                for (i = 0; folders && i < folders->len; ++i) {
1560
                        folder = g_ptr_array_index(folders, i);
1561
                        fd_write_all(sock, folder, strlen(folder));
1562
                        fd_write_all(sock, "\n", 1);
1563
                }
1564
                fd_write_all(sock, ".\n", 2);
1565
                for (;;) {
1566
                        if (fd_gets(sock, buf, sizeof(buf)) <= 0) break;
1567
                        if (!strncmp(buf, ".\n", 2)) break;
1568
                        fputs(buf, stdout);
1569
                }
1570
        } else if (cmd.open_msg) {
1571
                gchar *str;
1572

    
1573
                str = g_strdup_printf("open %s\n", cmd.open_msg);
1574
                fd_write_all(sock, str, strlen(str));
1575
                g_free(str);
1576
        } else if (cmd.exit) {
1577
                fd_write_all(sock, "exit\n", 5);
1578
        } else {
1579
#ifdef G_OS_WIN32
1580
                HWND hwnd;
1581

    
1582
                fd_write_all(sock, "popup\n", 6);
1583
                if (fd_read(sock, (gchar *)&hwnd, sizeof(hwnd)) == sizeof(hwnd))
1584
                        SetForegroundWindow(hwnd);
1585
#else
1586
                fd_write_all(sock, "popup\n", 6);
1587
#endif
1588
        }
1589

    
1590
        fd_close(sock);
1591
        return -1;
1592
}
1593

    
1594
static gint lock_socket_remove(void)
1595
{
1596
#ifndef G_OS_WIN32
1597
        gchar *filename;
1598
#endif
1599

    
1600
        if (lock_socket < 0) return -1;
1601

    
1602
        if (lock_socket_tag > 0)
1603
                g_source_remove(lock_socket_tag);
1604
        if (lock_ch) {
1605
                g_io_channel_shutdown(lock_ch, FALSE, NULL);
1606
                g_io_channel_unref(lock_ch);
1607
                lock_ch = NULL;
1608
        }
1609

    
1610
#ifndef G_OS_WIN32
1611
        filename = get_socket_name();
1612
        debug_print("lock_socket_remove: removing socket: %s\n", filename);
1613
        g_unlink(filename);
1614
#endif
1615

    
1616
        return 0;
1617
}
1618

    
1619
static GPtrArray *get_folder_item_list(gint sock)
1620
{
1621
        gchar buf[BUFFSIZE];
1622
        FolderItem *item;
1623
        GPtrArray *folders = NULL;
1624

    
1625
        for (;;) {
1626
                if (fd_gets(sock, buf, sizeof(buf)) <= 0) break;
1627
                if (!strncmp(buf, ".\n", 2)) break;
1628
                strretchomp(buf);
1629
                if (!folders) folders = g_ptr_array_new();
1630
                item = folder_find_item_from_identifier(buf);
1631
                if (item)
1632
                        g_ptr_array_add(folders, item);
1633
                else
1634
                        g_warning("no such folder: %s\n", buf);
1635
        }
1636

    
1637
        return folders;
1638
}
1639

    
1640
static gboolean lock_socket_input_cb(GIOChannel *source, GIOCondition condition,
1641
                                     gpointer data)
1642
{
1643
        MainWindow *mainwin = (MainWindow *)data;
1644
        gint fd, sock;
1645
        gchar buf[BUFFSIZE];
1646

    
1647
#if USE_THREADS
1648
        gdk_threads_enter();
1649
#endif
1650

    
1651
        fd = g_io_channel_unix_get_fd(source);
1652
        sock = fd_accept(fd);
1653
        if (fd_gets(sock, buf, sizeof(buf)) <= 0) {
1654
                fd_close(sock);
1655
#if USE_THREADS
1656
                gdk_threads_leave();
1657
#endif
1658
                return TRUE;
1659
        }
1660

    
1661
        if (!strncmp(buf, "popup", 5)) {
1662
#ifdef G_OS_WIN32
1663
                HWND hwnd;
1664

    
1665
                hwnd = (HWND)gdk_win32_drawable_get_handle
1666
                        (GDK_DRAWABLE(mainwin->window->window));
1667
                fd_write(sock, (gchar *)&hwnd, sizeof(hwnd));
1668
                if (mainwin->window_hidden)
1669
                        main_window_popup(mainwin);
1670
#else
1671
                main_window_popup(mainwin);
1672
#endif
1673
        } else if (!strncmp(buf, "receive_all", 11)) {
1674
                main_window_popup(mainwin);
1675
                if (!gtkut_window_modal_exist())
1676
                        inc_all_account_mail(mainwin, FALSE);
1677
        } else if (!strncmp(buf, "receive", 7)) {
1678
                main_window_popup(mainwin);
1679
                if (!gtkut_window_modal_exist())
1680
                        inc_mail(mainwin);
1681
        } else if (!strncmp(buf, "compose_attach", 14)) {
1682
                GPtrArray *files;
1683
                gchar *mailto;
1684

    
1685
                mailto = g_strdup(buf + strlen("compose_attach") + 1);
1686
                files = g_ptr_array_new();
1687
                while (fd_gets(sock, buf, sizeof(buf)) > 0) {
1688
                        if (buf[0] == '.' && buf[1] == '\n') break;
1689
                        strretchomp(buf);
1690
                        g_ptr_array_add(files, g_strdup(buf));
1691
                }
1692
                open_compose_new(mailto, files);
1693
                ptr_array_free_strings(files);
1694
                g_ptr_array_free(files, TRUE);
1695
                g_free(mailto);
1696
        } else if (!strncmp(buf, "compose", 7)) {
1697
                open_compose_new(buf + strlen("compose") + 1, NULL);
1698
        } else if (!strncmp(buf, "send", 4)) {
1699
                send_queue();
1700
        } else if (!strncmp(buf, "status-full", 11) ||
1701
                   !strncmp(buf, "status", 6)) {
1702
                gchar *status;
1703
                GPtrArray *folders;
1704

    
1705
                folders = get_folder_item_list(sock);
1706
                status = folder_get_status
1707
                        (folders, !strncmp(buf, "status-full", 11));
1708
                fd_write_all(sock, status, strlen(status));
1709
                fd_write_all(sock, ".\n", 2);
1710
                g_free(status);
1711
                if (folders) g_ptr_array_free(folders, TRUE);
1712
        } else if (!strncmp(buf, "open", 4)) {
1713
                strretchomp(buf);
1714
                if (strlen(buf) < 6 || buf[4] != ' ') {
1715
                        fd_close(sock);
1716
#if USE_THREADS
1717
                        gdk_threads_leave();
1718
#endif
1719
                        return TRUE;
1720
                }
1721
                open_message(buf + 5);
1722
        } else if (!strncmp(buf, "exit", 4)) {
1723
                fd_close(sock);
1724
                app_will_exit(TRUE);
1725
        }
1726

    
1727
        fd_close(sock);
1728

    
1729
#if USE_THREADS
1730
        gdk_threads_leave();
1731
#endif
1732

    
1733
        return TRUE;
1734
}
1735

    
1736
static void remote_command_exec(void)
1737
{
1738
        MainWindow *mainwin;
1739

    
1740
        mainwin = main_window_get();
1741

    
1742
        if (prefs_common.open_inbox_on_startup) {
1743
                FolderItem *item;
1744
                PrefsAccount *ac;
1745

    
1746
                ac = account_get_default();
1747
                if (!ac)
1748
                        ac = cur_account;
1749
                item = ac && ac->inbox
1750
                        ? folder_find_item_from_identifier(ac->inbox)
1751
                        : folder_get_default_inbox();
1752
                folderview_select(mainwin->folderview, item);
1753
        }
1754

    
1755
        if (!gtkut_window_modal_exist()) {
1756
                if (cmd.compose)
1757
                        open_compose_new(cmd.compose_mailto, cmd.attach_files);
1758

    
1759
                if (cmd.open_msg)
1760
                        open_message(cmd.open_msg);
1761

    
1762
                if (cmd.receive_all)
1763
                        inc_all_account_mail(mainwin, FALSE);
1764
                else if (prefs_common.chk_on_startup)
1765
                        inc_all_account_mail(mainwin, TRUE);
1766
                else if (cmd.receive)
1767
                        inc_mail(mainwin);
1768

    
1769
                if (cmd.send)
1770
                        send_queue();
1771
        }
1772

    
1773
        if (cmd.attach_files) {
1774
                ptr_array_free_strings(cmd.attach_files);
1775
                g_ptr_array_free(cmd.attach_files, TRUE);
1776
                cmd.attach_files = NULL;
1777
        }
1778
        if (cmd.status_folders) {
1779
                g_ptr_array_free(cmd.status_folders, TRUE);
1780
                cmd.status_folders = NULL;
1781
        }
1782
        if (cmd.status_full_folders) {
1783
                g_ptr_array_free(cmd.status_full_folders, TRUE);
1784
                cmd.status_full_folders = NULL;
1785
        }
1786
        if (cmd.open_msg) {
1787
                g_free(cmd.open_msg);
1788
                cmd.open_msg = NULL;
1789
        }
1790
        if (cmd.exit) {
1791
                app_will_exit(TRUE);
1792
        }
1793
}
1794

    
1795
#if !defined(G_OS_WIN32) && !defined(__APPLE__)
1796
static void migrate_old_config(void)
1797
{
1798
        GDir *dir;
1799
        const gchar *dir_name;
1800
        GPatternSpec *pspec;
1801

    
1802
        if (alertpanel(_("Migration of configuration"),
1803
                       _("The previous version of configuration found.\n"
1804
                         "Do you want to migrate it?"),
1805
                       GTK_STOCK_YES, GTK_STOCK_NO, NULL) != G_ALERTDEFAULT)
1806
                return;
1807

    
1808
        debug_print("Migrating old configuration...\n");
1809

    
1810
#define COPY_FILE(rcfile)                                                \
1811
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile)) {        \
1812
                conv_copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile,        \
1813
                               RC_DIR G_DIR_SEPARATOR_S rcfile,                \
1814
                               conv_get_locale_charset_str());                \
1815
        }
1816

    
1817
        COPY_FILE(ACCOUNT_RC);
1818
        COPY_FILE(ACTIONS_RC);
1819
        COPY_FILE(COMMON_RC);
1820
        COPY_FILE(CUSTOM_HEADER_RC);
1821
        COPY_FILE(DISPLAY_HEADER_RC);
1822
        COPY_FILE(FILTER_HEADER_RC);
1823
        COPY_FILE(COMMAND_HISTORY);
1824

    
1825
#undef COPY_FILE
1826

    
1827
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST))
1828
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST,
1829
                          RC_DIR G_DIR_SEPARATOR_S FILTER_LIST, FALSE);
1830
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST))
1831
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST,
1832
                          RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST, FALSE);
1833
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types"))
1834
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types",
1835
                          RC_DIR G_DIR_SEPARATOR_S "mime.types", FALSE);
1836

    
1837
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR))
1838
                conv_copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1839
                              RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1840
                              conv_get_locale_charset_str());
1841
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR))
1842
                copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR,
1843
                         RC_DIR G_DIR_SEPARATOR_S UIDL_DIR);
1844

    
1845
        if (!is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S ADDRESSBOOK_INDEX_FILE))
1846
                return;
1847

    
1848
        if ((dir = g_dir_open(OLD_RC_DIR, 0, NULL)) == NULL) {
1849
                g_warning("failed to open directory: %s\n", OLD_RC_DIR);
1850
                return;
1851
        }
1852

    
1853
        pspec = g_pattern_spec_new("addrbook-*.xml");
1854

    
1855
        while ((dir_name = g_dir_read_name(dir)) != NULL) {
1856
                if (g_pattern_match_string(pspec, dir_name)) {
1857
                        gchar *old_file;
1858
                        gchar *new_file;
1859

    
1860
                        old_file = g_strconcat(OLD_RC_DIR G_DIR_SEPARATOR_S,
1861
                                               dir_name, NULL);
1862
                        new_file = g_strconcat(RC_DIR G_DIR_SEPARATOR_S,
1863
                                               dir_name, NULL);
1864
                        copy_file(old_file, new_file, FALSE);
1865
                        g_free(new_file);
1866
                        g_free(old_file);
1867
                }
1868
        }
1869

    
1870
        g_pattern_spec_free(pspec);
1871
        g_dir_close(dir);
1872
}
1873
#endif /* !G_OS_WIN32 && !__APPLE__ */
1874

    
1875
static void open_compose_new(const gchar *address, GPtrArray *attach_files)
1876
{
1877
        gchar *utf8addr = NULL;
1878
#ifdef G_OS_WIN32
1879
        GPtrArray *utf8files = NULL;
1880
#endif
1881

    
1882
        if (gtkut_window_modal_exist())
1883
                return;
1884

    
1885
        if (address) {
1886
                utf8addr = g_locale_to_utf8(address, -1, NULL, NULL, NULL);
1887
                if (utf8addr)
1888
                        g_strstrip(utf8addr);
1889
                debug_print("open compose: %s\n", utf8addr ? utf8addr : "");
1890
        }
1891

    
1892
#ifdef G_OS_WIN32
1893
        if (attach_files) {
1894
                gint i;
1895
                gchar *file, *utf8file;
1896

    
1897
                utf8files = g_ptr_array_new();
1898
                for (i = 0; i < attach_files->len; i++) {
1899
                        file = g_ptr_array_index(attach_files, i);
1900
                        utf8file = g_locale_to_utf8(file, -1, NULL, NULL, NULL);
1901
                        if (utf8file)
1902
                                g_ptr_array_add(utf8files, utf8file);
1903
                }
1904
        }
1905

    
1906
        compose_new(NULL, NULL, utf8addr, utf8files);
1907
        if (utf8files) {
1908
                ptr_array_free_strings(utf8files);
1909
                g_ptr_array_free(utf8files, TRUE);
1910
        }
1911
#else
1912
        compose_new(NULL, NULL, utf8addr, attach_files);
1913
#endif
1914

    
1915
        g_free(utf8addr);
1916
}
1917

    
1918
static void open_message_file(const gchar *file)
1919
{
1920
        MsgInfo *msginfo;
1921
        MsgFlags flags = {0};
1922
        MessageView *msgview;
1923

    
1924
        g_return_if_fail(file != NULL);
1925

    
1926
        debug_print("open message file: %s\n", file);
1927

    
1928
        if (!is_file_exist(file) || get_file_size(file) <= 0) {
1929
                debug_print("file not found: %s\n", file);
1930
                return;
1931
        }
1932

    
1933
        msginfo = procheader_parse_file(file, flags, FALSE);
1934
        if (msginfo) {
1935
                msginfo->file_path = g_strdup(file);
1936
                msgview = messageview_create_with_new_window();
1937
                messageview_show(msgview, msginfo, FALSE);
1938
                procmsg_msginfo_free(msginfo);
1939
        } else
1940
                debug_print("cannot open message: %s\n", file);
1941
}
1942

    
1943
static void open_message(const gchar *path)
1944
{
1945
        gchar *fid;
1946
        gchar *msg;
1947
        gint num;
1948
        FolderItem *item;
1949
        MsgInfo *msginfo;
1950
        MessageView *msgview;
1951
        gchar *file;
1952

    
1953
        g_return_if_fail(path != NULL);
1954

    
1955
        if (gtkut_window_modal_exist())
1956
                return;
1957

    
1958
        debug_print("open message: %s\n", path);
1959

    
1960
        if (!strncmp(path, "file:", 5)) {
1961
                file = g_filename_from_uri(path, NULL, NULL);
1962
                open_message_file(file);
1963
                g_free(file);
1964
                return;
1965
        } else if (g_path_is_absolute(path)) {
1966
                open_message_file(path);
1967
                return;
1968
        }
1969

    
1970
        /* relative path, or folder identifier */
1971

    
1972
        fid = g_path_get_dirname(path);
1973
        msg = g_path_get_basename(path);
1974
        num = to_number(msg);
1975
        item = folder_find_item_from_identifier(fid);
1976

    
1977
        if (num > 0 && item) {
1978
                debug_print("open folder id: %s (msg %d)\n", fid, num);
1979
                msginfo = folder_item_get_msginfo(item, num);
1980
                if (msginfo) {
1981
                        msgview = messageview_create_with_new_window();
1982
                        messageview_show(msgview, msginfo, FALSE);
1983
                        procmsg_msginfo_free(msginfo);
1984
                        g_free(msg);
1985
                        g_free(fid);
1986
                        return;
1987
                } else
1988
                        debug_print("message %d not found\n", num);
1989
        }
1990

    
1991
        g_free(msg);
1992
        g_free(fid);
1993

    
1994
        /* relative path */
1995

    
1996
        file = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, path, NULL);
1997
        open_message_file(file);
1998
        g_free(file);
1999
}
2000

    
2001
static void send_queue(void)
2002
{
2003
        GList *list;
2004

    
2005
        if (gtkut_window_modal_exist())
2006
                return;
2007
        if (!main_window_toggle_online_if_offline(main_window_get()))
2008
                return;
2009

    
2010
        for (list = folder_get_list(); list != NULL; list = list->next) {
2011
                Folder *folder = list->data;
2012

    
2013
                if (folder->queue) {
2014
                        gint ret;
2015

    
2016
                        ret = send_message_queue_all(folder->queue,
2017
                                                     prefs_common.savemsg,
2018
                                                     prefs_common.filter_sent);
2019
                        statusbar_pop_all();
2020
                        if (ret > 0)
2021
                                folder_item_scan(folder->queue);
2022
                }
2023
        }
2024

    
2025
        folderview_update_all_updated(TRUE);
2026
        main_window_set_menu_sensitive(main_window_get());
2027
        main_window_set_toolbar_sensitive(main_window_get());
2028
}