Statistics
| Revision:

root / src / main.c @ 2635

History | View | Annotate | Download (41.7 kB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2010 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
#include "colorlabel.h"
89
90
#if USE_GPGME
91
#  include "rfc2015.h"
92
#endif
93
#if USE_SSL
94
#  include "ssl.h"
95
#  include "sslmanager.h"
96
#endif
97
98
#ifdef G_OS_WIN32
99
#  include <windows.h>
100
#  include <pbt.h>
101
#  include <fcntl.h>
102
#  include <conio.h>
103
#endif
104
105
#include "version.h"
106
107
gchar *prog_version;
108
109
#ifdef G_OS_WIN32
110
static gboolean init_console_done = FALSE;
111
#endif
112
113
static gint lock_socket = -1;
114
static gint lock_socket_tag = 0;
115
static GIOChannel *lock_ch = NULL;
116
static gchar *instance_id = NULL;
117
118
#if USE_THREADS
119
static GThread *main_thread;
120
#endif
121
122
static struct RemoteCmd {
123
        gboolean receive;
124
        gboolean receive_all;
125
        gboolean compose;
126
        const gchar *compose_mailto;
127
        GPtrArray *attach_files;
128
        gboolean send;
129
        gboolean status;
130
        gboolean status_full;
131
        GPtrArray *status_folders;
132
        GPtrArray *status_full_folders;
133
        gchar *open_msg;
134
        gboolean configdir;
135
        gboolean exit;
136
#ifdef G_OS_WIN32
137
        gushort ipcport;
138
#endif
139
} cmd;
140
141
#define STATUSBAR_PUSH(mainwin, str) \
142
{ \
143
        gtk_statusbar_push(GTK_STATUSBAR(mainwin->statusbar), \
144
                           mainwin->mainwin_cid, str); \
145
        gtkut_widget_draw_now(mainwin->statusbar); \
146
}
147
148
#define STATUSBAR_POP(mainwin) \
149
{ \
150
        gtk_statusbar_pop(GTK_STATUSBAR(mainwin->statusbar), \
151
                          mainwin->mainwin_cid); \
152
}
153
154
static void parse_cmd_opt                (int                 argc,
155
                                         char                *argv[]);
156
157
static void app_init                        (void);
158
static void parse_gtkrc_files                (void);
159
static void setup_rc_dir                (void);
160
static void check_gpg                        (void);
161
static void set_log_handlers                (gboolean         enable);
162
static void register_system_events        (void);
163
static void plugin_init                        (void);
164
165
static gchar *get_socket_name                (void);
166
static gint prohibit_duplicate_launch        (void);
167
static gint lock_socket_remove                (void);
168
static gboolean lock_socket_input_cb        (GIOChannel        *source,
169
                                         GIOCondition         condition,
170
                                         gpointer         data);
171
172
static void remote_command_exec                (void);
173
static void migrate_old_config                (void);
174
175
static void open_compose_new                (const gchar        *address,
176
                                         GPtrArray        *attach_files);
177
static void open_message                (const gchar        *path);
178
179
static void send_queue                        (void);
180
181
#define MAKE_DIR_IF_NOT_EXIST(dir)                                        \
182
{                                                                        \
183
        if (!is_dir_exist(dir)) {                                        \
184
                if (is_file_exist(dir)) {                                \
185
                        alertpanel_warning                                \
186
                                (_("File `%s' already exists.\n"        \
187
                                   "Can't create folder."),                \
188
                                 dir);                                        \
189
                        exit(1);                                        \
190
                }                                                        \
191
                if (make_dir(dir) < 0)                                        \
192
                        exit(1);                                        \
193
        }                                                                \
194
}
195
196
#define CHDIR_EXIT_IF_FAIL(dir, val)        \
197
{                                        \
198
        if (change_dir(dir) < 0)        \
199
                exit(val);                \
200
}
201
202
static void load_cb(GObject *obj, GModule *module, gpointer data)
203
{
204
        debug_print("load_cb: %p (%s), %p\n", module, module ? g_module_name(module) : "(null)", data);
205
}
206
207
int main(int argc, char *argv[])
208
{
209
        MainWindow *mainwin;
210
        FolderView *folderview;
211
        GdkPixbuf *icon;
212
#ifdef G_OS_WIN32
213
        GList *iconlist = NULL;
214
#endif
215
        GObject *syl_app;
216
        PrefsAccount *new_account = NULL;
217
218
        app_init();
219
        parse_cmd_opt(argc, argv);
220
221
        /* check and create (unix domain) socket for remote operation */
222
        lock_socket = prohibit_duplicate_launch();
223
        if (lock_socket < 0) return 0;
224
225
        if (cmd.status || cmd.status_full) {
226
                puts("0 Sylpheed not running.");
227
                lock_socket_remove();
228
                return 0;
229
        }
230
231
#if USE_THREADS
232
        gdk_threads_enter();
233
#endif
234
        gtk_set_locale();
235
        gtk_init(&argc, &argv);
236
237
        syl_app = syl_app_create();
238
239
        gdk_rgb_init();
240
        gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
241
        gtk_widget_set_default_visual(gdk_rgb_get_visual());
242
243
        parse_gtkrc_files();
244
        setup_rc_dir();
245
246
        if (is_file_exist("sylpheed.log")) {
247
                if (rename_force("sylpheed.log", "sylpheed.log.bak") < 0)
248
                        FILE_OP_ERROR("sylpheed.log", "rename");
249
        }
250
        set_log_file("sylpheed.log");
251
252
        set_ui_update_func(gtkut_events_flush);
253
        set_progress_func(main_window_progress_show);
254
        set_input_query_password_func(input_dialog_query_password);
255
#if USE_SSL
256
        ssl_init();
257
        ssl_set_verify_func(ssl_manager_verify_cert);
258
#endif
259
260
        CHDIR_EXIT_IF_FAIL(get_home_dir(), 1);
261
262
        prefs_common_read_config();
263
        filter_set_addressbook_func(addressbook_has_address);
264
        filter_read_config();
265
        prefs_actions_read_config();
266
        prefs_display_header_read_config();
267
        colorlabel_read_config();
268
269
        prefs_common.user_agent_str = g_strdup_printf
270
                ("%s (GTK+ %d.%d.%d; %s)",
271
                 prog_version,
272
                 gtk_major_version, gtk_minor_version, gtk_micro_version,
273
                 TARGET_ALIAS);
274
275
#ifdef G_OS_WIN32
276
        {
277
                gchar *path;
278
                path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, COMMON_RC,
279
                                   NULL);
280
                if (!is_file_exist(path) && conv_is_ja_locale()) {
281
                        const gchar *str;
282
283
                        debug_print("fixing prefs_common.textfont setting\n");
284
                        str = "MS Gothic 12";
285
                        if (!gtkut_font_can_load(str)) {
286
                                debug_print("font '%s' load failed\n", str);
287
                                str = "\xef\xbc\xad\xef\xbc\xb3 \xe3\x82\xb4\xe3\x82\xb7\xe3\x83\x83\xe3\x82\xaf 12";
288
                                if (!gtkut_font_can_load(str)) {
289
                                        debug_print("font '%s' load failed\n", str);
290
                                        str = NULL;
291
                                }
292
                        }
293
                        if (str) {
294
                                debug_print("font '%s' load ok\n", str);
295
                                g_free(prefs_common.textfont);
296
                                prefs_common.textfont = g_strdup(str);
297
                        }
298
                }
299
                g_free(path);
300
        }
301
#endif
302
303
        gtkut_stock_button_set_set_reverse(!prefs_common.comply_gnome_hig);
304
305
        check_gpg();
306
307
        sock_set_io_timeout(prefs_common.io_timeout_secs);
308
309
        gtkut_widget_init();
310
311
#ifdef G_OS_WIN32
312
        stock_pixbuf_gdk(NULL, STOCK_PIXMAP_SYLPHEED_32, &icon);
313
        iconlist = g_list_append(iconlist, icon);
314
        stock_pixbuf_gdk(NULL, STOCK_PIXMAP_SYLPHEED_SMALL, &icon);
315
        iconlist = g_list_append(iconlist, icon);
316
        gtk_window_set_default_icon_list(iconlist);
317
        g_list_free(iconlist);
318
#else
319
        stock_pixbuf_gdk(NULL, STOCK_PIXMAP_SYLPHEED, &icon);
320
        gtk_window_set_default_icon(icon);
321
#endif
322
323
        mainwin = main_window_create
324
                (prefs_common.sep_folder | prefs_common.sep_msg << 1);
325
        folderview = mainwin->folderview;
326
327
        /* register the callback of socket input */
328
        if (lock_socket > 0) {
329
                lock_ch = g_io_channel_unix_new(lock_socket);
330
                lock_socket_tag = g_io_add_watch(lock_ch,
331
                                                 G_IO_IN|G_IO_PRI|G_IO_ERR,
332
                                                 lock_socket_input_cb, mainwin);
333
        }
334
335
        set_log_handlers(TRUE);
336
337
        account_read_config_all();
338
        account_set_menu();
339
        main_window_reflect_prefs_all();
340
341
        if (folder_read_list() < 0) {
342
                setup_mailbox();
343
                folder_write_list();
344
        }
345
        if (!account_get_list()) {
346
                new_account = setup_account();
347
        }
348
349
        account_set_menu();
350
        main_window_reflect_prefs_all();
351
352
        account_set_missing_folder();
353
        folder_set_missing_folders();
354
        folderview_set(folderview);
355
        if (new_account && new_account->folder)
356
                folder_write_list();
357
358
        addressbook_read_file();
359
360
        register_system_events();
361
362
        inc_autocheck_timer_init(mainwin);
363
364
        plugin_init();
365
366
        g_signal_emit_by_name(syl_app, "init-done");
367
368
        remote_command_exec();
369
370
#if USE_UPDATE_CHECK
371
        if (prefs_common.auto_update_check)
372
                update_check(FALSE);
373
#endif
374
375
        gtk_main();
376
#if USE_THREADS
377
        gdk_threads_leave();
378
#endif
379
380
        return 0;
381
}
382
383
static void init_console(void)
384
{
385
#ifdef G_OS_WIN32
386
        gint fd;
387
        FILE *fp;
388
389
        if (init_console_done)
390
                return;
391
392
        if (!AllocConsole()) {
393
                g_warning("AllocConsole() failed\n");
394
                return;
395
        }
396
397
        fd = _open_osfhandle((glong)GetStdHandle(STD_OUTPUT_HANDLE), _O_TEXT);
398
        _dup2(fd, 1);
399
        fp = _fdopen(fd, "w");
400
        *stdout = *fp;
401
        setvbuf(stdout, NULL, _IONBF, 0);
402
        fd = _open_osfhandle((glong)GetStdHandle(STD_ERROR_HANDLE), _O_TEXT);
403
        _dup2(fd, 2);
404
        fp = _fdopen(fd, "w");
405
        *stderr = *fp;
406
        setvbuf(stderr, NULL, _IONBF, 0);
407
408
        init_console_done = TRUE;
409
#endif
410
}
411
412
static void cleanup_console(void)
413
{
414
#ifdef G_OS_WIN32
415
        FreeConsole();
416
#endif
417
}
418
419
#ifdef G_OS_WIN32
420
static void read_ini_file(void)
421
{
422
        static gushort ipcport = REMOTE_CMD_PORT;
423
        static gchar *confdir = NULL;
424
425
        static PrefParam param[] = {
426
                {"ipcport", "50215", &ipcport, P_USHORT},
427
                {"configdir", NULL, &confdir, P_STRING},
428
429
                {NULL, NULL, NULL, P_OTHER}
430
        };
431
432
        gchar *file;
433
434
        file = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, "sylpheed.ini",
435
                           NULL);
