Statistics
| Revision:

root / src / main.c @ 2164

History | View | Annotate | Download (37.6 KB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2009 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 "filter.h"
65
#include "send_message.h"
66
#include "inc.h"
67
#include "import.h"
68
#include "manage_window.h"
69
#include "alertpanel.h"
70
#include "inputdialog.h"
71
#include "statusbar.h"
72
#include "addressbook.h"
73
#include "addrindex.h"
74
#include "compose.h"
75
#include "logwindow.h"
76
#include "folder.h"
77
#include "setup.h"
78
#include "sylmain.h"
79
#include "utils.h"
80
#include "gtkutils.h"
81
#include "socket.h"
82
#include "stock_pixmap.h"
83
#include "trayicon.h"
84
#include "plugin.h"
85
#include "plugin_manager.h"
86
#include "foldersel.h"
87
#include "update_check.h"
88

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

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

    
104
#include "version.h"
105

    
106
gchar *prog_version;
107

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

    
112
static gint lock_socket = -1;
113
static gint lock_socket_tag = 0;
114
static GIOChannel *lock_ch = NULL;
115

    
116
static struct RemoteCmd {
117
        gboolean receive;
118
        gboolean receive_all;
119
        gboolean compose;
120
        const gchar *compose_mailto;
121
        GPtrArray *attach_files;
122
        gboolean send;
123
        gboolean status;
124
        gboolean status_full;
125
        GPtrArray *status_folders;
126
        GPtrArray *status_full_folders;
127
        gchar *open_msg;
128
        gboolean configdir;
129
        gboolean exit;
130
#ifdef G_OS_WIN32
131
        gushort ipcport;
132
#endif
133
} cmd;
134

    
135
static void parse_cmd_opt                (int                 argc,
136
                                         char                *argv[]);
137

    
138
static void app_init                        (void);
139
static void parse_gtkrc_files                (void);
140
static void setup_rc_dir                (void);
141
static void check_gpg                        (void);
142
static void set_log_handlers                (gboolean         enable);
143
static void register_system_events        (void);
144
static void plugin_init                        (void);
145

    
146
static gchar *get_socket_name                (void);
147
static gint prohibit_duplicate_launch        (void);
148
static gint lock_socket_remove                (void);
149
static gboolean lock_socket_input_cb        (GIOChannel        *source,
150
                                         GIOCondition         condition,
151
                                         gpointer         data);
152

    
153
static void remote_command_exec                (void);
154
static void migrate_old_config                (void);
155

    
156
static void open_compose_new                (const gchar        *address,
157
                                         GPtrArray        *attach_files);
158
static void open_message                (const gchar        *path);
159

    
160
static void send_queue                        (void);
161

    
162
#define MAKE_DIR_IF_NOT_EXIST(dir)                                        \
163
{                                                                        \
164
        if (!is_dir_exist(dir)) {                                        \
165
                if (is_file_exist(dir)) {                                \
166
                        alertpanel_warning                                \
167
                                (_("File `%s' already exists.\n"        \
168
                                   "Can't create folder."),                \
169
                                 dir);                                        \
170
                        exit(1);                                        \
171
                }                                                        \
172
                if (make_dir(dir) < 0)                                        \
173
                        exit(1);                                        \
174
        }                                                                \
175
}
176

    
177
#define CHDIR_EXIT_IF_FAIL(dir, val)        \
178
{                                        \
179
        if (change_dir(dir) < 0)        \
180
                exit(val);                \
181
}
182

    
183
static void load_cb(GObject *obj, GModule *module, gpointer data)
184
{
185
        g_print("load_cb: %p (%s), %p\n", module, module ? g_module_name(module) : "(null)", data);
186
}
187

    
188
int main(int argc, char *argv[])
189
{
190
        MainWindow *mainwin;
191
        FolderView *folderview;
192
        GdkPixbuf *icon;
193
#ifdef G_OS_WIN32
194
        GList *iconlist = NULL;
195
#endif
196
        GObject *syl_app;
197

    
198
        app_init();
199
        parse_cmd_opt(argc, argv);
200

    
201
        /* check and create (unix domain) socket for remote operation */
202
        lock_socket = prohibit_duplicate_launch();
203
        if (lock_socket < 0) return 0;
204

    
205
        if (cmd.status || cmd.status_full) {
206
                puts("0 Sylpheed not running.");
207
                lock_socket_remove();
208
                return 0;
209
        }
210

    
211
        gtk_set_locale();
212
        gtk_init(&argc, &argv);
213

    
214
        syl_app = syl_app_create();
215

    
216
        gdk_rgb_init();
217
        gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
218
        gtk_widget_set_default_visual(gdk_rgb_get_visual());
219

    
220
#if USE_THREADS || USE_LDAP
221
        if (!g_thread_supported())
222
                g_thread_init(NULL);
223
        if (!g_thread_supported())
224
                g_error(_("g_thread is not supported by glib.\n"));
225
#endif
226

    
227
        parse_gtkrc_files();
228
        setup_rc_dir();
229

    
230
        if (is_file_exist("sylpheed.log")) {
231
                if (rename_force("sylpheed.log", "sylpheed.log.bak") < 0)
232
                        FILE_OP_ERROR("sylpheed.log", "rename");
233
        }
234
        set_log_file("sylpheed.log");
235

    
236
        set_ui_update_func(gtkut_events_flush);
237
        set_progress_func(main_window_progress_show);
238
        set_input_query_password_func(input_dialog_query_password);
239
#if USE_SSL
240
        ssl_set_verify_func(ssl_manager_verify_cert);
241
#endif
242

    
243
        CHDIR_EXIT_IF_FAIL(get_home_dir(), 1);
244

    
245
        prefs_common_read_config();
246
        filter_read_config();
247
        prefs_actions_read_config();
248
        prefs_display_header_read_config();
249

    
250
#ifdef G_OS_WIN32
251
        {
252
                gchar *path;
253
                path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC,
254
                                   NULL);
255
                if (!is_file_exist(path) && conv_is_ja_locale()) {
256
                        const gchar *str;
257

    
258
                        debug_print("fixing prefs_common.textfont setting\n");
259
                        str = "MS Gothic 12";
260
                        if (!gtkut_font_can_load(str)) {
261
                                debug_print("font '%s' load failed\n", str);
262
                                str = "\xef\xbc\xad\xef\xbc\xb3 \xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf 12";
263
                                if (!gtkut_font_can_load(str)) {
264
                                        debug_print("font '%s' load failed\n", str);
265
                                        str = NULL;
266
                                }
267
                        }
268
                        if (str) {
269
                                debug_print("font '%s' load ok\n", str);
270
                                g_free(prefs_common.textfont);
271
                                prefs_common.textfont = g_strdup(str);
272
                        }
273
                }
274
                g_free(path);
275
        }
276
#endif
277

    
278
        gtkut_stock_button_set_set_reverse(!prefs_common.comply_gnome_hig);
279

    
280
        check_gpg();
281

    
282
        sock_set_io_timeout(prefs_common.io_timeout_secs);
283

    
284
        gtkut_widget_init();
285

    
286
#ifdef G_OS_WIN32
287
        stock_pixbuf_gdk(NULL, STOCK_PIXMAP_SYLPHEED_32, &icon);
288
        iconlist = g_list_append(iconlist, icon);
289
        stock_pixbuf_gdk(NULL, STOCK_PIXMAP_SYLPHEED_SMALL, &icon);
290
        iconlist = g_list_append(iconlist, icon);
291
        gtk_window_set_default_icon_list(iconlist);
292
        g_list_free(iconlist);
293
#else
294
        stock_pixbuf_gdk(NULL, STOCK_PIXMAP_SYLPHEED, &icon);
295
        gtk_window_set_default_icon(icon);
296
#endif
297

    
298
        mainwin = main_window_create
299
                (prefs_common.sep_folder | prefs_common.sep_msg << 1);
300
        folderview = mainwin->folderview;
301

    
302
        /* register the callback of socket input */
303
        if (lock_socket > 0) {
304
                lock_ch = g_io_channel_unix_new(lock_socket);
305
                lock_socket_tag = g_io_add_watch(lock_ch,
306
                                                 G_IO_IN|G_IO_PRI|G_IO_ERR,
307
                                                 lock_socket_input_cb, mainwin);
308
        }
309

    
310
        set_log_handlers(TRUE);
311

    
312
        account_read_config_all();
313
        account_set_menu();
314
        main_window_reflect_prefs_all();
315

    
316
        if (folder_read_list() < 0) {
317
                setup(mainwin);
318
                folder_write_list();
319
        }
320
        if (!account_get_list()) {
321
                account_edit_open();
322
                account_add();
323
        }
324

    
325
        account_set_missing_folder();
326
        folder_set_missing_folders();
327
        folderview_set(folderview);
328

    
329
        addressbook_read_file();
330

    
331
        register_system_events();
332

    
333
        inc_autocheck_timer_init(mainwin);
334

    
335
        plugin_init();
336

    
337
        g_signal_emit_by_name(syl_app, "init-done");
338

    
339
        remote_command_exec();
340
        if (prefs_common.auto_update_check)
341
                update_check(FALSE);
342

    
343
        gtk_main();
344

    
345
        return 0;
346
}
347

    
348
static void init_console(void)
349
{
350
#ifdef G_OS_WIN32
351
        gint fd;
352
        FILE *fp;
353

    
354
        if (init_console_done)
355
                return;
356

    
357
        if (!AllocConsole()) {
358
                g_warning("AllocConsole() failed\n");
359
                return;
360
        }
361

    
362
        fd = _open_osfhandle((glong)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
363
        _dup2(fd, 1);
364
        fp = _fdopen(fd, "w");
365
        *stdout = *fp;
366
        setvbuf(stdout, NULL, _IONBF, 0);
367
        fd = _open_osfhandle((glong)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT);
368
        _dup2(fd, 2);
369
        fp = _fdopen(fd, "w");
370
        *stderr = *fp;
371
        setvbuf(stderr, NULL, _IONBF, 0);
372

    
373
        init_console_done = TRUE;
374
#endif
375
}
376

    
377
static void cleanup_console(void)
378
{
379
#ifdef G_OS_WIN32
380
        FreeConsole();
381
#endif
382
}
383

    
384
#ifdef G_OS_WIN32
385
static void read_ini_file(void)
386
{
387
        static gushort ipcport = REMOTE_CMD_PORT;
388
        static gchar *confdir = NULL;
389

    
390
        static PrefParam param[] = {
391
                {"ipcport", "50215", &ipcport, P_USHORT},
392
                {"configdir", NULL, &confdir, P_STRING},
393

    
394
                {NULL, NULL, NULL, P_OTHER}
395
        };
396

    
397
        gchar *file;
398

    
399
        file = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, "sylpheed.ini",
400
                           NULL);
401
        if (!is_file_exist(file)) {
402
                g_free(file);
403
                return;
404
        }
405

    
406
        prefs_read_config(param, "Sylpheed", file,
407
                          conv_get_locale_charset_str());
408
        g_free(file);
409

    
410
        cmd.ipcport = ipcport;
411
        if (confdir) {
412
                set_rc_dir(confdir);
413
                g_free(confdir);
414
                confdir = NULL;
415
                cmd.configdir = TRUE;
416
        }
417
}
418
#endif
419

    
420
static void parse_cmd_opt(int argc, char *argv[])
421
{
422
        gint i;
423

    
424
        for (i = 1; i < argc; i++) {
425
                if (!strncmp(argv[i], "--debug", 7)) {
426
                        init_console();
427
                        set_debug_mode(TRUE);
428
                } else if (!strncmp(argv[i], "--receive-all", 13))
429
                        cmd.receive_all = TRUE;
430
                else if (!strncmp(argv[i], "--receive", 9))
431
                        cmd.receive = TRUE;
432
                else if (!strncmp(argv[i], "--compose", 9)) {
433
                        const gchar *p = argv[i + 1];
434

    
435
                        cmd.compose = TRUE;
436
                        cmd.compose_mailto = NULL;
437
                        if (p && *p != '\0' && *p != '-') {
438
                                if (!strncmp(p, "mailto:", 7))
439
                                        cmd.compose_mailto = p + 7;
440
                                else
441
                                        cmd.compose_mailto = p;
442
                                i++;
443
                        }
444
                } else if (!strncmp(argv[i], "--attach", 8)) {
445
                        const gchar *p = argv[i + 1];
446
                        gchar *file;
447

    
448
                        while (p && *p != '\0' && *p != '-') {
449
                                if (!cmd.attach_files)
450
                                        cmd.attach_files = g_ptr_array_new();
451
                                if (!g_path_is_absolute(p))
452
                                        file = g_strconcat(get_startup_dir(),
453
                                                           G_DIR_SEPARATOR_S,
454
                                                           p, NULL);
455
                                else
456
                                        file = g_strdup(p);
457
                                g_ptr_array_add(cmd.attach_files, file);
458
                                i++;
459
                                p = argv[i + 1];
460
                        }
461
                } else if (!strncmp(argv[i], "--send", 6)) {
462
                        cmd.send = TRUE;
463
                } else if (!strncmp(argv[i], "--version", 9)) {
464
                        puts("Sylpheed version " VERSION);
465
                        exit(0);
466
                } else if (!strncmp(argv[i], "--status-full", 13)) {
467
                        const gchar *p = argv[i + 1];
468

    
469
                        cmd.status_full = TRUE;
470
                        while (p && *p != '\0' && *p != '-') {
471
                                if (!cmd.status_full_folders)
472
                                        cmd.status_full_folders =
473
                                                g_ptr_array_new();
474
                                g_ptr_array_add(cmd.status_full_folders,
475
                                                g_strdup(p));
476
                                i++;
477
                                p = argv[i + 1];
478
                        }
479
                } else if (!strncmp(argv[i], "--status", 8)) {
480
                        const gchar *p = argv[i + 1];
481

    
482
                        cmd.status = TRUE;
483
                        while (p && *p != '\0' && *p != '-') {
484
                                if (!cmd.status_folders)
485
                                        cmd.status_folders = g_ptr_array_new();
486
                                g_ptr_array_add(cmd.status_folders,
487
                                                g_strdup(p));
488
                                i++;
489
                                p = argv[i + 1];
490
                        }
491
                } else if (!strncmp(argv[i], "--open", 6)) {
492
                        const gchar *p = argv[i + 1];
493

    
494
                        if (p && *p != '\0' && *p != '-') {
495
                                cmd.open_msg = g_locale_to_utf8
496
                                        (p, -1, NULL, NULL, NULL);
497
                                i++;
498
                        }
499
                } else if (!strncmp(argv[i], "--configdir", 11)) {
500
                        const gchar *p = argv[i + 1];
501

    
502
                        if (p && *p != '\0' && *p != '-') {
503
                                /* this must only be done at startup */
504
#ifdef G_OS_WIN32
505
                                gchar *utf8dir;
506

    
507
                                utf8dir = g_locale_to_utf8
508
                                        (p, -1, NULL, NULL, NULL);
509
                                if (utf8dir) {
510
                                        set_rc_dir(utf8dir);
511
                                        g_free(utf8dir);
512
                                } else
513
                                        set_rc_dir(p);
514
#else
515
                                set_rc_dir(p);
516
#endif
517
                                cmd.configdir = TRUE;
518
                                i++;
519
                        }
520
#ifdef G_OS_WIN32
521
                } else if (!strncmp(argv[i], "--ipcport", 9)) {
522
                        if (argv[i + 1]) {
523
                                cmd.ipcport = atoi(argv[i + 1]);
524
                                i++;
525
                        }
526
#endif
527
                } else if (!strncmp(argv[i], "--exit", 6)) {
528
                        cmd.exit = TRUE;
529
                } else if (!strncmp(argv[i], "--help", 6)) {
530
                        init_console();
531

    
532
                        g_print(_("Usage: %s [OPTION]...\n"),
533
                                g_basename(argv[0]));
534

    
535
                        g_print("%s\n", _("  --compose [address]    open composition window"));
536
                        g_print("%s\n", _("  --attach file1 [file2]...\n"
537
                                "                         open composition window with specified files\n"
538
                                "                         attached"));
539
                        g_print("%s\n", _("  --receive              receive new messages"));
540
                        g_print("%s\n", _("  --receive-all          receive new messages of all accounts"));
541
                        g_print("%s\n", _("  --send                 send all queued messages"));
542
                        g_print("%s\n", _("  --status [folder]...   show the total number of messages"));
543
                        g_print("%s\n", _("  --status-full [folder]...\n"
544
                                "                         show the status of each folder"));
545
                        g_print("%s\n", _("  --open folderid/msgnum open message in new window"));
546
                        g_print("%s\n", _("  --configdir dirname    specify directory which stores configuration files"));
547
#ifdef G_OS_WIN32
548
                        g_print("%s\n", _("  --ipcport portnum      specify port for IPC remote commands"));
549
#endif
550
                        g_print("%s\n", _("  --exit                 exit Sylpheed"));
551
                        g_print("%s\n", _("  --debug                debug mode"));
552
                        g_print("%s\n", _("  --help                 display this help and exit"));
553
                        g_print("%s\n", _("  --version              output version information and exit"));
554

    
555
#ifdef G_OS_WIN32
556
                        g_print("\n");
557
                        g_print(_("Press any key..."));
558
                        _getch();
559
#endif
560

    
561
                        cleanup_console();
562
                        exit(1);
563
                }
564
        }
565

    
566
        if (cmd.attach_files && cmd.compose == FALSE) {
567
                cmd.compose = TRUE;
568
                cmd.compose_mailto = NULL;
569
        }
570
}
571

    
572
static gint get_queued_message_num(void)
573
{
574
        FolderItem *queue;
575

    
576
        queue = folder_get_default_queue();
577
        if (!queue) return -1;
578

    
579
        folder_item_scan(queue);
580
        return queue->total;
581
}
582

    
583
static void app_init(void)
584
{
585
        syl_init();
586

    
587
        prog_version = PROG_VERSION;
588

    
589
#ifdef G_OS_WIN32
590
        read_ini_file();
591
#endif
592
}
593

    
594
static void parse_gtkrc_files(void)
595
{
596
        gchar *userrc;
597

    
598
        /* parse gtkrc files */
599
        userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtkrc-2.0",
600
                             NULL);
