Statistics
| Revision:

root / src / main.c @ 686

History | View | Annotate | Download (26.8 kB)

1
/*
2
 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3
 * Copyright (C) 1999-2005 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 "utils.h"
79
#include "gtkutils.h"
80
#include "socket.h"
81
#include "stock_pixmap.h"
82
83
#if USE_GPGME
84
#  include "rfc2015.h"
85
#endif
86
#if USE_SSL
87
#  include "ssl.h"
88
#endif
89
90
#ifdef G_OS_WIN32
91
#  include <windows.h>
92
#endif
93
94
#include "version.h"
95
96
gchar *prog_version;
97
98
static gint lock_socket = -1;
99
static gint lock_socket_tag = 0;
100
static GIOChannel *lock_ch = NULL;
101
102
static struct RemoteCmd {
103
        gboolean receive;
104
        gboolean receive_all;
105
        gboolean compose;
106
        const gchar *compose_mailto;
107
        GPtrArray *attach_files;
108
        gboolean send;
109
        gboolean status;
110
        gboolean status_full;
111
        GPtrArray *status_folders;
112
        GPtrArray *status_full_folders;
113
        gboolean configdir;
114
} cmd;
115
116
static void parse_cmd_opt                (int                 argc,
117
                                         char                *argv[]);
118
119
static void app_init                        (void);
120
static void parse_gtkrc_files                (void);
121
static void setup_rc_dir                (void);
122
static void check_gpg                        (void);
123
static void set_log_handlers                (gboolean         enable);
124
125
static gchar *get_socket_name                (void);
126
static gint prohibit_duplicate_launch        (void);
127
static gint lock_socket_remove                (void);
128
static gboolean lock_socket_input_cb        (GIOChannel        *source,
129
                                         GIOCondition         condition,
130
                                         gpointer         data);
131
132
static void remote_command_exec                (void);
133
static void migrate_old_config                (void);
134
135
static void open_compose_new                (const gchar        *address,
136
                                         GPtrArray        *attach_files);
137
138
static void send_queue                        (void);
139
140
#define MAKE_DIR_IF_NOT_EXIST(dir)                                        \
141
{                                                                        \
142
        if (!is_dir_exist(dir)) {                                        \
143
                if (is_file_exist(dir)) {                                \
144
                        alertpanel_warning                                \
145
                                (_("File `%s' already exists.\n"        \
146
                                   "Can't create folder."),                \
147
                                 dir);                                        \
148
                        exit(1);                                        \
149
                }                                                        \
150
                if (make_dir(dir) < 0)                                        \
151
                        exit(1);                                        \
152
        }                                                                \
153
}
154
155
#define CHDIR_EXIT_IF_FAIL(dir, val)        \
156
{                                        \
157
        if (change_dir(dir) < 0)        \
158
                exit(val);                \
159
}
160
161
162
int main(int argc, char *argv[])
163
{
164
        MainWindow *mainwin;
165
        FolderView *folderview;
166
        GdkPixbuf *icon;
167
168
        app_init();
169
        parse_cmd_opt(argc, argv);
170
171
        /* check and create unix domain socket for remote operation */
172
        lock_socket = prohibit_duplicate_launch();
173
        if (lock_socket < 0) return 0;
174
175
#ifdef G_OS_UNIX
176
        if (cmd.status || cmd.status_full) {
177
                puts("0 Sylpheed not running.");
178
                lock_socket_remove();
179
                return 0;
180
        }
181
#endif
182
183
        gtk_set_locale();
184
        gtk_init(&argc, &argv);
185
186
        gdk_rgb_init();
187
        gtk_widget_set_default_colormap(gdk_rgb_get_cmap());
188
        gtk_widget_set_default_visual(gdk_rgb_get_visual());
189
190
#if USE_THREADS || USE_LDAP
191
        g_thread_init(NULL);
192
        if (!g_thread_supported())
193
                g_error(_("g_thread is not supported by glib.\n"));
194
#endif
195
196
        parse_gtkrc_files();
197
        setup_rc_dir();
198
199
        if (is_file_exist("sylpheed.log")) {
200
                if (rename_force("sylpheed.log", "sylpheed.log.bak") < 0)
201
                        FILE_OP_ERROR("sylpheed.log", "rename");
202
        }
203
        set_log_file("sylpheed.log");
204
205
        set_ui_update_func(gtkut_events_flush);
206
        set_progress_func(main_window_progress_show);
207
        set_input_query_password_func(input_dialog_query_password);
208
209
        CHDIR_EXIT_IF_FAIL(get_home_dir(), 1);
210
211
        prefs_common_read_config();
212
        filter_read_config();
213
        prefs_actions_read_config();
214
        prefs_display_header_read_config();
215
216
        gtkut_stock_button_set_set_reverse(!prefs_common.comply_gnome_hig);