436
        if (!is_file_exist(file)) {
437
                g_free(file);
438
                return;
439
        }
440
441
        prefs_read_config(param, "Sylpheed", file,
442
                          conv_get_locale_charset_str());
443
        g_free(file);
444
445
        cmd.ipcport = ipcport;
446
        if (confdir) {
447
                set_rc_dir(confdir);
448
                g_free(confdir);
449
                confdir = NULL;
450
                cmd.configdir = TRUE;
451
        }
452
}
453
#endif
454
455
static void parse_cmd_opt(int argc, char *argv[])
456
{
457
        gint i;
458
459
        for (i = 1; i < argc; i++) {
460
                if (!strncmp(argv[i], "--debug", 7)) {
461
                        init_console();
462
                        set_debug_mode(TRUE);
463
                } else if (!strncmp(argv[i], "--receive-all", 13))
464
                        cmd.receive_all = TRUE;
465
                else if (!strncmp(argv[i], "--receive", 9))
466
                        cmd.receive = TRUE;
467
                else if (!strncmp(argv[i], "--compose", 9)) {
468
                        const gchar *p = argv[i + 1];
469
470
                        cmd.compose = TRUE;
471
                        cmd.compose_mailto = NULL;
472
                        if (p && *p != '\0' && *p != '-') {
473
                                if (!strncmp(p, "mailto:", 7))
474
                                        cmd.compose_mailto = p + 7;
475
                                else
476
                                        cmd.compose_mailto = p;
477
                                i++;
478
                        }
479
                } else if (!strncmp(argv[i], "--attach", 8)) {
480
                        const gchar *p = argv[i + 1];
481
                        gchar *file;
482
483
                        while (p && *p != '\0' && *p != '-') {
484
                                if (!cmd.attach_files)
485
                                        cmd.attach_files = g_ptr_array_new();
486
                                if (!g_path_is_absolute(p))
487
                                        file = g_strconcat(get_startup_dir(),
488
                                                           G_DIR_SEPARATOR_S,
489
                                                           p, NULL);
490
                                else
491
                                        file = g_strdup(p);
492
                                g_ptr_array_add(cmd.attach_files, file);
493
                                i++;
494
                                p = argv[i + 1];
495
                        }
496
                } else if (!strncmp(argv[i], "--send", 6)) {
497
                        cmd.send = TRUE;
498
                } else if (!strncmp(argv[i], "--version", 9)) {
499
                        puts("Sylpheed version " VERSION);
500
                        exit(0);
501
                } else if (!strncmp(argv[i], "--status-full", 13)) {
502
                        const gchar *p = argv[i + 1];
503
504
                        cmd.status_full = TRUE;
505
                        while (p && *p != '\0' && *p != '-') {
506
                                if (!cmd.status_full_folders)
507
                                        cmd.status_full_folders =
508
                                                g_ptr_array_new();
509
                                g_ptr_array_add(cmd.status_full_folders,
510
                                                g_strdup(p));
511
                                i++;
512
                                p = argv[i + 1];
513
                        }
514
                } else if (!strncmp(argv[i], "--status", 8)) {
515
                        const gchar *p = argv[i + 1];
516
517
                        cmd.status = TRUE;
518
                        while (p && *p != '\0' && *p != '-') {
519
                                if (!cmd.status_folders)
520
                                        cmd.status_folders = g_ptr_array_new();
521
                                g_ptr_array_add(cmd.status_folders,
522
                                                g_strdup(p));
523
                                i++;
524
                                p = argv[i + 1];
525
                        }
526
                } else if (!strncmp(argv[i], "--open", 6)) {
527
                        const gchar *p = argv[i + 1];
528
529
                        if (p && *p != '\0' && *p != '-') {
530
                                cmd.open_msg = g_locale_to_utf8
531
                                        (p, -1, NULL, NULL, NULL);
532
                                i++;
533
                        }
534
                } else if (!strncmp(argv[i], "--configdir", 11)) {
535
                        const gchar *p = argv[i + 1];
536
537
                        if (p && *p != '\0' && *p != '-') {
538
                                /* this must only be done at startup */
539
#ifdef G_OS_WIN32
540
                                gchar *utf8dir;
541
542
                                utf8dir = g_locale_to_utf8
543
                                        (p, -1, NULL, NULL, NULL);
544
                                if (utf8dir) {
545
                                        set_rc_dir(utf8dir);
546
                                        g_free(utf8dir);
547
                                } else
548
                                        set_rc_dir(p);
549
#else
550
                                set_rc_dir(p);
551
#endif
552
                                cmd.configdir = TRUE;
553
                                i++;
554
                        }
555
#ifdef G_OS_WIN32
556
                } else if (!strncmp(argv[i], "--ipcport", 9)) {
557
                        if (argv[i + 1]) {
558
                                cmd.ipcport = atoi(argv[i + 1]);
559
                                i++;
560
                        }
561
#endif
562
                } else if (!strncmp(argv[i], "--instance-id", 13)) {
563
                        if (argv[i + 1]) {
564
                                instance_id = g_locale_to_utf8
565
                                        (argv[i + 1], -1, NULL, NULL, NULL);
566
                                i++;
567
                        }
568
                } else if (!strncmp(argv[i], "--exit", 6)) {
569
                        cmd.exit = TRUE;
570
                } else if (!strncmp(argv[i], "--help", 6)) {
571
                        init_console();
572
573
                        g_print(_("Usage: %s [OPTION]...\n"),
574
                                g_basename(argv[0]));
575
576
                        g_print("%s\n", _("  --compose [address]    open composition window"));
577
                        g_print("%s\n", _("  --attach file1 [file2]...\n"
578
                                "                         open composition window with specified files\n"
579
                                "                         attached"));
580
                        g_print("%s\n", _("  --receive              receive new messages"));
581
                        g_print("%s\n", _("  --receive-all          receive new messages of all accounts"));
582
                        g_print("%s\n", _("  --send                 send all queued messages"));
583
                        g_print("%s\n", _("  --status [folder]...   show the total number of messages"));
584
                        g_print("%s\n", _("  --status-full [folder]...\n"
585
                                "                         show the status of each folder"));
586
                        g_print("%s\n", _("  --open folderid/msgnum open message in new window"));
587
                        g_print("%s\n", _("  --configdir dirname    specify directory which stores configuration files"));
588
#ifdef G_OS_WIN32
589
                        g_print("%s\n", _("  --ipcport portnum      specify port for IPC remote commands"));
590
#endif
591
                        g_print("%s\n", _("  --exit                 exit Sylpheed"));
592
                        g_print("%s\n", _("  --debug                debug mode"));
593
                        g_print("%s\n", _("  --help                 display this help and exit"));
594
                        g_print("%s\n", _("  --version              output version information and exit"));
595
596
#ifdef G_OS_WIN32
597
                        g_print("\n");
598
                        g_print(_("Press any key..."));
599
                        _getch();
600
#endif
601
602
                        cleanup_console();
603
                        exit(1);
604
                }
605
        }
606
607
        if (cmd.attach_files && cmd.compose == FALSE) {
608
                cmd.compose = TRUE;
609
                cmd.compose_mailto = NULL;
610
        }
611
}
612
613
static gint get_queued_message_num(void)
614
{
615
        FolderItem *queue;
616
617
        queue = folder_get_default_queue();
618
        if (!queue) return -1;
619
620
        folder_item_scan(queue);
621
        return queue->total;
622
}
623
624
#if USE_THREADS
625
/* enables recursive locking with gdk_thread_enter / gdk_threads_leave */
626
static GStaticRecMutex syl_mutex = G_STATIC_REC_MUTEX_INIT;
627
628
static void thread_enter_func(void)
629
{
630
        g_static_rec_mutex_lock(&syl_mutex);
631
#if 0
632
        syl_mutex_lock_count++;
633
        if (syl_mutex_lock_count > 1)
634
                g_print("enter: syl_mutex_lock_count: %d\n", syl_mutex_lock_count);
635
#endif
636
}
637
638
static void thread_leave_func(void)
639
{
640
#if 0
641
        syl_mutex_lock_count--;
642
        if (syl_mutex_lock_count > 0)
643
                g_print("leave: syl_mutex_lock_count: %d\n", syl_mutex_lock_count);
644
#endif
645
        g_static_rec_mutex_unlock(&syl_mutex);
646
}
647
648
static void event_loop_iteration_func(void)
649
{
650
        if (g_thread_self() != main_thread) {
651
                g_fprintf(stderr, "event_loop_iteration_func called from non-main thread (%p)\n", g_thread_self());
652
                g_usleep(10000);
653
                return;
654
        }
655
        gtk_main_iteration();
656
}
657
#endif
658
659
static void app_init(void)
660
{
661
#if USE_THREADS
662
        if (!g_thread_supported())
663
                g_thread_init(NULL);
664
        if (!g_thread_supported())
665
                g_error("g_thread is not supported by glib.");
666
        else {
667
                gdk_threads_set_lock_functions(thread_enter_func,
668
                                               thread_leave_func);
669
                gdk_threads_init();
670
                main_thread = g_thread_self();
671
        }
672
#endif
673
        syl_init();
674
675
#if USE_THREADS
676
        set_event_loop_func(event_loop_iteration_func);
677
#endif
678
        prog_version = PROG_VERSION;
679
680
#ifdef G_OS_WIN32
681
        read_ini_file();
682
#endif
683
}
684
685
static void parse_gtkrc_files(void)
686
{
687
        gchar *userrc;
688
689
        /* parse gtkrc files */
690
        userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtkrc-2.0",
691
                             NULL);