601
        gtk_rc_parse(userrc);
602
        g_free(userrc);
603
        userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtk",
604
                             G_DIR_SEPARATOR_S, "gtkrc-2.0", NULL);
605
        gtk_rc_parse(userrc);
606
        g_free(userrc);
607
        userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, "gtkrc", NULL);
608
        gtk_rc_parse(userrc);
609
        g_free(userrc);
610

    
611
        userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
612
        gtk_accel_map_load(userrc);
613
        g_free(userrc);
614
}
615

    
616
static void setup_rc_dir(void)
617
{
618
#ifndef G_OS_WIN32
619
        CHDIR_EXIT_IF_FAIL(get_home_dir(), 1);
620

    
621
        /* backup if old rc file exists */
622
        if (!cmd.configdir && is_file_exist(RC_DIR)) {
623
                if (rename_force(RC_DIR, RC_DIR ".bak") < 0)
624
                        FILE_OP_ERROR(RC_DIR, "rename");
625
        }
626

    
627
        /* migration from ~/.sylpheed to ~/.sylpheed-2.0 */
628
        if (!cmd.configdir && !is_dir_exist(RC_DIR)) {
629
                const gchar *envstr;
630
                AlertValue val;
631

    
632
                /* check for filename encoding */
633
                if (conv_get_locale_charset() != C_UTF_8) {
634
                        envstr = g_getenv("G_FILENAME_ENCODING");
635
                        if (!envstr)
636
                                envstr = g_getenv("G_BROKEN_FILENAMES");
637
                        if (!envstr) {
638
                                val = alertpanel(_("Filename encoding"),
639
                                                 _("The locale encoding is not UTF-8, but the environmental variable G_FILENAME_ENCODING is not set.\n"
640
                                                   "If the locale encoding is used for file name or directory name, it will not work correctly.\n"
641
                                                   "In that case, you must set the following environmental variable (see README for detail):\n"
642
                                                   "\n"
643
                                                   "\tG_FILENAME_ENCODING=@locale\n"
644
                                                   "\n"
645
                                                   "Continue?"),
646
                                                 GTK_STOCK_OK, GTK_STOCK_QUIT,
647
                                                 NULL);
648
                                if (G_ALERTDEFAULT != val)
649
                                        exit(1);
650
                        }
651
                }
652

    
653
                if (make_dir(RC_DIR) < 0)
654
                        exit(1);
655
                if (is_dir_exist(OLD_RC_DIR))
656
                        migrate_old_config();
657
        }
658
#endif /* !G_OS_WIN32 */
659

    
660
        syl_setup_rc_dir();
661
}
662

    
663
void app_will_exit(gboolean force)
664
{
665
        MainWindow *mainwin;
666
        gchar *filename;
667
        static gboolean on_exit = FALSE;
668
        GList *cur;
669

    
670
        if (on_exit)
671
                return;
672
        on_exit = TRUE;
673

    
674
        mainwin = main_window_get();
675

    
676
        if (!force && compose_get_compose_list()) {
677
                if (alertpanel(_("Notice"),
678
                               _("Composing message exists. Really quit?"),
679
                               GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL)
680
                    != G_ALERTDEFAULT) {
681
                        on_exit = FALSE;
682
                        return;
683
                }
684
                manage_window_focus_in(mainwin->window, NULL, NULL);
685
        }
686

    
687
        if (!force &&
688
            prefs_common.warn_queued_on_exit && get_queued_message_num() > 0) {
689
                if (alertpanel(_("Queued messages"),
690
                               _("Some unsent messages are queued. Exit now?"),
691
                               GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL)
692
                    != G_ALERTDEFAULT) {
693
                        on_exit = FALSE;
694
                        return;
695
                }
696
                manage_window_focus_in(mainwin->window, NULL, NULL);
697
        }
698

    
699
        g_signal_emit_by_name(syl_app_get(), "app-exit");
700

    
701
        inc_autocheck_timer_remove();
702

    
703
        if (prefs_common.clean_on_exit)
704
                main_window_empty_trash(mainwin,
705
                                        !force && prefs_common.ask_on_clean);
706

    
707
        for (cur = account_get_list(); cur != NULL; cur = cur->next) {
708
                PrefsAccount *ac = (PrefsAccount *)cur->data;
709
                if (ac->protocol == A_IMAP4 && ac->imap_clear_cache_on_exit &&
710
                    ac->folder)
711
                        procmsg_remove_all_cached_messages(FOLDER(ac->folder));
712
        }
713

    
714
        syl_plugin_unload_all();
715

    
716
        trayicon_destroy(mainwin->tray_icon);
717

    
718
        /* save all state before exiting */
719
        summary_write_cache(mainwin->summaryview);
720
        main_window_get_size(mainwin);
721
        main_window_get_position(mainwin);
722
        syl_save_all_state();
723
        addressbook_export_to_file();
724

    
725
        filename = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
726
        gtk_accel_map_save(filename);
727
        g_free(filename);
728

    
729
        /* remove temporary files, close log file, socket cleanup */
730
        syl_cleanup();
731
        lock_socket_remove();
732

    
733
        cleanup_console();
734

    
735
        if (gtk_main_level() > 0)
736
                gtk_main_quit();
737

    
738
        exit(0);
739
}
740

    
741
#if 0
742
#if USE_GPGME
743
static void idle_function_for_gpgme(void)
744
{
745
        while (gtk_events_pending())
746
                gtk_main_iteration();
747
}
748
#endif /* USE_GPGME */
749
#endif /* 0 */
750

    
751
static void check_gpg(void)
752
{
753
#if USE_GPGME
754
        if (gpgme_check_version("0.4.5") &&
755
            !gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP)) {
756
                /* Also does some gpgme init */
757
                gpgme_engine_info_t engineInfo;
758

    
759
#if HAVE_LOCALE_H
760
                gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
761
                gpgme_set_locale(NULL, LC_MESSAGES,
762
                                 setlocale(LC_MESSAGES, NULL));
763
#endif
764

    
765
                if (!gpgme_get_engine_info(&engineInfo)) {
766
                        while (engineInfo) {
767
                                debug_print("GpgME Protocol: %s\n      Version: %s\n",
768
                                            gpgme_get_protocol_name
769
                                                (engineInfo->protocol),
770
                                            engineInfo->version ?
771
                                            engineInfo->version : "(unknown)");
772
                                engineInfo = engineInfo->next;
773
                        }
774
                }
775

    
776
                procmsg_set_decrypt_message_func
777
                        (rfc2015_open_message_decrypted);
778
                procmsg_set_auto_decrypt_message(TRUE);
779
        } else {
780
                rfc2015_disable_all();
781

    
782
                if (prefs_common.gpg_warning) {
783
                        AlertValue val;
784

    
785
                        val = alertpanel_message_with_disable
786
                                (_("Warning"),
787
                                 _("GnuPG is not installed properly, or its version is too old.\n"
788
                                   "OpenPGP support disabled."),
789
                                 ALERT_WARNING);
790
                        if (val & G_ALERTDISABLE)
791
                                prefs_common.gpg_warning = FALSE;
792
                }
793
        }