217
218
        check_gpg();
219
220
        sock_set_io_timeout(prefs_common.io_timeout_secs);
221
222
        gtkut_widget_init();
223
        stock_pixbuf_gdk(NULL, STOCK_PIXMAP_SYLPHEED, &icon);
224
        gtk_window_set_default_icon(icon);
225
226
        mainwin = main_window_create
227
                (prefs_common.sep_folder | prefs_common.sep_msg << 1);
228
        folderview = mainwin->folderview;
229
230
#ifdef G_OS_UNIX
231
        /* register the callback of unix domain socket input */
232
        lock_ch = g_io_channel_unix_new(lock_socket);
233
        lock_socket_tag = g_io_add_watch(lock_ch,
234
                                         G_IO_IN|G_IO_PRI|G_IO_ERR,
235
                                         lock_socket_input_cb, mainwin);
236
#endif
237
238
        set_log_handlers(TRUE);
239
240
        account_read_config_all();
241
        account_set_menu();
242
        main_window_reflect_prefs_all();
243
244
        if (folder_read_list() < 0) {
245
                setup(mainwin);
246
                folder_write_list();
247
        }
248
        if (!account_get_list()) {
249
                account_edit_open();
250
                account_add();
251
        }
252
253
        account_set_missing_folder();
254
        folder_set_missing_folders();
255
        folderview_set(folderview);
256
257
        addressbook_read_file();
258
259
        inc_autocheck_timer_init(mainwin);
260
261
        remote_command_exec();
262
263
        gtk_main();
264
265
        return 0;