692
        gtk_rc_parse(userrc);
693
        g_free(userrc);
694
        userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtk",
695
                             G_DIR_SEPARATOR_S, "gtkrc-2.0", NULL);
696
        gtk_rc_parse(userrc);
697
        g_free(userrc);
698
        userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, "gtkrc", NULL);
699
        gtk_rc_parse(userrc);
700
        g_free(userrc);
701
702
        userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
703
        gtk_accel_map_load(userrc);
704
        g_free(userrc);
705
}
706
707
static void setup_rc_dir(void)
708
{
709
#ifndef G_OS_WIN32
710
        CHDIR_EXIT_IF_FAIL(get_home_dir(), 1);
711
712
        /* backup if old rc file exists */
713
        if (!cmd.configdir && is_file_exist(RC_DIR)) {
714
                if (rename_force(RC_DIR, RC_DIR ".bak") < 0)
715
                        FILE_OP_ERROR(RC_DIR, "rename");
716
        }
717
718
        /* migration from ~/.sylpheed to ~/.sylpheed-2.0 */
719
        if (!cmd.configdir && !is_dir_exist(RC_DIR)) {
720
                const gchar *envstr;
721
                AlertValue val;
722
723
                /* check for filename encoding */
724
                if (conv_get_locale_charset() != C_UTF_8) {
725
                        envstr = g_getenv("G_FILENAME_ENCODING");
726
                        if (!envstr)
727
                                envstr = g_getenv("G_BROKEN_FILENAMES");
728
                        if (!envstr) {
729
                                val = alertpanel(_("Filename encoding"),
730
                                                 _("The locale encoding is not UTF-8, but the environmental variable G_FILENAME_ENCODING is not set.\n"
731
                                                   "If the locale encoding is used for file name or directory name, it will not work correctly.\n"
732
                                                   "In that case, you must set the following environmental variable (see README for detail):\n"
733
                                                   "\n"
734
                                                   "\tG_FILENAME_ENCODING=@locale\n"
735
                                                   "\n"
736
                                                   "Continue?"),
737
                                                 GTK_STOCK_OK, GTK_STOCK_QUIT,
738
                                                 NULL);
739
                                if (G_ALERTDEFAULT != val)
740
                                        exit(1);
741
                        }
742
                }
743
744
                if (make_dir(RC_DIR) < 0)
745
                        exit(1);
746
                if (is_dir_exist(OLD_RC_DIR))
747
                        migrate_old_config();
748
        }
749
#endif /* !G_OS_WIN32 */
750
751
        syl_setup_rc_dir();
752
}
753
754
void app_will_exit(gboolean force)
755
{
756
        MainWindow *mainwin;
757
        gchar *filename;
758
        static gboolean on_exit = FALSE;
759
        GList *cur;
760
761
        if (on_exit)
762
                return;
763
        on_exit = TRUE;
764
765
        mainwin = main_window_get();
766
767
        if (!force && compose_get_compose_list()) {
768
                if (alertpanel(_("Notice"),
769
                               _("Composing message exists. Really quit?"),
770
                               GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL)
771
                    != G_ALERTDEFAULT) {
772
                        on_exit = FALSE;
773
                        return;
774
                }
775
                manage_window_focus_in(mainwin->window, NULL, NULL);
776
        }
777
778
        if (!force &&
779
            prefs_common.warn_queued_on_exit && get_queued_message_num() > 0) {
780
                if (alertpanel(_("Queued messages"),
781
                               _("Some unsent messages are queued. Exit now?"),
782
                               GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL)
783
                    != G_ALERTDEFAULT) {
784
                        on_exit = FALSE;
785
                        return;
786
                }
787
                manage_window_focus_in(mainwin->window, NULL, NULL);
788
        }
789
790
        g_signal_emit_by_name(syl_app_get(), "app-exit");
791
792
        inc_autocheck_timer_remove();
793
794
        if (prefs_common.clean_on_exit)
795
                main_window_empty_trash(mainwin,
796
                                        !force && prefs_common.ask_on_clean);
797
798
        for (cur = account_get_list(); cur != NULL; cur = cur->next) {
799
                PrefsAccount *ac = (PrefsAccount *)cur->data;
800
                if (ac->protocol == A_IMAP4 && ac->imap_clear_cache_on_exit &&
801
                    ac->folder)
802
                        procmsg_remove_all_cached_messages(FOLDER(ac->folder));
803
        }
804
805
        syl_plugin_unload_all();
806
807
        trayicon_destroy(mainwin->tray_icon);
808
809
        /* save all state before exiting */
810
        summary_write_cache(mainwin->summaryview);
811
        main_window_get_size(mainwin);
812
        main_window_get_position(mainwin);
813
        syl_save_all_state();
814
        addressbook_export_to_file();
815
816
        filename = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
817
        gtk_accel_map_save(filename);
818
        g_free(filename);
819
820
        /* remove temporary files, close log file, socket cleanup */
821
#if USE_SSL
822
        ssl_done();
823
#endif
824
        syl_cleanup();
825
        lock_socket_remove();
826
827
        cleanup_console();
828
829
        if (gtk_main_level() > 0)
830
                gtk_main_quit();
831
832
        exit(0);
833
}
834
835
#if 0
836
#if USE_GPGME
837
static void idle_function_for_gpgme(void)
838
{
839
        while (gtk_events_pending())
840
                gtk_main_iteration();
841
}
842
#endif /* USE_GPGME */
843
#endif /* 0 */
844
845
static void check_gpg(void)
846
{
847
#if USE_GPGME
848
        const gchar *version;
849
        gpgme_error_t err = 0;
850
851
        version = gpgme_check_version("1.0.0");
852
        if (version) {
853
                debug_print("GPGME Version: %s\n", version);
854
                err = gpgme_engine_check_version(GPGME_PROTOCOL_OpenPGP);
855
                if (err)
856
                        debug_print("gpgme_engine_check_version: %s\n",
857
                                    gpgme_strerror(err));
858
        }
859
860
        if (version && !err) {
861
                /* Also does some gpgme init */
862
                gpgme_engine_info_t engineInfo;
863
864
#if HAVE_LOCALE_H
865
                gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
866
                gpgme_set_locale(NULL, LC_MESSAGES,
867
                                 setlocale(LC_MESSAGES, NULL));
868
#endif
869
870
                if (!gpgme_get_engine_info(&engineInfo)) {
871
                        while (engineInfo) {
872
                                debug_print("GPGME Protocol: %s\n      Version: %s\n",
873
                                            gpgme_get_protocol_name
874
                                                (engineInfo->protocol),
875
                                            engineInfo->version ?
876
                                            engineInfo->version : "(unknown)");
877
                                engineInfo = engineInfo->next;
878
                        }
879
                }
880
881
                procmsg_set_decrypt_message_func
882
                        (rfc2015_open_message_decrypted);
883
                procmsg_set_auto_decrypt_message(TRUE);
884
        } else {
885
                rfc2015_disable_all();
886
887
                if (prefs_common.gpg_warning) {
888
                        AlertValue val;
889
890
                        val = alertpanel_message_with_disable
891
                                (_("Warning"),
892
                                 _("GnuPG is not installed properly, or its version is too old.\n"
893
                                   "OpenPGP support disabled."),
894
                                 ALERT_WARNING);
895
                        if (val & G_ALERTDISABLE)
896
                                prefs_common.gpg_warning = FALSE;
897
                }
898
        }
899
        /* FIXME: This function went away.  We can either block until gpgme
900
         * operations finish (currently implemented) or register callbacks
901
         * with the gtk main loop via the gpgme io callback interface instead.
902
         *
903
         * gpgme_register_idle(idle_function_for_gpgme);
904
         */
905
#endif
906
}
907
908
static void default_log_func(const gchar *log_domain, GLogLevelFlags log_level,
909
                             const gchar *message, gpointer user_data)