794
        /* FIXME: This function went away.  We can either block until gpgme
795
         * operations finish (currently implemented) or register callbacks
796
         * with the gtk main loop via the gpgme io callback interface instead.
797
         *
798
         * gpgme_register_idle(idle_function_for_gpgme);
799
         */
800
#endif
801
}
802

    
803
static void default_log_func(const gchar *log_domain, GLogLevelFlags log_level,
804
                             const gchar *message, gpointer user_data)
805
{
806
        gchar *prefix = "";
807
        gchar *file_prefix = "";
808
        LogType level = LOG_NORMAL;
809
        gchar *str;
810
        const gchar *message_;
811

    
812
        switch (log_level) {
813
        case G_LOG_LEVEL_ERROR:
814
                prefix = "ERROR";
815
                file_prefix = "*** ";
816
                level = LOG_ERROR;
817
                break;
818
        case G_LOG_LEVEL_CRITICAL:
819
                prefix = "CRITICAL";
820
                file_prefix = "** ";
821
                level = LOG_WARN;
822
                break;
823
        case G_LOG_LEVEL_WARNING:
824
                prefix = "WARNING";
825
                file_prefix = "** ";
826
                level = LOG_WARN;
827
                break;
828
        case G_LOG_LEVEL_MESSAGE:
829
                prefix = "Message";
830
                file_prefix = "* ";
831
                level = LOG_MSG;
832
                break;
833
        case G_LOG_LEVEL_INFO:
834
                prefix = "INFO";
835
                file_prefix = "* ";
836
                level = LOG_MSG;
837
                break;
838
        case G_LOG_LEVEL_DEBUG:
839
                prefix = "DEBUG";
840
                break;
841
        default:
842
                prefix = "LOG";
843
                break;
844
        }
845

    
846
        if (!message)
847
                message_ = "(NULL) message";
848
        else
849
                message_ = message;
850
        if (log_domain)
851
                str = g_strconcat(log_domain, "-", prefix, ": ", message_, "\n",
852
                                  NULL);
853
        else
854
                str = g_strconcat(prefix, ": ", message_, "\n", NULL);
855
        log_window_append(str, level);
856
        log_write(str, file_prefix);
857
        g_free(str);
858

    
859
        g_log_default_handler(log_domain, log_level, message, user_data);
860
}
861

    
862
static void set_log_handlers(gboolean enable)
863
{
864
#if GLIB_CHECK_VERSION(2, 6, 0)
865
        if (enable)
866
                g_log_set_default_handler(default_log_func, NULL);
867
        else
868
                g_log_set_default_handler(g_log_default_handler, NULL);
869
#else
870
        static guint handler_id[4] = {0, 0, 0, 0};
871

    
872
        if (enable) {
873
                handler_id[0] = g_log_set_handler
874
                        ("GLib", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
875
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
876
                handler_id[1] = g_log_set_handler
877
                        ("Gtk", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
878
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
879
                handler_id[2] = g_log_set_handler
880
                        ("LibSylph", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
881
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
882
                handler_id[3] = g_log_set_handler
883
                        ("Sylpheed", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
884
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
885
        } else {
886
                g_log_remove_handler("GLib", handler_id[0]);
887
                g_log_remove_handler("Gtk", handler_id[1]);
888
                g_log_remove_handler("LibSylph", handler_id[2]);
889
                g_log_remove_handler("Sylpheed", handler_id[3]);
890
                handler_id[0] = 0;
891
                handler_id[1] = 0;
892
                handler_id[2] = 0;
893
                handler_id[3] = 0;
894
        }
895
#endif
896
}
897

    
898
#ifdef G_OS_WIN32
899
static BOOL WINAPI
900
ctrl_handler(DWORD dwctrltype)
901
{
902
        log_print("ctrl_handler: received %d\n", dwctrltype);
903
        app_will_exit(TRUE);
904

    
905
        return TRUE;
906
}
907

    
908
static LRESULT CALLBACK
909
wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
910
{
911
        switch (message) {
912
        case WM_POWERBROADCAST:
913
                debug_print("WM_POWERBROADCAST received: wparam = %d\n",
914
                            wparam);
915
                if (wparam == PBT_APMSUSPEND || wparam == PBT_APMSTANDBY) {
916
                        debug_print("suspend now\n");
917
                        inc_autocheck_timer_remove();
918
                } else if (wparam == PBT_APMRESUMESUSPEND ||
919
                           wparam == PBT_APMRESUMESTANDBY) {
920
                        debug_print("resume now\n");
921
                        inc_autocheck_timer_set();
922
                }
923
                break;
924
        case WM_ENDSESSION:
925
                if (wparam == 1) {
926
                        log_print("WM_ENDSESSION received: system is quitting\n");
927
                        app_will_exit(TRUE);
928
                }
929
                break;
930
        default:
931
                break;
932
        }
933

    
934
        return DefWindowProc(hwnd, message, wparam, lparam);
935
}
936

    
937
static void register_system_events(void)
938
{
939
        WNDCLASS wclass;
940
        static HWND hwnd = NULL;
941
        static BOOL ctrl_handler_set = FALSE;
942
        ATOM klass;
943
        HINSTANCE hmodule = GetModuleHandle(NULL);
944

    
945
        if (init_console_done && !ctrl_handler_set) {
946
                debug_print("register_system_events(): SetConsoleCtrlHandler\n");
947
                ctrl_handler_set = SetConsoleCtrlHandler(ctrl_handler, TRUE);
948
                if (!ctrl_handler_set)
949
                        g_warning("SetConsoleCtrlHandler() failed\n");
950
        }
951

    
952
        if (hwnd)
953
                return;
954

    
955
        debug_print("register_system_events(): RegisterClass\n");
956

    
957
        memset(&wclass, 0, sizeof(WNDCLASS));
958
        wclass.lpszClassName = "sylpheed-observer";
959
        wclass.lpfnWndProc   = wndproc;
960
        wclass.hInstance     = hmodule;
961

    
962
        klass = RegisterClass(&wclass);
963
        if (!klass)
964
                return;
965

    
966
        hwnd = CreateWindow(MAKEINTRESOURCE(klass), NULL, WS_POPUP,
967
                            0, 0, 1, 1, NULL, NULL, hmodule, NULL);
968
        if (!hwnd)
969
                UnregisterClass(MAKEINTRESOURCE(klass), hmodule);
970
}
971
#else /* G_OS_WIN32 */
972
static void sig_handler(gint signum)
973
{
974
        debug_print("signal %d received\n", signum);
975

    
976
        switch (signum) {
977
        case SIGHUP:
978
        case SIGINT:
979
        case SIGTERM:
980
        case SIGQUIT:
981
                app_will_exit(TRUE);
982
                break;
983
        default:
984
                break;
985
        }
986
}
987

    
988
static void register_system_events(void)
989
{
990
        struct sigaction sa;
991

    
992
        memset(&sa, 0, sizeof(sa));
993
        sa.sa_handler = sig_handler;
994
        sa.sa_flags = SA_RESTART;
995

    
996
        sigemptyset(&sa.sa_mask);
997
        sigaddset(&sa.sa_mask, SIGHUP);
998
        sigaddset(&sa.sa_mask, SIGINT);
999
        sigaddset(&sa.sa_mask, SIGTERM);
1000
        sigaddset(&sa.sa_mask, SIGQUIT);
1001
        sigaddset(&sa.sa_mask, SIGPIPE);
1002

    
1003
        sigaction(SIGHUP, &sa, NULL);
1004
        sigaction(SIGINT, &sa, NULL);
1005
        sigaction(SIGTERM, &sa, NULL);
1006
        sigaction(SIGQUIT, &sa, NULL);
1007
        sigaction(SIGPIPE, &sa, NULL);
1008
}
1009
#endif
1010

    
1011
static void plugin_init(void)
1012
{
1013
        MainWindow *mainwin;
1014

    
1015
        mainwin = main_window_get();
1016

    
1017
        if (syl_plugin_init_lib() != 0)
1018
                return;
1019

    
1020
        syl_plugin_add_symbol("prog_version", prog_version);
1021
        syl_plugin_add_symbol("main_window_get", main_window_get);
1022
        syl_plugin_add_symbol("main_window_popup", main_window_popup);
1023
        syl_plugin_add_symbol("app_will_exit", app_will_exit);
1024
        syl_plugin_add_symbol("main_window_menu_factory",
1025
                              mainwin->menu_factory);
1026

    
1027
        syl_plugin_add_symbol("folderview", mainwin->folderview);
1028
        syl_plugin_add_symbol("folderview_get_selected_item",
1029
                              folderview_get_selected_item);
1030
        syl_plugin_add_symbol("folderview_mail_popup_factory",
1031
                              mainwin->folderview->mail_factory);
1032

    
1033
        syl_plugin_add_symbol("summaryview", mainwin->summaryview);
1034
        syl_plugin_add_symbol("summary_select_by_msgnum",
1035
                              summary_select_by_msgnum);
1036
        syl_plugin_add_symbol("summary_select_by_msginfo",
1037
                              summary_select_by_msginfo);
1038

    
1039
        syl_plugin_add_symbol("messageview_create_with_new_window",
1040
                              messageview_create_with_new_window);
1041
        syl_plugin_add_symbol("messageview_show", messageview_show);
1042

    
1043
        syl_plugin_add_symbol("foldersel_folder_sel",
1044
                              foldersel_folder_sel);
1045
        syl_plugin_add_symbol("foldersel_folder_sel_full",
1046
                              foldersel_folder_sel_full);
1047
        syl_plugin_add_symbol("input_dialog", input_dialog);
1048
        syl_plugin_add_symbol("input_dialog_with_invisible",
1049
                              input_dialog_with_invisible);
1050

    
1051
        syl_plugin_add_symbol("manage_window_set_transient",
1052
                              manage_window_set_transient);
1053
        syl_plugin_add_symbol("manage_window_signals_connect",
1054
                              manage_window_signals_connect);
1055
        syl_plugin_add_symbol("manage_window_get_focus_window",
1056
                              manage_window_get_focus_window);
1057

    
1058
        syl_plugin_add_symbol("inc_mail", inc_mail);
1059
        syl_plugin_add_symbol("inc_lock", inc_lock);
1060
        syl_plugin_add_symbol("inc_unlock", inc_unlock);
1061

    
1062
        syl_plugin_signal_connect("plugin-load", G_CALLBACK(load_cb), NULL);
1063

    
1064
#ifdef G_OS_WIN32
1065
        {
1066
                gchar *path;
1067
                path = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S,
1068
                                   "plugins", NULL);
1069
                syl_plugin_load_all(path);
1070
                g_free(path);
1071
        }
1072
#else
1073
        syl_plugin_load_all(PLUGINDIR);
1074
#endif
1075
}
1076

    
1077
static gchar *get_socket_name(void)
1078
{
1079
        static gchar *filename = NULL;
1080

    
1081
        if (filename == NULL) {
1082
                filename = g_strdup_printf("%s%csylpheed-%d",
1083
                                           g_get_tmp_dir(), G_DIR_SEPARATOR,
1084
#if HAVE_GETUID
1085
                                           getuid());
1086
#else
1087
                                           0);
1088
#endif
1089
        }
1090

    
1091
        return filename;
1092
}
1093

    
1094
static gint prohibit_duplicate_launch(void)
1095
{
1096
        gint sock;
1097

    
1098
#ifdef G_OS_WIN32
1099
        HANDLE hmutex;
1100

    
1101
        hmutex = CreateMutexA(NULL, FALSE, "Sylpheed");
1102
        if (!hmutex) {
1103
                g_warning("cannot create Mutex\n");
1104
                return -1;
1105
        }
1106
        if (GetLastError() != ERROR_ALREADY_EXISTS) {
1107
                sock = fd_open_inet(cmd.ipcport ? cmd.ipcport : REMOTE_CMD_PORT);
1108
                if (sock < 0)
1109
                        return 0;
1110
                return sock;
1111
        }
1112

    
1113
        sock = fd_connect_inet(cmd.ipcport ? cmd.ipcport : REMOTE_CMD_PORT);
1114
        if (sock < 0)
1115
                return -1;
1116
#else
1117
        gchar *path;
1118

    
1119
        path = get_socket_name();
1120
        sock = fd_connect_unix(path);
1121
        if (sock < 0) {
1122
                g_unlink(path);
1123
                return fd_open_unix(path);
1124
        }
1125
#endif
1126

    
1127
        /* remote command mode */
1128

    
1129
        debug_print(_("another Sylpheed is already running.\n"));
1130

    
1131
        if (cmd.receive_all)
1132
                fd_write_all(sock, "receive_all\n", 12);
1133
        else if (cmd.receive)
1134
                fd_write_all(sock, "receive\n", 8);
1135
        else if (cmd.compose && cmd.attach_files) {
1136
                gchar *str, *compose_str;
1137
                gint i;
1138

    
1139
                if (cmd.compose_mailto)
1140
                        compose_str = g_strdup_printf("compose_attach %s\n",
1141
                                                      cmd.compose_mailto);
1142
                else
1143
                        compose_str = g_strdup("compose_attach\n");
1144

    
1145
                fd_write_all(sock, compose_str, strlen(compose_str));
1146
                g_free(compose_str);
1147

    
1148
                for (i = 0; i < cmd.attach_files->len; i++) {
1149
                        str = g_ptr_array_index(cmd.attach_files, i);
1150
                        fd_write_all(sock, str, strlen(str));
1151
                        fd_write_all(sock, "\n", 1);
1152
                }
1153

    
1154
                fd_write_all(sock, ".\n", 2);
1155
        } else if (cmd.compose) {
1156
                gchar *compose_str;
1157

    
1158
                if (cmd.compose_mailto)
1159
                        compose_str = g_strdup_printf
1160
                                ("compose %s\n", cmd.compose_mailto);
1161
                else
1162
                        compose_str = g_strdup("compose\n");
1163

    
1164
                fd_write_all(sock, compose_str, strlen(compose_str));
1165
                g_free(compose_str);
1166
        } else if (cmd.send) {
1167
                fd_write_all(sock, "send\n", 5);
1168
        } else if (cmd.status || cmd.status_full) {
1169
                gchar buf[BUFFSIZE];
1170
                gint i;
1171
                const gchar *command;
1172
                GPtrArray *folders;
1173
                gchar *folder;
1174

    
1175
                command = cmd.status_full ? "status-full\n" : "status\n";
1176
                folders = cmd.status_full ? cmd.status_full_folders :
1177
                        cmd.status_folders;
1178

    
1179
                fd_write_all(sock, command, strlen(command));
1180
                for (i = 0; folders && i < folders->len; ++i) {
1181
                        folder = g_ptr_array_index(folders, i);
1182
                        fd_write_all(sock, folder, strlen(folder));
1183
                        fd_write_all(sock, "\n", 1);
1184
                }
1185
                fd_write_all(sock, ".\n", 2);
1186
                for (;;) {
1187
                        fd_gets(sock, buf, sizeof(buf));
1188
                        if (!strncmp(buf, ".\n", 2)) break;
1189
                        fputs(buf, stdout);
1190
                }
1191
        } else if (cmd.open_msg) {
1192
                gchar *str;
1193

    
1194
                str = g_strdup_printf("open %s\n", cmd.open_msg);
1195
                fd_write_all(sock, str, strlen(str));
1196
                g_free(str);
1197
        } else if (cmd.exit) {
1198
                fd_write_all(sock, "exit\n", 5);
1199
        } else {
1200
#ifdef G_OS_WIN32
1201
                HWND hwnd;
1202

    
1203
                fd_write_all(sock, "popup\n", 6);
1204
                if (fd_read(sock, (gchar *)&hwnd, sizeof(hwnd)) == sizeof(hwnd))
1205
                        SetForegroundWindow(hwnd);
1206
#else
1207
                fd_write_all(sock, "popup\n", 6);
1208
#endif
1209
        }
1210

    
1211
        fd_close(sock);
1212
        return -1;
1213
}
1214

    
1215
static gint lock_socket_remove(void)
1216
{
1217
#ifndef G_OS_WIN32
1218
        gchar *filename;
1219
#endif
1220

    
1221
        if (lock_socket < 0) return -1;
1222

    
1223
        if (lock_socket_tag > 0)
1224
                g_source_remove(lock_socket_tag);
1225
        if (lock_ch) {
1226
                g_io_channel_shutdown(lock_ch, FALSE, NULL);
1227
                g_io_channel_unref(lock_ch);
1228
                lock_ch = NULL;
1229
        }
1230

    
1231
#ifndef G_OS_WIN32
1232
        filename = get_socket_name();
1233
        g_unlink(filename);
1234
#endif
1235

    
1236
        return 0;
1237
}
1238

    
1239
static GPtrArray *get_folder_item_list(gint sock)
1240
{
1241
        gchar buf[BUFFSIZE];
1242
        FolderItem *item;
1243
        GPtrArray *folders = NULL;
1244

    
1245
        for (;;) {
1246
                fd_gets(sock, buf, sizeof(buf));
1247
                if (!strncmp(buf, ".\n", 2)) break;
1248
                strretchomp(buf);
1249
                if (!folders) folders = g_ptr_array_new();
1250
                item = folder_find_item_from_identifier(buf);
1251
                if (item)
1252
                        g_ptr_array_add(folders, item);
1253
                else
1254
                        g_warning("no such folder: %s\n", buf);
1255
        }
1256

    
1257
        return folders;
1258
}
1259

    
1260
static gboolean lock_socket_input_cb(GIOChannel *source, GIOCondition condition,
1261
                                     gpointer data)
1262
{
1263
        MainWindow *mainwin = (MainWindow *)data;
1264
        gint fd, sock;
1265
        gchar buf[BUFFSIZE];
1266

    
1267
        fd = g_io_channel_unix_get_fd(source);
1268
        sock = fd_accept(fd);
1269
        fd_gets(sock, buf, sizeof(buf));
1270

    
1271
        if (!strncmp(buf, "popup", 5)) {
1272
#ifdef G_OS_WIN32
1273
                HWND hwnd;
1274

    
1275
                hwnd = (HWND)gdk_win32_drawable_get_handle
1276
                        (GDK_DRAWABLE(mainwin->window->window));
1277
                fd_write(sock, (gchar *)&hwnd, sizeof(hwnd));
1278
                if (mainwin->window_hidden)
1279
                        main_window_popup(mainwin);
1280
#else
1281
                main_window_popup(mainwin);
1282
#endif
1283
        } else if (!strncmp(buf, "receive_all", 11)) {
1284
                main_window_popup(mainwin);
1285
                if (!gtkut_window_modal_exist())
1286
                        inc_all_account_mail(mainwin, FALSE);
1287
        } else if (!strncmp(buf, "receive", 7)) {
1288
                main_window_popup(mainwin);
1289
                if (!gtkut_window_modal_exist())
1290
                        inc_mail(mainwin);
1291
        } else if (!strncmp(buf, "compose_attach", 14)) {
1292
                GPtrArray *files;
1293
                gchar *mailto;
1294

    
1295
                mailto = g_strdup(buf + strlen("compose_attach") + 1);
1296
                files = g_ptr_array_new();
1297
                while (fd_gets(sock, buf, sizeof(buf)) > 0) {
1298
                        if (buf[0] == '.' && buf[1] == '\n') break;
1299
                        strretchomp(buf);
1300
                        g_ptr_array_add(files, g_strdup(buf));
1301
                }
1302
                open_compose_new(mailto, files);
1303
                ptr_array_free_strings(files);
1304
                g_ptr_array_free(files, TRUE);
1305
                g_free(mailto);
1306
        } else if (!strncmp(buf, "compose", 7)) {
1307
                open_compose_new(buf + strlen("compose") + 1, NULL);
1308
        } else if (!strncmp(buf, "send", 4)) {
1309
                send_queue();
1310
        } else if (!strncmp(buf, "status-full", 11) ||
1311
                   !strncmp(buf, "status", 6)) {
1312
                gchar *status;
1313
                GPtrArray *folders;
1314

    
1315
                folders = get_folder_item_list(sock);
1316
                status = folder_get_status
1317
                        (folders, !strncmp(buf, "status-full", 11));
1318
                fd_write_all(sock, status, strlen(status));
1319
                fd_write_all(sock, ".\n", 2);
1320
                g_free(status);
1321
                if (folders) g_ptr_array_free(folders, TRUE);
1322
        } else if (!strncmp(buf, "open", 4)) {
1323
                strretchomp(buf);
1324
                if (strlen(buf) < 6 || buf[4] != ' ') {
1325
                        fd_close(sock);
1326
                        return TRUE;
1327
                }
1328
                open_message(buf + 5);
1329
        } else if (!strncmp(buf, "exit", 4)) {
1330
                fd_close(sock);
1331
                app_will_exit(TRUE);
1332
        }
1333

    
1334
        fd_close(sock);
1335

    
1336
        return TRUE;
1337
}
1338

    
1339
static void remote_command_exec(void)
1340
{
1341
        MainWindow *mainwin;
1342

    
1343
        mainwin = main_window_get();
1344

    
1345
        if (prefs_common.open_inbox_on_startup) {
1346
                FolderItem *item;
1347
                item = cur_account && cur_account->inbox
1348
                        ? folder_find_item_from_identifier(cur_account->inbox)
1349
                        : folder_get_default_inbox();
1350
                folderview_select(mainwin->folderview, item);
1351
        }
1352

    
1353
        if (!gtkut_window_modal_exist()) {
1354
                if (cmd.receive_all)
1355
                        inc_all_account_mail(mainwin, FALSE);
1356
                else if (prefs_common.chk_on_startup)
1357
                        inc_all_account_mail(mainwin, TRUE);
1358
                else if (cmd.receive)
1359
                        inc_mail(mainwin);
1360

    
1361
                if (cmd.compose)
1362
                        open_compose_new(cmd.compose_mailto, cmd.attach_files);
1363

    
1364
                if (cmd.send)
1365
                        send_queue();
1366

    
1367
                if (cmd.open_msg)
1368
                        open_message(cmd.open_msg);
1369
        }
1370

    
1371
        if (cmd.attach_files) {
1372
                ptr_array_free_strings(cmd.attach_files);
1373
                g_ptr_array_free(cmd.attach_files, TRUE);
1374
                cmd.attach_files = NULL;
1375
        }
1376
        if (cmd.status_folders) {
1377
                g_ptr_array_free(cmd.status_folders, TRUE);
1378
                cmd.status_folders = NULL;
1379
        }
1380
        if (cmd.status_full_folders) {
1381
                g_ptr_array_free(cmd.status_full_folders, TRUE);
1382
                cmd.status_full_folders = NULL;
1383
        }
1384
        if (cmd.open_msg) {
1385
                g_free(cmd.open_msg);
1386
                cmd.open_msg = NULL;
1387
        }
1388
        if (cmd.exit) {
1389
                app_will_exit(TRUE);
1390
        }
1391
}
1392

    
1393
static void migrate_old_config(void)
1394
{
1395
        GDir *dir;
1396
        const gchar *dir_name;
1397
        GPatternSpec *pspec;
1398

    
1399
        if (alertpanel(_("Migration of configuration"),
1400
                       _("The previous version of configuration found.\n"
1401
                         "Do you want to migrate it?"),
1402
                       GTK_STOCK_YES, GTK_STOCK_NO, NULL) != G_ALERTDEFAULT)
1403
                return;
1404

    
1405
        debug_print("Migrating old configuration...\n");
1406

    
1407
#define COPY_FILE(rcfile)                                                \
1408
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile)) {        \
1409
                conv_copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile,        \
1410
                               RC_DIR G_DIR_SEPARATOR_S rcfile,                \
1411
                               conv_get_locale_charset_str());                \
1412
        }