266
}
267
268
static void parse_cmd_opt(int argc, char *argv[])
269
{
270
        gint i;
271
272
        for (i = 1; i < argc; i++) {
273
                if (!strncmp(argv[i], "--debug", 7))
274
                        set_debug_mode(TRUE);
275
                else if (!strncmp(argv[i], "--receive-all", 13))
276
                        cmd.receive_all = TRUE;
277
                else if (!strncmp(argv[i], "--receive", 9))
278
                        cmd.receive = TRUE;
279
                else if (!strncmp(argv[i], "--compose", 9)) {
280
                        const gchar *p = argv[i + 1];
281
282
                        cmd.compose = TRUE;
283
                        cmd.compose_mailto = NULL;
284
                        if (p && *p != '\0' && *p != '-') {
285
                                if (!strncmp(p, "mailto:", 7))
286
                                        cmd.compose_mailto = p + 7;
287
                                else
288
                                        cmd.compose_mailto = p;
289
                                i++;
290
                        }
291
                } else if (!strncmp(argv[i], "--attach", 8)) {
292
                        const gchar *p = argv[i + 1];
293
                        gchar *file;
294
295
                        while (p && *p != '\0' && *p != '-') {
296
                                if (!cmd.attach_files)
297
                                        cmd.attach_files = g_ptr_array_new();
298
                                if (*p != G_DIR_SEPARATOR)
299
                                        file = g_strconcat(get_startup_dir(),
300
                                                           G_DIR_SEPARATOR_S,
301
                                                           p, NULL);
302
                                else
303
                                        file = g_strdup(p);
304
                                g_ptr_array_add(cmd.attach_files, file);
305
                                i++;
306
                                p = argv[i + 1];
307
                        }
308
                } else if (!strncmp(argv[i], "--send", 6)) {
309
                        cmd.send = TRUE;
310
                } else if (!strncmp(argv[i], "--version", 9)) {
311
                        puts("Sylpheed version " VERSION);
312
                        exit(0);
313
                } else if (!strncmp(argv[i], "--status-full", 13)) {
314
                        const gchar *p = argv[i + 1];
315
316
                        cmd.status_full = TRUE;
317
                        while (p && *p != '\0' && *p != '-') {
318
                                if (!cmd.status_full_folders)
319
                                        cmd.status_full_folders =
320
                                                g_ptr_array_new();
321
                                g_ptr_array_add(cmd.status_full_folders,
322
                                                g_strdup(p));
323
                                i++;
324
                                p = argv[i + 1];
325
                        }
326
                } else if (!strncmp(argv[i], "--status", 8)) {
327
                        const gchar *p = argv[i + 1];
328
329
                        cmd.status = TRUE;
330
                        while (p && *p != '\0' && *p != '-') {
331
                                if (!cmd.status_folders)
332
                                        cmd.status_folders = g_ptr_array_new();
333
                                g_ptr_array_add(cmd.status_folders,
334
                                                g_strdup(p));
335
                                i++;
336
                                p = argv[i + 1];
337
                        }
338
                } else if (!strncmp(argv[i], "--configdir", 11)) {
339
                        const gchar *p = argv[i + 1];
340
341
                        if (p && *p != '\0' && *p != '-') {
342
                                /* this must only be done at startup */
343
#ifdef G_OS_WIN32
344
                                gchar *utf8dir;
345
346
                                utf8dir = g_locale_to_utf8
347
                                        (p, -1, NULL, NULL, NULL);
348
                                if (utf8dir) {
349
                                        set_rc_dir(utf8dir);
350
                                        g_free(utf8dir);
351
                                } else
352
                                        set_rc_dir(p);
353
#else
354
                                set_rc_dir(p);
355
#endif
356
                                cmd.configdir = TRUE;
357
                                i++;
358
                        }
359
                } else if (!strncmp(argv[i], "--help", 6)) {
360
                        g_print(_("Usage: %s [OPTION]...\n"),
361
                                g_basename(argv[0]));
362
363
                        g_print("%s\n", _("  --compose [address]    open composition window"));
364
                        g_print("%s\n", _("  --attach file1 [file2]...\n"
365
                                "                         open composition window with specified files\n"
366
                                "                         attached"));
367
                        g_print("%s\n", _("  --receive              receive new messages"));
368
                        g_print("%s\n", _("  --receive-all          receive new messages of all accounts"));
369
                        g_print("%s\n", _("  --send                 send all queued messages"));
370
                        g_print("%s\n", _("  --status [folder]...   show the total number of messages"));
371
                        g_print("%s\n", _("  --status-full [folder]...\n"
372
                                "                         show the status of each folder"));
373
                        g_print("%s\n", _("  --configdir dirname    specify directory which stores configuration files"));
374
                        g_print("%s\n", _("  --debug                debug mode"));
375
                        g_print("%s\n", _("  --help                 display this help and exit"));
376
                        g_print("%s\n", _("  --version              output version information and exit"));
377
378
                        exit(1);
379
                }
380
        }
381
382
        if (cmd.attach_files && cmd.compose == FALSE) {
383
                cmd.compose = TRUE;
384
                cmd.compose_mailto = NULL;
385
        }
386
}
387
388
static gint get_queued_message_num(void)
389
{
390
        FolderItem *queue;
391
392
        queue = folder_get_default_queue();
393
        if (!queue) return -1;
394
395
        folder_item_scan(queue);
396
        return queue->total;
397
}
398
399
static void app_init(void)
400
{
401
#ifdef G_OS_WIN32
402
        gchar *newpath;
403
#endif
404
405
        setlocale(LC_ALL, "");
406
407
        prog_version = PROG_VERSION;
408
        set_startup_dir();
409
410
#ifdef G_OS_WIN32
411
        /* include startup directory into %PATH% for GSpawn */
412
        newpath = g_strconcat(get_startup_dir(), ";", g_getenv("PATH"), NULL);
413
        g_setenv("PATH", newpath, TRUE);
414
        g_free(newpath);
415
#endif
416
417
        if (g_path_is_absolute(LOCALEDIR))
418
                bindtextdomain(PACKAGE, LOCALEDIR);
419
        else {
420
                gchar *locale_dir;
421
422
                locale_dir = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S,
423
                                         LOCALEDIR, NULL);
424
#ifdef G_OS_WIN32
425
                {
426
                        gchar *locale_dir_;
427
428
                        locale_dir_ = g_locale_from_utf8(locale_dir, -1,
429
                                                         NULL, NULL, NULL);
430
                        if (locale_dir_) {
431
                                g_free(locale_dir);
432
                                locale_dir = locale_dir_;
433
                        }
434
                }
435
#endif
436
                bindtextdomain(PACKAGE, locale_dir);
437
                g_free(locale_dir);
438
        }
439
440
        bind_textdomain_codeset(PACKAGE, CS_UTF_8);
441
        textdomain(PACKAGE);
442
443
        sock_init();
444
#if USE_SSL
445
        ssl_init();
446
#endif
447
448
#ifdef G_OS_UNIX
449
        /* ignore SIGPIPE signal for preventing sudden death of program */
450
        signal(SIGPIPE, SIG_IGN);
451
#endif
452
}
453
454
static void parse_gtkrc_files(void)
455
{
456
        gchar *userrc;
457
458
        /* parse gtkrc files */
459
        userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtkrc-2.0",
460
                             NULL);
461
        gtk_rc_parse(userrc);
462
        g_free(userrc);
463
        userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtk",
464
                             G_DIR_SEPARATOR_S, "gtkrc-2.0", NULL);
465
        gtk_rc_parse(userrc);
466
        g_free(userrc);
467
        userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, "gtkrc", NULL);
468
        gtk_rc_parse(userrc);
469
        g_free(userrc);
470
471
        userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
472
        gtk_accel_map_load(userrc);
473
        g_free(userrc);