910
{
911
        gchar *prefix = "";
912
        gchar *file_prefix = "";
913
        LogType level = LOG_NORMAL;
914
        gchar *str;
915
        const gchar *message_;
916
917
        switch (log_level) {
918
        case G_LOG_LEVEL_ERROR:
919
                prefix = "ERROR";
920
                file_prefix = "*** ";
921
                level = LOG_ERROR;
922
                break;
923
        case G_LOG_LEVEL_CRITICAL:
924
                prefix = "CRITICAL";
925
                file_prefix = "** ";
926
                level = LOG_WARN;
927
                break;
928
        case G_LOG_LEVEL_WARNING:
929
                prefix = "WARNING";
930
                file_prefix = "** ";
931
                level = LOG_WARN;
932
                break;
933
        case G_LOG_LEVEL_MESSAGE:
934
                prefix = "Message";
935
                file_prefix = "* ";
936
                level = LOG_MSG;
937
                break;
938
        case G_LOG_LEVEL_INFO:
939
                prefix = "INFO";
940
                file_prefix = "* ";
941
                level = LOG_MSG;
942
                break;
943
        case G_LOG_LEVEL_DEBUG:
944
                prefix = "DEBUG";
945
                break;
946
        default:
947
                prefix = "LOG";
948
                break;
949
        }
950
951
        if (!message)
952
                message_ = "(NULL) message";
953
        else
954
                message_ = message;
955
        if (log_domain)
956
                str = g_strconcat(log_domain, "-", prefix, ": ", message_, "\n",
957
                                  NULL);
958
        else
959
                str = g_strconcat(prefix, ": ", message_, "\n", NULL);
960
        log_window_append(str, level);
961
        log_write(str, file_prefix);
962
        g_free(str);
963
964
        g_log_default_handler(log_domain, log_level, message, user_data);
965
}
966
967
static void set_log_handlers(gboolean enable)
968
{
969
#if GLIB_CHECK_VERSION(2, 6, 0)
970
        if (enable)
971
                g_log_set_default_handler(default_log_func, NULL);
972
        else
973
                g_log_set_default_handler(g_log_default_handler, NULL);
974
#else
975
        static guint handler_id[4] = {0, 0, 0, 0};
976
977
        if (enable) {
978
                handler_id[0] = g_log_set_handler
979
                        ("GLib", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
980
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
981
                handler_id[1] = g_log_set_handler
982
                        ("Gtk", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
983
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
984
                handler_id[2] = g_log_set_handler
985
                        ("LibSylph", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
986
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
987
                handler_id[3] = g_log_set_handler
988
                        ("Sylpheed", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
989
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
990
        } else {
991
                g_log_remove_handler("GLib", handler_id[0]);
992
                g_log_remove_handler("Gtk", handler_id[1]);
993
                g_log_remove_handler("LibSylph", handler_id[2]);
994
                g_log_remove_handler("Sylpheed", handler_id[3]);
995
                handler_id[0] = 0;
996
                handler_id[1] = 0;
997
                handler_id[2] = 0;
998
                handler_id[3] = 0;
999
        }
1000
#endif
1001
}
1002
1003
#ifdef G_OS_WIN32
1004
static BOOL WINAPI
1005
ctrl_handler(DWORD dwctrltype)
1006
{
1007
        log_print("ctrl_handler: received %d\n", dwctrltype);
1008
        app_will_exit(TRUE);
1009
1010
        return TRUE;
1011
}
1012
1013
static LRESULT CALLBACK
1014
wndproc(HWND hwnd, UINT message, WPARAM wparam, LPARAM lparam)
1015
{
1016
        switch (message) {
1017
        case WM_POWERBROADCAST:
1018
                debug_print("WM_POWERBROADCAST received: wparam = %d\n",
1019
                            wparam);
1020
                if (wparam == PBT_APMSUSPEND || wparam == PBT_APMSTANDBY) {
1021
                        debug_print("suspend now\n");
1022
                        inc_autocheck_timer_remove();
1023
                } else if (wparam == PBT_APMRESUMESUSPEND ||
1024
                           wparam == PBT_APMRESUMESTANDBY) {
1025
                        debug_print("resume now\n");
1026
                        inc_autocheck_timer_set();
1027
                }
1028
                break;
1029
        case WM_ENDSESSION:
1030
                if (wparam == 1) {
1031
                        log_print("WM_ENDSESSION received: system is quitting\n");
1032
                        app_will_exit(TRUE);
1033
                }
1034
                break;
1035
        default:
1036
                break;
1037
        }
1038
1039
        return DefWindowProc(hwnd, message, wparam, lparam);
1040
}
1041
1042
static void register_system_events(void)
1043
{
1044
        WNDCLASS wclass;
1045
        static HWND hwnd = NULL;
1046
        static BOOL ctrl_handler_set = FALSE;
1047
        ATOM klass;
1048
        HINSTANCE hmodule = GetModuleHandle(NULL);
1049
1050
        if (init_console_done && !ctrl_handler_set) {
1051
                debug_print("register_system_events(): SetConsoleCtrlHandler\n");
1052
                ctrl_handler_set = SetConsoleCtrlHandler(ctrl_handler, TRUE);
1053
                if (!ctrl_handler_set)
1054
                        g_warning("SetConsoleCtrlHandler() failed\n");
1055
        }
1056
1057
        if (hwnd)
1058
                return;
1059
1060
        debug_print("register_system_events(): RegisterClass\n");
1061
1062
        memset(&wclass, 0, sizeof(WNDCLASS));
1063
        wclass.lpszClassName = "sylpheed-observer";
1064
        wclass.lpfnWndProc   = wndproc;
1065
        wclass.hInstance     = hmodule;
1066
1067
        klass = RegisterClass(&wclass);
1068
        if (!klass)
1069
                return;
1070
1071
        hwnd = CreateWindow(MAKEINTRESOURCE(klass), NULL, WS_POPUP,
1072
                            0, 0, 1, 1, NULL, NULL, hmodule, NULL);
1073
        if (!hwnd)
1074
                UnregisterClass(MAKEINTRESOURCE(klass), hmodule);
1075
}
1076
#else /* G_OS_WIN32 */
1077
static void sig_handler(gint signum)
1078
{
1079
        debug_print("signal %d received\n", signum);
1080
1081
        switch (signum) {
1082
        case SIGHUP:
1083
        case SIGINT:
1084
        case SIGTERM:
1085
        case SIGQUIT:
1086
                app_will_exit(TRUE);
1087
                break;
1088
        default:
1089
                break;
1090
        }
1091
}
1092
1093
static void register_system_events(void)
1094
{
1095
        struct sigaction sa;
1096
1097
        memset(&sa, 0, sizeof(sa));
1098
        sa.sa_handler = sig_handler;
1099
        sa.sa_flags = SA_RESTART;
1100
1101
        sigemptyset(&sa.sa_mask);
1102
        sigaddset(&sa.sa_mask, SIGHUP);
1103
        sigaddset(&sa.sa_mask, SIGINT);
1104
        sigaddset(&sa.sa_mask, SIGTERM);
1105
        sigaddset(&sa.sa_mask, SIGQUIT);
1106
        sigaddset(&sa.sa_mask, SIGPIPE);
1107
1108
        sigaction(SIGHUP, &sa, NULL);
1109
        sigaction(SIGINT, &sa, NULL);
1110
        sigaction(SIGTERM, &sa, NULL);
1111
        sigaction(SIGQUIT, &sa, NULL);
1112
        sigaction(SIGPIPE, &sa, NULL);
1113
}
1114
#endif
1115
1116
#define ADD_SYM(sym)        syl_plugin_add_symbol(#sym, sym)
1117
1118
static void plugin_init(void)
1119
{
1120
        MainWindow *mainwin;
1121
        gchar *path;
1122
1123
        mainwin = main_window_get();
1124
1125
        STATUSBAR_PUSH(mainwin, _("Loading plug-ins..."));
1126
1127
        if (syl_plugin_init_lib() != 0) {
1128
                STATUSBAR_POP(mainwin);
1129
                return;
1130
        }
1131
1132
        ADD_SYM(prog_version);
1133
        ADD_SYM(app_will_exit);
1134
1135
        ADD_SYM(main_window_lock);
1136
        ADD_SYM(main_window_unlock);
1137
        ADD_SYM(main_window_get);
1138
        ADD_SYM(main_window_popup);
1139
1140
        syl_plugin_add_symbol("main_window_menu_factory",
1141
                              mainwin->menu_factory);
1142
        syl_plugin_add_symbol("main_window_statusbar", mainwin->statusbar);
1143
1144
        ADD_SYM(folderview_get);
1145
        ADD_SYM(folderview_add_sub_widget);
1146
        ADD_SYM(folderview_select);
1147
        ADD_SYM(folderview_unselect);
1148
        ADD_SYM(folderview_select_next_unread);
1149
        ADD_SYM(folderview_get_selected_item);
1150
        ADD_SYM(folderview_check_new);
1151
        ADD_SYM(folderview_check_new_item);
1152
        ADD_SYM(folderview_check_new_all);
1153
        ADD_SYM(folderview_update_item);
1154
        ADD_SYM(folderview_update_item_foreach);
1155
        ADD_SYM(folderview_update_all_updated);
1156
        ADD_SYM(folderview_check_new_selected);
1157
1158
        syl_plugin_add_symbol("folderview_mail_popup_factory",
1159
                              mainwin->folderview->mail_factory);
1160
        syl_plugin_add_symbol("folderview_imap_popup_factory",
1161
                              mainwin->folderview->imap_factory);
1162
        syl_plugin_add_symbol("folderview_news_popup_factory",
1163
                              mainwin->folderview->news_factory);
1164
1165
        syl_plugin_add_symbol("summaryview", mainwin->summaryview);
1166
        syl_plugin_add_symbol("summaryview_popup_factory",
1167
                              mainwin->summaryview->popupfactory);
1168
1169
        ADD_SYM(summary_select_by_msgnum);
1170
        ADD_SYM(summary_select_by_msginfo);
1171
        ADD_SYM(summary_lock);
1172
        ADD_SYM(summary_unlock);
1173
        ADD_SYM(summary_is_locked);
1174
        ADD_SYM(summary_is_read_locked);
1175
        ADD_SYM(summary_write_lock);
1176
        ADD_SYM(summary_write_unlock);
1177
        ADD_SYM(summary_is_write_locked);
1178
        ADD_SYM(summary_get_selection_type);
1179
        ADD_SYM(summary_get_selected_msg_list);
1180
        ADD_SYM(summary_get_msg_list);
1181
        ADD_SYM(summary_show_queued_msgs);
1182
1183
        ADD_SYM(messageview_create_with_new_window);
1184
        ADD_SYM(messageview_show);
1185
1186
        ADD_SYM(compose_new);
1187
        ADD_SYM(compose_entry_set);
1188
        ADD_SYM(compose_entry_append);
1189
        ADD_SYM(compose_entry_get_text);
1190
        ADD_SYM(compose_lock);
1191
        ADD_SYM(compose_unlock);
1192
1193
        ADD_SYM(foldersel_folder_sel);
1194
        ADD_SYM(foldersel_folder_sel_full);
1195
1196
        ADD_SYM(input_dialog);
1197
        ADD_SYM(input_dialog_with_invisible);
1198
1199
        ADD_SYM(manage_window_set_transient);
1200
        ADD_SYM(manage_window_signals_connect);
1201
        ADD_SYM(manage_window_get_focus_window);
1202
1203
        ADD_SYM(inc_mail);
1204
        ADD_SYM(inc_is_active);
1205
        ADD_SYM(inc_lock);
1206
        ADD_SYM(inc_unlock);
1207
1208
#if USE_UPDATE_CHECK
1209
        ADD_SYM(update_check);
1210
        ADD_SYM(update_check_set_check_url);
1211
        ADD_SYM(update_check_get_check_url);
1212
        ADD_SYM(update_check_set_jump_url);
1213
        ADD_SYM(update_check_get_jump_url);
1214
#endif
1215
1216
        syl_plugin_signal_connect("plugin-load", G_CALLBACK(load_cb), NULL);
1217
1218
        /* loading plug-ins from user plug-in directory */
1219
        path = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, PLUGIN_DIR, NULL);
1220
        syl_plugin_load_all(path);
1221
        g_free(path);
1222
1223
        /* loading plug-ins from system plug-in directory */
1224
#ifdef G_OS_WIN32
1225
        path = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S, PLUGIN_DIR,
1226
                           NULL);
1227
        syl_plugin_load_all(path);
1228
        g_free(path);
1229
#else
1230
        syl_plugin_load_all(PLUGINDIR);
1231
#endif
1232
1233
        STATUSBAR_POP(mainwin);
1234
}
1235
1236
static gchar *get_socket_name(void)
1237
{
1238
        static gchar *filename = NULL;
1239
1240
        if (filename == NULL) {
1241
                filename = g_strdup_printf("%s%c%s-%d",
1242
                                           g_get_tmp_dir(), G_DIR_SEPARATOR,
1243
                                           instance_id ? instance_id : "sylpheed",
1244
#if HAVE_GETUID
1245
                                           getuid());
1246
#else
1247
                                           0);
1248
#endif
1249
        }
1250
1251
        return filename;
1252
}
1253
1254
static gint prohibit_duplicate_launch(void)
1255
{
1256
        gint sock;
1257
1258
#ifdef G_OS_WIN32
1259
        HANDLE hmutex;
1260
        const gchar *ins_id = instance_id ? instance_id : "Sylpheed";
1261
        gushort port = cmd.ipcport ? cmd.ipcport : REMOTE_CMD_PORT;
1262
1263
        debug_print("prohibit_duplicate_launch: checking mutex: %s\n", ins_id);
1264
        hmutex = CreateMutexA(NULL, FALSE, ins_id);
1265
        if (!hmutex) {
1266
                g_warning("cannot create Mutex: %s\n", ins_id);
1267
                return -1;
1268
        }
1269
        if (GetLastError() != ERROR_ALREADY_EXISTS) {
1270
                debug_print("prohibit_duplicate_launch: creating socket: port %d\n", port);
1271
                sock = fd_open_inet(port);
1272
                if (sock < 0)
1273
                        return 0;
1274
                return sock;
1275
        }
1276
1277
        debug_print("prohibit_duplicate_launch: connecting to socket: port %d\n", port);
1278
        sock = fd_connect_inet(port);
1279
        if (sock < 0)
1280
                return -1;
1281
#else
1282
        gchar *path;
1283
1284
        path = get_socket_name();
1285
        debug_print("prohibit_duplicate_launch: checking socket: %s\n", path);
1286
        sock = fd_connect_unix(path);
1287
        if (sock < 0) {
1288
                debug_print("prohibit_duplicate_launch: creating socket: %s\n", path);
1289
                g_unlink(path);
1290
                return fd_open_unix(path);
1291
        }
1292
#endif
1293
1294
        /* remote command mode */
1295
1296
        debug_print(_("another Sylpheed is already running.\n"));
1297
1298
        if (cmd.receive_all)
1299
                fd_write_all(sock, "receive_all\n", 12);
1300
        else if (cmd.receive)
1301
                fd_write_all(sock, "receive\n", 8);
1302
        else if (cmd.compose && cmd.attach_files) {
1303
                gchar *str, *compose_str;
1304
                gint i;
1305
1306
                if (cmd.compose_mailto)
1307
                        compose_str = g_strdup_printf("compose_attach %s\n",
1308
                                                      cmd.compose_mailto);
1309
                else
1310
                        compose_str = g_strdup("compose_attach\n");
1311
1312
                fd_write_all(sock, compose_str, strlen(compose_str));
1313
                g_free(compose_str);
1314
1315
                for (i = 0; i < cmd.attach_files->len; i++) {
1316
                        str = g_ptr_array_index(cmd.attach_files, i);
1317
                        fd_write_all(sock, str, strlen(str));
1318
                        fd_write_all(sock, "\n", 1);
1319
                }
1320
1321
                fd_write_all(sock, ".\n", 2);
1322
        } else if (cmd.compose) {
1323
                gchar *compose_str;
1324
1325
                if (cmd.compose_mailto)
1326
                        compose_str = g_strdup_printf
1327
                                ("compose %s\n", cmd.compose_mailto);
1328
                else
1329
                        compose_str = g_strdup("compose\n");
1330
1331
                fd_write_all(sock, compose_str, strlen(compose_str));
1332
                g_free(compose_str);
1333
        } else if (cmd.send) {
1334
                fd_write_all(sock, "send\n", 5);
1335
        } else if (cmd.status || cmd.status_full) {
1336
                gchar buf[BUFFSIZE];
1337
                gint i;
1338
                const gchar *command;
1339
                GPtrArray *folders;
1340
                gchar *folder;
1341
1342
                command = cmd.status_full ? "status-full\n" : "status\n";
1343
                folders = cmd.status_full ? cmd.status_full_folders :
1344
                        cmd.status_folders;
1345
1346
                fd_write_all(sock, command, strlen(command));
1347
                for (i = 0; folders && i < folders->len; ++i) {
1348
                        folder = g_ptr_array_index(folders, i);
1349
                        fd_write_all(sock, folder, strlen(folder));
1350
                        fd_write_all(sock, "\n", 1);
1351
                }
1352
                fd_write_all(sock, ".\n", 2);
1353
                for (;;) {
1354
                        fd_gets(sock, buf, sizeof(buf));
1355
                        if (!strncmp(buf, ".\n", 2)) break;
1356
                        fputs(buf, stdout);
1357
                }
1358
        } else if (cmd.open_msg) {
1359
                gchar *str;
1360
1361
                str = g_strdup_printf("open %s\n", cmd.open_msg);
1362
                fd_write_all(sock, str, strlen(str));
1363
                g_free(str);
1364
        } else if (cmd.exit) {
1365
                fd_write_all(sock, "exit\n", 5);
1366
        } else {
1367
#ifdef G_OS_WIN32
1368
                HWND hwnd;
1369
1370
                fd_write_all(sock, "popup\n", 6);
1371
                if (fd_read(sock, (gchar *)&hwnd, sizeof(hwnd)) == sizeof(hwnd))
1372
                        SetForegroundWindow(hwnd);
1373
#else
1374
                fd_write_all(sock, "popup\n", 6);
1375
#endif
1376
        }
1377
1378
        fd_close(sock);
1379
        return -1;
1380
}
1381
1382
static gint lock_socket_remove(void)
1383
{
1384
#ifndef G_OS_WIN32
1385
        gchar *filename;
1386
#endif
1387
1388
        if (lock_socket < 0) return -1;
1389
1390
        if (lock_socket_tag > 0)
1391
                g_source_remove(lock_socket_tag);
1392
        if (lock_ch) {
1393
                g_io_channel_shutdown(lock_ch, FALSE, NULL);
1394
                g_io_channel_unref(lock_ch);
1395
                lock_ch = NULL;
1396
        }
1397
1398
#ifndef G_OS_WIN32
1399
        filename = get_socket_name();
1400
        debug_print("lock_socket_remove: removing socket: %s\n", filename);
1401
        g_unlink(filename);
1402
#endif
1403
1404
        return 0;
1405
}
1406
1407
static GPtrArray *get_folder_item_list(gint sock)
1408
{
1409
        gchar buf[BUFFSIZE];
1410
        FolderItem *item;
1411
        GPtrArray *folders = NULL;
1412
1413
        for (;;) {
1414
                fd_gets(sock, buf, sizeof(buf));
1415
                if (!strncmp(buf, ".\n", 2)) break;
1416
                strretchomp(buf);
1417
                if (!folders) folders = g_ptr_array_new();
1418
                item = folder_find_item_from_identifier(buf);
1419
                if (item)
1420
                        g_ptr_array_add(folders, item);
1421
                else
1422
                        g_warning("no such folder: %s\n", buf);
1423
        }
1424
1425
        return folders;
1426
}
1427
1428
static gboolean lock_socket_input_cb(GIOChannel *source, GIOCondition condition,
1429
                                     gpointer data)
1430
{
1431
        MainWindow *mainwin = (MainWindow *)data;
1432
        gint fd, sock;
1433
        gchar buf[BUFFSIZE];
1434
1435
#if USE_THREADS
1436
        gdk_threads_enter();
1437
#endif
1438
1439
        fd = g_io_channel_unix_get_fd(source);
1440
        sock = fd_accept(fd);
1441
        fd_gets(sock, buf, sizeof(buf));
1442
1443
        if (!strncmp(buf, "popup", 5)) {
1444
#ifdef G_OS_WIN32
1445
                HWND hwnd;
1446
1447
                hwnd = (HWND)gdk_win32_drawable_get_handle
1448
                        (GDK_DRAWABLE(mainwin->window->window));
1449
                fd_write(sock, (gchar *)&hwnd, sizeof(hwnd));
1450
                if (mainwin->window_hidden)
1451
                        main_window_popup(mainwin);
1452
#else
1453
                main_window_popup(mainwin);
1454
#endif
1455
        } else if (!strncmp(buf, "receive_all", 11)) {
1456
                main_window_popup(mainwin);
1457
                if (!gtkut_window_modal_exist())
1458
                        inc_all_account_mail(mainwin, FALSE);
1459
        } else if (!strncmp(buf, "receive", 7)) {
1460
                main_window_popup(mainwin);
1461
                if (!gtkut_window_modal_exist())
1462
                        inc_mail(mainwin);
1463
        } else if (!strncmp(buf, "compose_attach", 14)) {
1464
                GPtrArray *files;
1465
                gchar *mailto;
1466
1467
                mailto = g_strdup(buf + strlen("compose_attach") + 1);
1468
                files = g_ptr_array_new();
1469
                while (fd_gets(sock, buf, sizeof(buf)) > 0) {
1470
                        if (buf[0] == '.' && buf[1] == '\n') break;
1471
                        strretchomp(buf);
1472
                        g_ptr_array_add(files, g_strdup(buf));
1473
                }
1474
                open_compose_new(mailto, files);
1475
                ptr_array_free_strings(files);
1476
                g_ptr_array_free(files, TRUE);
1477
                g_free(mailto);
1478
        } else if (!strncmp(buf, "compose", 7)) {
1479
                open_compose_new(buf + strlen("compose") + 1, NULL);
1480
        } else if (!strncmp(buf, "send", 4)) {
1481
                send_queue();
1482
        } else if (!strncmp(buf, "status-full", 11) ||
1483
                   !strncmp(buf, "status", 6)) {
1484
                gchar *status;
1485
                GPtrArray *folders;
1486
1487
                folders = get_folder_item_list(sock);
1488
                status = folder_get_status
1489
                        (folders, !strncmp(buf, "status-full", 11));
1490
                fd_write_all(sock, status, strlen(status));
1491
                fd_write_all(sock, ".\n", 2);
1492
                g_free(status);
1493
                if (folders) g_ptr_array_free(folders, TRUE);
1494
        } else if (!strncmp(buf, "open", 4)) {
1495
                strretchomp(buf);
1496
                if (strlen(buf) < 6 || buf[4] != ' ') {
1497
                        fd_close(sock);
1498
#if USE_THREADS
1499
                        gdk_threads_leave();
1500
#endif
1501
                        return TRUE;
1502
                }
1503
                open_message(buf + 5);
1504
        } else if (!strncmp(buf, "exit", 4)) {
1505
                fd_close(sock);
1506
                app_will_exit(TRUE);
1507
        }
1508
1509
        fd_close(sock);
1510
1511
#if USE_THREADS
1512
        gdk_threads_leave();
1513
#endif
1514
1515
        return TRUE;
1516
}
1517
1518
static void remote_command_exec(void)
1519
{
1520
        MainWindow *mainwin;
1521
1522
        mainwin = main_window_get();
1523
1524
        if (prefs_common.open_inbox_on_startup) {
1525
                FolderItem *item;
1526
                item = cur_account && cur_account->inbox
1527
                        ? folder_find_item_from_identifier(cur_account->inbox)
1528
                        : folder_get_default_inbox();
1529
                folderview_select(mainwin->folderview, item);
1530
        }
1531
1532
        if (!gtkut_window_modal_exist()) {
1533
                if (cmd.receive_all)
1534
                        inc_all_account_mail(mainwin, FALSE);
1535
                else if (prefs_common.chk_on_startup)
1536
                        inc_all_account_mail(mainwin, TRUE);
1537
                else if (cmd.receive)
1538
                        inc_mail(mainwin);
1539
1540
                if (cmd.compose)
1541
                        open_compose_new(cmd.compose_mailto, cmd.attach_files);
1542
1543
                if (cmd.send)
1544
                        send_queue();
1545
1546
                if (cmd.open_msg)
1547
                        open_message(cmd.open_msg);
1548
        }
1549
1550
        if (cmd.attach_files) {
1551
                ptr_array_free_strings(cmd.attach_files);
1552
                g_ptr_array_free(cmd.attach_files, TRUE);
1553
                cmd.attach_files = NULL;
1554
        }
1555
        if (cmd.status_folders) {
1556
                g_ptr_array_free(cmd.status_folders, TRUE);
1557
                cmd.status_folders = NULL;
1558
        }
1559
        if (cmd.status_full_folders) {
1560
                g_ptr_array_free(cmd.status_full_folders, TRUE);
1561
                cmd.status_full_folders = NULL;
1562
        }
1563
        if (cmd.open_msg) {
1564
                g_free(cmd.open_msg);
1565
                cmd.open_msg = NULL;
1566
        }
1567
        if (cmd.exit) {
1568
                app_will_exit(TRUE);
1569
        }
1570
}
1571
1572
static void migrate_old_config(void)
1573
{
1574
        GDir *dir;
1575
        const gchar *dir_name;
1576
        GPatternSpec *pspec;
1577
1578
        if (alertpanel(_("Migration of configuration"),
1579
                       _("The previous version of configuration found.\n"
1580
                         "Do you want to migrate it?"),
1581
                       GTK_STOCK_YES, GTK_STOCK_NO, NULL) != G_ALERTDEFAULT)
1582
                return;
1583
1584
        debug_print("Migrating old configuration...\n");
1585
1586
#define COPY_FILE(rcfile)                                                \
1587
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile)) {        \
1588
                conv_copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile,        \
1589
                               RC_DIR G_DIR_SEPARATOR_S rcfile,                \
1590
                               conv_get_locale_charset_str());                \