1413

    
1414
        COPY_FILE(ACCOUNT_RC);
1415
        COPY_FILE(ACTIONS_RC);
1416
        COPY_FILE(COMMON_RC);
1417
        COPY_FILE(CUSTOM_HEADER_RC);
1418
        COPY_FILE(DISPLAY_HEADER_RC);
1419
        COPY_FILE(FILTER_HEADER_RC);
1420
        COPY_FILE(COMMAND_HISTORY);
1421

    
1422
#undef COPY_FILE
1423

    
1424
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST))
1425
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST,
1426
                          RC_DIR G_DIR_SEPARATOR_S FILTER_LIST, FALSE);
1427
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST))
1428
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST,
1429
                          RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST, FALSE);
1430
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types"))
1431
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types",
1432
                          RC_DIR G_DIR_SEPARATOR_S "mime.types", FALSE);
1433

    
1434
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR))
1435
                conv_copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1436
                              RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1437
                              conv_get_locale_charset_str());
1438
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR))
1439
                copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR,
1440
                         RC_DIR G_DIR_SEPARATOR_S UIDL_DIR);
1441

    
1442
        if (!is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S ADDRESSBOOK_INDEX_FILE))
1443
                return;
1444

    
1445
        if ((dir = g_dir_open(OLD_RC_DIR, 0, NULL)) == NULL) {
1446
                g_warning("failed to open directory: %s\n", OLD_RC_DIR);
1447
                return;
1448
        }