474
}
475
476
static void setup_rc_dir(void)
477
{
478
#ifndef G_OS_WIN32
479
        CHDIR_EXIT_IF_FAIL(get_home_dir(), 1);
480
481
        /* backup if old rc file exists */
482
        if (!cmd.configdir && is_file_exist(RC_DIR)) {
483
                if (rename_force(RC_DIR, RC_DIR ".bak") < 0)
484
                        FILE_OP_ERROR(RC_DIR, "rename");
485
        }
486
487
        /* migration from ~/.sylpheed to ~/.sylpheed-2.0 */
488
        if (!cmd.configdir && !is_dir_exist(RC_DIR)) {
489
                const gchar *envstr;
490
                AlertValue val;
491
492
                /* check for filename encoding */
493
                if (conv_get_locale_charset() != C_UTF_8) {
494
                        envstr = g_getenv("G_FILENAME_ENCODING");
495
                        if (!envstr)
496
                                envstr = g_getenv("G_BROKEN_FILENAMES");
497
                        if (!envstr) {
498
                                val = alertpanel(_("Filename encoding"),
499
                                                 _("The locale encoding is not UTF-8, but the environmental variable G_FILENAME_ENCODING is not set.\n"
500
                                                   "If the locale encoding is used for file name or directory name, it will not work correctly.\n"
501
                                                   "In that case, you must set the following environmental variable (see README for detail):\n"
502
                                                   "\n"
503
                                                   "\tG_FILENAME_ENCODING=@locale\n"
504
                                                   "\n"
505
                                                   "Continue?"),
506
                                                 GTK_STOCK_OK, GTK_STOCK_QUIT,
507
                                                 NULL);
508
                                if (G_ALERTDEFAULT != val)
509
                                        exit(1);
510
                        }
511
                }
512
513
                if (make_dir(RC_DIR) < 0)
514
                        exit(1);
515
                if (is_dir_exist(OLD_RC_DIR))
516
                        migrate_old_config();
517
        }
518
#endif /* !G_OS_WIN32 */
519
520
        if (!is_dir_exist(get_rc_dir())) {
521
                if (make_dir_hier(get_rc_dir()) < 0)
522
                        exit(1);
523
        }
524
525
        MAKE_DIR_IF_NOT_EXIST(get_mail_base_dir());
526
527
        CHDIR_EXIT_IF_FAIL(get_rc_dir(), 1);
528
529
        MAKE_DIR_IF_NOT_EXIST(get_imap_cache_dir());
530
        MAKE_DIR_IF_NOT_EXIST(get_news_cache_dir());
531
        MAKE_DIR_IF_NOT_EXIST(get_mime_tmp_dir());
532
        MAKE_DIR_IF_NOT_EXIST(get_tmp_dir());
533
        MAKE_DIR_IF_NOT_EXIST(UIDL_DIR);
534
535
        /* remove temporary files */
536
        remove_all_files(get_tmp_dir());
537
        remove_all_files(get_mime_tmp_dir());
538
}
539
540
void app_will_exit(GtkWidget *widget, gpointer data)
541
{
542
        MainWindow *mainwin = data;
543
        gchar *filename;
544
545
        if (compose_get_compose_list()) {
546
                if (alertpanel(_("Notice"),
547
                               _("Composing message exists. Really quit?"),
548
                               GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL)
549
                    != G_ALERTDEFAULT)
550
                        return;
551
                manage_window_focus_in(mainwin->window, NULL, NULL);
552
        }
553
554
        if (prefs_common.warn_queued_on_exit && get_queued_message_num() > 0) {
555
                if (alertpanel(_("Queued messages"),
556
                               _("Some unsent messages are queued. Exit now?"),
557
                               GTK_STOCK_OK, GTK_STOCK_CANCEL, NULL)
558
                    != G_ALERTDEFAULT)
559
                        return;
560
                manage_window_focus_in(mainwin->window, NULL, NULL);
561
        }
562
563
        inc_autocheck_timer_remove();
564
565
        if (prefs_common.clean_on_exit)
566
                main_window_empty_trash(mainwin, prefs_common.ask_on_clean);
567
568
        /* save all state before exiting */
569
        folder_write_list();
570
        summary_write_cache(mainwin->summaryview);
571
572
        main_window_get_size(mainwin);
573
        main_window_get_position(mainwin);
574
        prefs_common_write_config();
575
        filter_write_config();
576
        account_write_config_all();
577
        addressbook_export_to_file();
578
579
        filename = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
580
        gtk_accel_map_save(filename);
581
        g_free(filename);
582
583
        /* remove temporary files */
584
        remove_all_files(get_tmp_dir());
585
        remove_all_files(get_mime_tmp_dir());
586
587
        set_log_handlers(FALSE);
588
        close_log_file();
589
        lock_socket_remove();
590
591
#if USE_SSL
592
        ssl_done();
593
#endif
594
595
        sock_cleanup();
596
597
        gtk_main_quit();
598
}
599
600
#if 0
601
#if USE_GPGME
602
static void idle_function_for_gpgme(void)
603
{
604
        while (gtk_events_pending())
605
                gtk_main_iteration();
606
}
607
#endif /* USE_GPGME */
608
#endif /* 0 */
609
610
static void check_gpg(void)
611
{
612
#if USE_GPGME
613
        if (gpgme_check_version("0.4.5")) {
614
                /* Also does some gpgme init */
615
                gpgme_engine_info_t engineInfo;
616
617
                rfc2015_disable_all();
618
619
                gpgme_set_locale(NULL, LC_CTYPE, setlocale(LC_CTYPE, NULL));
620
                gpgme_set_locale(NULL, LC_MESSAGES,
621
                                 setlocale(LC_MESSAGES, NULL));
622
623
                if (!gpgme_get_engine_info(&engineInfo)) {
624
                        while (engineInfo) {
625
                                debug_print("GpgME Protocol: %s\n      Version: %s\n",
626
                                            gpgme_get_protocol_name
627
                                                (engineInfo->protocol),
628
                                            engineInfo->version ?
629
                                            engineInfo->version : "(unknown)");
630
                                engineInfo = engineInfo->next;
631
                        }
632
                }
633
634
                procmsg_set_decrypt_message_func
635
                        (rfc2015_open_message_decrypted);
636
        } else {
637
                if (prefs_common.gpg_warning) {
638
                        AlertValue val;
639
640
                        val = alertpanel_message_with_disable
641
                                (_("Warning"),
642
                                 _("GnuPG is not installed properly, or its version is too old.\n"
643
                                   "OpenPGP support disabled."),
644
                                 ALERT_WARNING);
645
                        if (val & G_ALERTDISABLE)
646
                                prefs_common.gpg_warning = FALSE;
647
                }
648
        }
649
        /* FIXME: This function went away.  We can either block until gpgme
650
         * operations finish (currently implemented) or register callbacks
651
         * with the gtk main loop via the gpgme io callback interface instead.
652
         *
653
         * gpgme_register_idle(idle_function_for_gpgme);
654
         */
655
#endif
656
}
657
658
static void default_log_func(const gchar *log_domain, GLogLevelFlags log_level,
659
                             const gchar *message, gpointer user_data)