1591
        }
1592
1593
        COPY_FILE(ACCOUNT_RC);
1594
        COPY_FILE(ACTIONS_RC);
1595
        COPY_FILE(COMMON_RC);
1596
        COPY_FILE(CUSTOM_HEADER_RC);
1597
        COPY_FILE(DISPLAY_HEADER_RC);
1598
        COPY_FILE(FILTER_HEADER_RC);
1599
        COPY_FILE(COMMAND_HISTORY);
1600
1601
#undef COPY_FILE
1602
1603
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST))
1604
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST,
1605
                          RC_DIR G_DIR_SEPARATOR_S FILTER_LIST, FALSE);
1606
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST))
1607
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST,
1608
                          RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST, FALSE);
1609
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types"))
1610
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types",
1611
                          RC_DIR G_DIR_SEPARATOR_S "mime.types", FALSE);
1612
1613
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR))
1614
                conv_copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1615
                              RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1616
                              conv_get_locale_charset_str());
1617
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR))
1618
                copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR,
1619
                         RC_DIR G_DIR_SEPARATOR_S UIDL_DIR);
1620
1621
        if (!is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S ADDRESSBOOK_INDEX_FILE))
1622
                return;
1623
1624
        if ((dir = g_dir_open(OLD_RC_DIR, 0, NULL)) == NULL) {
1625
                g_warning("failed to open directory: %s\n", OLD_RC_DIR);
1626
                return;
1627
        }