1449

    
1450
        pspec = g_pattern_spec_new("addrbook-*.xml");
1451

    
1452
        while ((dir_name = g_dir_read_name(dir)) != NULL) {
1453
                if (g_pattern_match_string(pspec, dir_name)) {
1454
                        gchar *old_file;
1455
                        gchar *new_file;
1456

    
1457
                        old_file = g_strconcat(OLD_RC_DIR G_DIR_SEPARATOR_S,
1458
                                               dir_name, NULL);
1459
                        new_file = g_strconcat(RC_DIR G_DIR_SEPARATOR_S,
1460
                                               dir_name, NULL);
1461
                        copy_file(old_file, new_file, FALSE);
1462
                        g_free(new_file);
1463
                        g_free(old_file);
1464
                }
1465
        }
1466

    
1467
        g_pattern_spec_free(pspec);
1468
        g_dir_close(dir);
1469
}
1470

    
1471
static void open_compose_new(const gchar *address, GPtrArray *attach_files)
1472
{
1473
        gchar *utf8addr = NULL;
1474
#ifdef G_OS_WIN32
1475
        GPtrArray *utf8files = NULL;
1476
#endif
1477

    
1478
        if (gtkut_window_modal_exist())
1479
                return;
1480

    
1481
        if (address) {
1482
                utf8addr = g_locale_to_utf8(address, -1, NULL, NULL, NULL);
1483
                if (utf8addr)
1484
                        g_strstrip(utf8addr);
1485
        }
1486

    
1487
#ifdef G_OS_WIN32
1488
        if (attach_files) {
1489
                gint i;
1490
                gchar *file, *utf8file;
1491

    
1492
                utf8files = g_ptr_array_new();
1493
                for (i = 0; i < attach_files->len; i++) {
1494
                        file = g_ptr_array_index(attach_files, i);
1495
                        utf8file = g_locale_to_utf8(file, -1, NULL, NULL, NULL);
1496
                        if (utf8file)
1497
                                g_ptr_array_add(utf8files, utf8file);
1498
                }
1499
        }
1500

    
1501
        compose_new(NULL, NULL, utf8addr, utf8files);
1502
        if (utf8files) {
1503
                ptr_array_free_strings(utf8files);
1504
                g_ptr_array_free(utf8files, TRUE);
1505
        }
1506
#else
1507
        compose_new(NULL, NULL, utf8addr, attach_files);
1508
#endif
1509

    
1510
        g_free(utf8addr);
1511
}
1512

    
1513
static void open_message(const gchar *path)
1514
{
1515
        gchar *id;
1516
        gchar *msg;
1517
        gint num;
1518
        FolderItem *item;
1519
        MsgInfo *msginfo;
1520
        MessageView *msgview;
1521

    
1522
        if (gtkut_window_modal_exist())
1523
                return;
1524

    
1525
        id = g_path_get_dirname(path);
1526
        msg = g_path_get_basename(path);
1527
        num = to_number(msg);
1528
        item = folder_find_item_from_identifier(id);
1529
        debug_print("open folder id: %s (msg %d)\n", id, num);
1530

    
1531
        if (num > 0 && item) {
1532
                msginfo = folder_item_get_msginfo(item, num);
1533
                if (msginfo) {
1534
                        msgview = messageview_create_with_new_window();
1535
                        messageview_show(msgview, msginfo, FALSE);
1536
                        procmsg_msginfo_free(msginfo);
1537
                } else
1538
                        debug_print("message %d not found\n", num);
1539
        }
1540

    
1541
        g_free(msg);
1542
        g_free(id);
1543
}
1544

    
1545
static void send_queue(void)
1546
{
1547
        GList *list;
1548

    
1549
        if (gtkut_window_modal_exist())
1550
                return;
1551
        if (!main_window_toggle_online_if_offline(main_window_get()))
1552
                return;
1553

    
1554
        for (list = folder_get_list(); list != NULL; list = list->next) {
1555
                Folder *folder = list->data;
1556

    
1557
                if (folder->queue) {
1558
                        gint ret;
1559

    
1560
                        ret = send_message_queue_all(folder->queue,
1561
                                                     prefs_common.savemsg,
1562
                                                     prefs_common.filter_sent);
1563
                        statusbar_pop_all();
1564
                        if (ret > 0)
1565
                                folder_item_scan(folder->queue);
1566
                }
1567
        }
1568

    
1569
        folderview_update_all_updated(TRUE);
1570
        main_window_set_menu_sensitive(main_window_get());
1571
        main_window_set_toolbar_sensitive(main_window_get());
1572
}