660
{
661
        gchar *prefix = "";
662
        gchar *file_prefix = "";
663
        LogType level = LOG_NORMAL;
664
        gchar *str;
665
        const gchar *message_;
666
667
        switch (log_level) {
668
        case G_LOG_LEVEL_ERROR:
669
                prefix = "ERROR";
670
                file_prefix = "*** ";
671
                level = LOG_ERROR;
672
                break;
673
        case G_LOG_LEVEL_CRITICAL:
674
                prefix = "CRITICAL";
675
                file_prefix = "** ";
676
                level = LOG_WARN;
677
                break;
678
        case G_LOG_LEVEL_WARNING:
679
                prefix = "WARNING";
680
                file_prefix = "** ";
681
                level = LOG_WARN;
682
                break;
683
        case G_LOG_LEVEL_MESSAGE:
684
                prefix = "Message";
685
                file_prefix = "* ";
686
                level = LOG_MSG;
687
                break;
688
        case G_LOG_LEVEL_INFO:
689
                prefix = "INFO";
690
                file_prefix = "* ";
691
                level = LOG_MSG;
692
                break;
693
        case G_LOG_LEVEL_DEBUG:
694
                prefix = "DEBUG";
695
                break;
696
        default:
697
                prefix = "LOG";
698
                break;
699
        }
700
701
        if (!message)
702
                message_ = "(NULL) message";
703
        else
704
                message_ = message;
705
        if (log_domain)
706
                str = g_strconcat(log_domain, "-", prefix, ": ", message_, "\n",
707
                                  NULL);
708
        else
709
                str = g_strconcat(prefix, ": ", message_, "\n", NULL);
710
        log_window_append(str, level);
711
        log_write(str, file_prefix);
712
        g_free(str);
713
714
        g_log_default_handler(log_domain, log_level, message, user_data);
715
}
716
717
static void set_log_handlers(gboolean enable)
718
{
719
#if GLIB_CHECK_VERSION(2, 6, 0)
720
        if (enable)
721
                g_log_set_default_handler(default_log_func, NULL);
722
        else
723
                g_log_set_default_handler(g_log_default_handler, NULL);
724
#else
725
        static guint handler_id[4] = {0, 0, 0, 0};
726
727
        if (enable) {
728
                handler_id[0] = g_log_set_handler
729
                        ("GLib", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
730
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
731
                handler_id[1] = g_log_set_handler
732
                        ("Gtk", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
733
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
734
                handler_id[2] = g_log_set_handler
735
                        ("LibSylph", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
736
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
737
                handler_id[3] = g_log_set_handler
738
                        ("Sylpheed", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
739
                         | G_LOG_FLAG_RECURSION, default_log_func, NULL);
740
        } else {
741
                g_log_remove_handler("GLib", handler_id[0]);
742
                g_log_remove_handler("Gtk", handler_id[1]);
743
                g_log_remove_handler("LibSylph", handler_id[2]);
744
                g_log_remove_handler("Sylpheed", handler_id[3]);
745
                handler_id[0] = 0;
746
                handler_id[1] = 0;
747
                handler_id[2] = 0;
748
                handler_id[3] = 0;
749
        }
750
#endif
751
}
752
753
static gchar *get_socket_name(void)
754
{
755
        static gchar *filename = NULL;
756
757
        if (filename == NULL) {
758
                filename = g_strdup_printf("%s%csylpheed-%d",
759
                                           g_get_tmp_dir(), G_DIR_SEPARATOR,
760
#if HAVE_GETUID
761
                                           getuid());
762
#else
763
                                           0);
764
#endif
765
        }
766
767
        return filename;
768
}
769
770
static gint prohibit_duplicate_launch(void)
771
{
772
#ifdef G_OS_WIN32
773
        HANDLE hmutex;
774
775
        hmutex = CreateMutexA(NULL, FALSE, "Sylpheed");
776
        if (!hmutex) {
777
                g_warning("cannot create Mutex\n");
778
                return -1;
779
        }
780
        if (GetLastError() == ERROR_ALREADY_EXISTS) {
781
                debug_print(_("another Sylpheed is already running.\n"));
782
                return -1;
783
        }
784
785
        return 0;
786
#else
787
        gint uxsock;
788
        gchar *path;
789
790
        path = get_socket_name();
791
        uxsock = fd_connect_unix(path);
792
        if (uxsock < 0) {
793
                g_unlink(path);
794
                return fd_open_unix(path);
795
        }
796
797
        /* remote command mode */
798
799
        debug_print(_("another Sylpheed is already running.\n"));
800
801
        if (cmd.receive_all)
802
                fd_write_all(uxsock, "receive_all\n", 12);
803
        else if (cmd.receive)
804
                fd_write_all(uxsock, "receive\n", 8);
805
        else if (cmd.compose && cmd.attach_files) {
806
                gchar *str, *compose_str;
807
                gint i;
808
809
                if (cmd.compose_mailto)
810
                        compose_str = g_strdup_printf("compose_attach %s\n",
811
                                                      cmd.compose_mailto);
812
                else
813
                        compose_str = g_strdup("compose_attach\n");
814
815
                fd_write_all(uxsock, compose_str, strlen(compose_str));
816
                g_free(compose_str);
817
818
                for (i = 0; i < cmd.attach_files->len; i++) {
819
                        str = g_ptr_array_index(cmd.attach_files, i);
820
                        fd_write_all(uxsock, str, strlen(str));
821
                        fd_write_all(uxsock, "\n", 1);
822
                }
823
824
                fd_write_all(uxsock, ".\n", 2);
825
        } else if (cmd.compose) {
826
                gchar *compose_str;
827
828
                if (cmd.compose_mailto)
829
                        compose_str = g_strdup_printf
830
                                ("compose %s\n", cmd.compose_mailto);
831
                else
832
                        compose_str = g_strdup("compose\n");
833
834
                fd_write_all(uxsock, compose_str, strlen(compose_str));
835
                g_free(compose_str);
836
        } else if (cmd.send) {
837
                fd_write_all(uxsock, "send\n", 5);
838
        } else if (cmd.status || cmd.status_full) {
839
                gchar buf[BUFFSIZE];
840
                gint i;
841
                const gchar *command;
842
                GPtrArray *folders;
843
                gchar *folder;
844
845
                command = cmd.status_full ? "status-full\n" : "status\n";
846
                folders = cmd.status_full ? cmd.status_full_folders :
847
                        cmd.status_folders;
848
849
                fd_write_all(uxsock, command, strlen(command));
850
                for (i = 0; folders && i < folders->len; ++i) {
851
                        folder = g_ptr_array_index(folders, i);
852
                        fd_write_all(uxsock, folder, strlen(folder));
853
                        fd_write_all(uxsock, "\n", 1);
854
                }
855
                fd_write_all(uxsock, ".\n", 2);
856
                for (;;) {
857
                        fd_gets(uxsock, buf, sizeof(buf));
858
                        if (!strncmp(buf, ".\n", 2)) break;
859
                        fputs(buf, stdout);
860
                }
861
        } else
862
                fd_write_all(uxsock, "popup\n", 6);
863
864
        fd_close(uxsock);
865
        return -1;
866
#endif
867
}
868
869
static gint lock_socket_remove(void)
870
{
871
#ifdef G_OS_UNIX
872
        gchar *filename;
873
874
        if (lock_socket < 0) return -1;
875
876
        if (lock_socket_tag > 0)
877
                g_source_remove(lock_socket_tag);
878
        if (lock_ch) {
879
                g_io_channel_shutdown(lock_ch, FALSE, NULL);
880
                g_io_channel_unref(lock_ch);
881
                lock_ch = NULL;
882
        }
883
        filename = get_socket_name();
884
        g_unlink(filename);
885
#endif
886
887
        return 0;
888
}
889
890
static GPtrArray *get_folder_item_list(gint sock)
891
{
892
        gchar buf[BUFFSIZE];
893
        FolderItem *item;
894
        GPtrArray *folders = NULL;
895
896
        for (;;) {
897
                fd_gets(sock, buf, sizeof(buf));
898
                if (!strncmp(buf, ".\n", 2)) break;
899
                strretchomp(buf);
900
                if (!folders) folders = g_ptr_array_new();
901
                item = folder_find_item_from_identifier(buf);
902
                if (item)
903
                        g_ptr_array_add(folders, item);
904
                else
905
                        g_warning("no such folder: %s\n", buf);
906
        }
907
908
        return folders;
909
}
910
911
static gboolean lock_socket_input_cb(GIOChannel *source, GIOCondition condition,
912
                                     gpointer data)
913
{
914
        MainWindow *mainwin = (MainWindow *)data;
915
        gint fd, sock;
916
        gchar buf[BUFFSIZE];
917
918
        fd = g_io_channel_unix_get_fd(source);
919
        sock = fd_accept(fd);
920
        fd_gets(sock, buf, sizeof(buf));
921
922
        if (!strncmp(buf, "popup", 5)) {
923
                main_window_popup(mainwin);
924
        } else if (!strncmp(buf, "receive_all", 11)) {
925
                main_window_popup(mainwin);
926
                inc_all_account_mail(mainwin, FALSE);
927
        } else if (!strncmp(buf, "receive", 7)) {
928
                main_window_popup(mainwin);
929
                inc_mail(mainwin);
930
        } else if (!strncmp(buf, "compose_attach", 14)) {
931
                GPtrArray *files;
932
                gchar *mailto;
933
934
                mailto = g_strdup(buf + strlen("compose_attach") + 1);
935
                files = g_ptr_array_new();
936
                while (fd_gets(sock, buf, sizeof(buf)) > 0) {
937
                        if (buf[0] == '.' && buf[1] == '\n') break;
938
                        strretchomp(buf);
939
                        g_ptr_array_add(files, g_strdup(buf));
940
                }
941
                open_compose_new(mailto, files);
942
                ptr_array_free_strings(files);
943
                g_ptr_array_free(files, TRUE);
944
                g_free(mailto);
945
        } else if (!strncmp(buf, "compose", 7)) {
946
                open_compose_new(buf + strlen("compose") + 1, NULL);
947
        } else if (!strncmp(buf, "send", 4)) {
948
                send_queue();
949
        } else if (!strncmp(buf, "status-full", 11) ||
950
                   !strncmp(buf, "status", 6)) {
951
                gchar *status;
952
                GPtrArray *folders;
953
954
                folders = get_folder_item_list(sock);
955
                status = folder_get_status
956
                        (folders, !strncmp(buf, "status-full", 11));
957
                fd_write_all(sock, status, strlen(status));
958
                fd_write_all(sock, ".\n", 2);
959
                g_free(status);
960
                if (folders) g_ptr_array_free(folders, TRUE);
961
        }
962
963
        fd_close(sock);
964
965
        return TRUE;
966
}
967
968
static void remote_command_exec(void)
969
{
970
        MainWindow *mainwin;
971
972
        mainwin = main_window_get();
973
974
        if (cmd.receive_all)
975
                inc_all_account_mail(mainwin, FALSE);
976
        else if (prefs_common.chk_on_startup)
977
                inc_all_account_mail(mainwin, TRUE);
978
        else if (cmd.receive)
979
                inc_mail(mainwin);
980
981
        if (cmd.compose)
982
                open_compose_new(cmd.compose_mailto, cmd.attach_files);
983
        if (cmd.attach_files) {
984
                ptr_array_free_strings(cmd.attach_files);
985
                g_ptr_array_free(cmd.attach_files, TRUE);
986
                cmd.attach_files = NULL;
987
        }
988
        if (cmd.send)
989
                send_queue();
990
        if (cmd.status_folders) {
991
                g_ptr_array_free(cmd.status_folders, TRUE);
992
                cmd.status_folders = NULL;
993
        }
994
        if (cmd.status_full_folders) {
995
                g_ptr_array_free(cmd.status_full_folders, TRUE);
996
                cmd.status_full_folders = NULL;
997
        }
998
}
999
1000
static void migrate_old_config(void)
1001
{
1002
        GDir *dir;
1003
        const gchar *dir_name;
1004
        GPatternSpec *pspec;
1005
1006
        if (alertpanel(_("Migration of configuration"),
1007
                       _("The previous version of configuration found.\n"
1008
                         "Do you want to migrate it?"),
1009
                       GTK_STOCK_YES, GTK_STOCK_NO, NULL) != G_ALERTDEFAULT)
1010
                return;
1011
1012
        debug_print("Migrating old configuration...\n");
1013
1014
#define COPY_FILE(rcfile)                                                \
1015
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile)) {        \
1016
                conv_copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S rcfile,        \
1017
                               RC_DIR G_DIR_SEPARATOR_S rcfile,                \
1018
                               conv_get_locale_charset_str());                \
1019
        }