1628
1629
        pspec = g_pattern_spec_new("addrbook-*.xml");
1630
1631
        while ((dir_name = g_dir_read_name(dir)) != NULL) {
1632
                if (g_pattern_match_string(pspec, dir_name)) {
1633
                        gchar *old_file;
1634
                        gchar *new_file;
1635
1636
                        old_file = g_strconcat(OLD_RC_DIR G_DIR_SEPARATOR_S,
1637
                                               dir_name, NULL);
1638
                        new_file = g_strconcat(RC_DIR G_DIR_SEPARATOR_S,
1639
                                               dir_name, NULL);
1640
                        copy_file(old_file, new_file, FALSE);
1641
                        g_free(new_file);
1642
                        g_free(old_file);
1643
                }
1644
        }
1645
1646
        g_pattern_spec_free(pspec);
1647
        g_dir_close(dir);
1648
}
1649
1650
static void open_compose_new(const gchar *address, GPtrArray *attach_files)
1651
{
1652
        gchar *utf8addr = NULL;
1653
#ifdef G_OS_WIN32
1654
        GPtrArray *utf8files = NULL;
1655
#endif
1656
1657
        if (gtkut_window_modal_exist())
1658
                return;
1659
1660
        if (address) {
1661
                utf8addr = g_locale_to_utf8(address, -1, NULL, NULL, NULL);
1662
                if (utf8addr)
1663
                        g_strstrip(utf8addr);
1664
        }
1665
1666
#ifdef G_OS_WIN32
1667
        if (attach_files) {
1668
                gint i;
1669
                gchar *file, *utf8file;
1670
1671
                utf8files = g_ptr_array_new();
1672
                for (i = 0; i < attach_files->len; i++) {
1673
                        file = g_ptr_array_index(attach_files, i);
1674
                        utf8file = g_locale_to_utf8(file, -1, NULL, NULL, NULL);
1675
                        if (utf8file)
1676
                                g_ptr_array_add(utf8files, utf8file);
1677
                }
1678
        }
1679
1680
        compose_new(NULL, NULL, utf8addr, utf8files);
1681
        if (utf8files) {
1682
                ptr_array_free_strings(utf8files);
1683
                g_ptr_array_free(utf8files, TRUE);
1684
        }
1685
#else
1686
        compose_new(NULL, NULL, utf8addr, attach_files);
1687
#endif
1688
1689
        g_free(utf8addr);
1690
}
1691
1692
static void open_message(const gchar *path)
1693
{
1694
        gchar *id;
1695
        gchar *msg;
1696
        gint num;
1697
        FolderItem *item;
1698
        MsgInfo *msginfo;
1699
        MessageView *msgview;
1700
1701
        if (gtkut_window_modal_exist())
1702
                return;
1703
1704
        id = g_path_get_dirname(path);
1705
        msg = g_path_get_basename(path);
1706
        num = to_number(msg);
1707
        item = folder_find_item_from_identifier(id);
1708
        debug_print("open folder id: %s (msg %d)\n", id, num);
1709
1710
        if (num > 0 && item) {
1711
                msginfo = folder_item_get_msginfo(item, num);
1712
                if (msginfo) {
1713
                        msgview = messageview_create_with_new_window();
1714
                        messageview_show(msgview, msginfo, FALSE);
1715
                        procmsg_msginfo_free(msginfo);
1716
                } else
1717
                        debug_print("message %d not found\n", num);
1718
        }
1719
1720
        g_free(msg);
1721
        g_free(id);
1722
}
1723
1724
static void send_queue(void)
1725
{
1726
        GList *list;
1727
1728
        if (gtkut_window_modal_exist())
1729
                return;
1730
        if (!main_window_toggle_online_if_offline(main_window_get()))
1731
                return;
1732
1733
        for (list = folder_get_list(); list != NULL; list = list->next) {
1734
                Folder *folder = list->data;
1735
1736
                if (folder->queue) {
1737
                        gint ret;
1738
1739
                        ret = send_message_queue_all(folder->queue,
1740
                                                     prefs_common.savemsg,
1741
                                                     prefs_common.filter_sent);
1742
                        statusbar_pop_all();
1743
                        if (ret > 0)
1744
                                folder_item_scan(folder->queue);
1745
                }
1746
        }
1747
1748
        folderview_update_all_updated(TRUE);
1749
        main_window_set_menu_sensitive(main_window_get());
1750
        main_window_set_toolbar_sensitive(main_window_get());
1751
}