1020
1021
        COPY_FILE(ACCOUNT_RC);
1022
        COPY_FILE(ACTIONS_RC);
1023
        COPY_FILE(COMMON_RC);
1024
        COPY_FILE(CUSTOM_HEADER_RC);
1025
        COPY_FILE(DISPLAY_HEADER_RC);
1026
        COPY_FILE(FILTER_HEADER_RC);
1027
        COPY_FILE(COMMAND_HISTORY);
1028
1029
#undef COPY_FILE
1030
1031
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST))
1032
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FILTER_LIST,
1033
                          RC_DIR G_DIR_SEPARATOR_S FILTER_LIST, FALSE);
1034
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST))
1035
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST,
1036
                          RC_DIR G_DIR_SEPARATOR_S FOLDER_LIST, FALSE);
1037
        if (is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types"))
1038
                copy_file(OLD_RC_DIR G_DIR_SEPARATOR_S "mime.types",
1039
                          RC_DIR G_DIR_SEPARATOR_S "mime.types", FALSE);
1040
1041
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR))
1042
                conv_copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1043
                              RC_DIR G_DIR_SEPARATOR_S TEMPLATE_DIR,
1044
                              conv_get_locale_charset_str());
1045
        if (is_dir_exist(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR))
1046
                copy_dir(OLD_RC_DIR G_DIR_SEPARATOR_S UIDL_DIR,
1047
                         RC_DIR G_DIR_SEPARATOR_S UIDL_DIR);
1048
1049
        if (!is_file_exist(OLD_RC_DIR G_DIR_SEPARATOR_S ADDRESSBOOK_INDEX_FILE))
1050
                return;
1051
1052
        if ((dir = g_dir_open(OLD_RC_DIR, 0, NULL)) == NULL) {
1053
                g_warning("failed to open directory: %s\n", OLD_RC_DIR);
1054
                return;
1055
        }
1056
1057
        pspec = g_pattern_spec_new("addrbook-*.xml");
1058
1059
        while ((dir_name = g_dir_read_name(dir)) != NULL) {
1060
                if (g_pattern_match_string(pspec, dir_name)) {
1061
                        gchar *old_file;
1062
                        gchar *new_file;
1063
1064
                        old_file = g_strconcat(OLD_RC_DIR G_DIR_SEPARATOR_S,
1065
                                               dir_name, NULL);
1066
                        new_file = g_strconcat(RC_DIR G_DIR_SEPARATOR_S,
1067
                                               dir_name, NULL);
1068
                        copy_file(old_file, new_file, FALSE);
1069
                        g_free(new_file);
1070
                        g_free(old_file);
1071
                }
1072
        }
1073
1074
        g_pattern_spec_free(pspec);
1075
        g_dir_close(dir);
1076
}
1077
1078
static void open_compose_new(const gchar *address, GPtrArray *attach_files)
1079
{
1080
        gchar *addr = NULL;
1081
1082
        if (address) {
1083
                Xstrdup_a(addr, address, return);
1084
                g_strstrip(addr);
1085
        }
1086
1087
        compose_new(NULL, NULL, addr, attach_files);
1088
}
1089
1090
static void send_queue(void)
1091
{
1092
        GList *list;
1093
1094
        if (!main_window_toggle_online_if_offline(main_window_get()))
1095
                return;
1096
1097
        for (list = folder_get_list(); list != NULL; list = list->next) {
1098
                Folder *folder = list->data;
1099
1100
                if (folder->queue) {
1101
                        gint ret;
1102
1103
                        ret = send_message_queue_all(folder->queue,
1104
                                                     prefs_common.savemsg,
1105
                                                     prefs_common.filter_sent);
1106
                        statusbar_pop_all();
1107
                        if (ret > 0)
1108
                                folder_item_scan(folder->queue);
1109
                }
1110
        }
1111
1112
        folderview_update_all_updated(TRUE);
1113
}