2 * Sylpheed -- a GTK+ based, lightweight, and fast e-mail client
3 * Copyright (C) 1999-2007 Hiroyuki Yamamoto and the Claws Mail team
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 3 of the License, or
8 * (at your option) any later version.
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.
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
27 #include <glib/gi18n.h>
28 #include <gtk/gtkmain.h>
29 #include <gtk/gtkrc.h>
38 #include <sys/types.h>
43 #include <X11/SM/SMlib.h>
48 #ifdef HAVE_STARTUP_NOTIFICATION
49 # define SN_API_NOT_YET_FROZEN
50 # include <libsn/sn-launchee.h>
51 # include <gdk/gdkx.h>
56 #include "mainwindow.h"
57 #include "folderview.h"
58 #include "image_viewer.h"
59 #include "summaryview.h"
60 #include "prefs_common.h"
61 #include "prefs_account.h"
62 #include "prefs_actions.h"
63 #include "prefs_ext_prog.h"
64 #include "prefs_fonts.h"
65 #include "prefs_image_viewer.h"
66 #include "prefs_message.h"
67 #include "prefs_receive.h"
68 #include "prefs_msg_colors.h"
69 #include "prefs_quote.h"
70 #include "prefs_spelling.h"
71 #include "prefs_summaries.h"
72 #include "prefs_themes.h"
73 #include "prefs_other.h"
74 #include "prefs_logging.h"
75 #include "prefs_send.h"
76 #include "prefs_wrapping.h"
77 #include "prefs_compose_writing.h"
78 #include "prefs_display_header.h"
83 #include "manage_window.h"
84 #include "alertpanel.h"
85 #include "statusbar.h"
86 #include "addressbook.h"
94 #include "prefs_toolbar.h"
102 #include "imap-thread.h"
104 #include "stock_pixmap.h"
106 #include "valgrind.h"
119 #include <hildon-widgets/hildon-program.h>
120 #include <gtk/gtkmain.h>
122 #include <libgnomevfs/gnome-vfs-volume.h>
123 #include <libgnomevfs/gnome-vfs-volume-monitor.h>
124 #include <libgnomevfs/gnome-vfs-utils.h>
126 #define OSSO_NAME "claws_mail"
127 #define OSSO_SERVICE "com.nokia."OSSO_NAME
128 #define OSSO_OBJECT "/com/nokia/"OSSO_NAME
129 #define OSSO_IFACE "com.nokia."OSSO_NAME
131 typedef struct _AppData AppData;
133 HildonProgram *program;
134 HildonWindow *window;
135 osso_context_t *osso_context;
138 static GnomeVFSVolumeMonitor *volmon;
144 #ifdef HAVE_STARTUP_NOTIFICATION
145 static SnLauncheeContext *sn_context = NULL;
146 static SnDisplay *sn_display = NULL;
149 static gint lock_socket = -1;
150 static gint lock_socket_tag = 0;
151 static gchar *x_display = NULL;
154 ONLINE_MODE_DONT_CHANGE,
159 static struct RemoteCmd {
161 gboolean receive_all;
163 const gchar *compose_mailto;
164 GPtrArray *attach_files;
166 gboolean status_full;
167 GPtrArray *status_folders;
168 GPtrArray *status_full_folders;
175 const gchar *subscribe_uri;
179 static void parse_cmd_opt(int argc, char *argv[]);
181 static gint prohibit_duplicate_launch (void);
182 static gchar * get_crashfile_name (void);
183 static gint lock_socket_remove (void);
184 static void lock_socket_input_cb (gpointer data,
186 GdkInputCondition condition);
188 static void open_compose_new (const gchar *address,
189 GPtrArray *attach_files);
191 static void send_queue (void);
192 static void initial_processing (FolderItem *item, gpointer data);
193 static void quit_signal_handler (int sig);
194 static void install_basic_sighandlers (void);
195 static void exit_claws (MainWindow *mainwin);
197 #define MAKE_DIR_IF_NOT_EXIST(dir) \
199 if (!is_dir_exist(dir)) { \
200 if (is_file_exist(dir)) { \
202 (_("File '%s' already exists.\n" \
203 "Can't create folder."), \
207 if (make_dir(dir) < 0) \
212 static MainWindow *static_mainwindow;
215 static HildonProgram *static_hildonprogram;
216 static osso_context_t *static_osso_context;
218 void exit_event_handler(gboolean die_now, gpointer data)
221 appdata = (AppData *) data;
222 /* Do whatever application needs to do before exiting */
223 exit_claws(static_mainwindow);
224 hildon_banner_show_information(GTK_WIDGET(appdata->window), NULL,
229 /* Callback for normal D-BUS messages */
230 gint dbus_req_handler(const gchar * interface, const gchar * method,
231 GArray * arguments, gpointer data,
235 appdata = (AppData *) data;
237 if (!strcmp(method, "top_application")) {
238 osso_rpc_free_val(retval);
241 osso_system_note_infoprint(appdata->osso_context, method, retval);
242 osso_rpc_free_val(retval);
247 static gboolean emergency_exit = FALSE;
249 #ifdef HAVE_STARTUP_NOTIFICATION
250 static void sn_error_trap_push(SnDisplay *display, Display *xdisplay)
252 gdk_error_trap_push();
255 static void sn_error_trap_pop(SnDisplay *display, Display *xdisplay)
257 gdk_error_trap_pop();
260 static void startup_notification_complete(gboolean with_window)
263 GtkWidget *hack = NULL;
266 /* this is needed to make the startup notification leave,
267 * if we have been launched from a menu.
268 * We have to display a window, so let it be very little */
269 hack = gtk_window_new(GTK_WINDOW_POPUP);
270 gtk_widget_set_uposition(hack, 0, 0);
271 gtk_widget_set_size_request(hack, 1, 1);
272 gtk_widget_show(hack);
275 xdisplay = GDK_DISPLAY();
276 sn_display = sn_display_new(xdisplay,
279 sn_context = sn_launchee_context_new_from_environment(sn_display,
280 DefaultScreen(xdisplay));
282 if (sn_context != NULL) {
283 sn_launchee_context_complete(sn_context);
284 sn_launchee_context_unref(sn_context);
285 sn_display_unref(sn_display);
288 gtk_widget_destroy(hack);
291 #endif /* HAVE_STARTUP_NOTIFICATION */
293 static void claws_gtk_idle(void)
295 while(gtk_events_pending()) {
296 gtk_main_iteration();
301 static gboolean sc_starting = FALSE;
303 static gboolean defer_check_all(void *data)
305 gboolean autochk = GPOINTER_TO_INT(data);
307 inc_all_account_mail(static_mainwindow, autochk,
308 prefs_common.newmail_notify_manu);
312 main_window_set_menu_sensitive(static_mainwindow);
313 toolbar_main_set_sensitive(static_mainwindow);
318 static gboolean defer_check(void *data)
320 inc_mail(static_mainwindow, prefs_common.newmail_notify_manu);
324 main_window_set_menu_sensitive(static_mainwindow);
325 toolbar_main_set_sensitive(static_mainwindow);
330 static gboolean defer_jump(void *data)
332 if (cmd.receive_all) {
333 defer_check_all(GINT_TO_POINTER(FALSE));
334 } else if (prefs_common.chk_on_startup) {
335 defer_check_all(GINT_TO_POINTER(TRUE));
336 } else if (cmd.receive) {
339 mainwindow_jump_to(data, FALSE);
342 main_window_set_menu_sensitive(static_mainwindow);
343 toolbar_main_set_sensitive(static_mainwindow);
348 static void chk_update_val(GtkWidget *widget, gpointer data)
350 gboolean *val = (gboolean *)data;
351 *val = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget));
354 static gboolean migrate_old_config(const gchar *old_cfg_dir, const gchar *new_cfg_dir, const gchar *oldversion)
356 gchar *message = g_strdup_printf(_("Configuration for %s found.\n"
357 "Do you want to migrate this configuration?"), oldversion);
358 gchar *message2 = g_strdup_printf(_("\n\nYour Sylpheed filtering rules can be converted by a\n"
359 "script available at %s."), TOOLS_URI);
361 if (!strcmp(oldversion, "Sylpheed"))
362 message = g_strconcat(message, message2, NULL);
366 GtkWidget *window = NULL;
367 GtkWidget *keep_backup_chk;
368 GtkTooltips *tips = gtk_tooltips_new();
369 gboolean backup = TRUE;
371 keep_backup_chk = gtk_check_button_new_with_label (_("Keep old configuration"));
372 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(keep_backup_chk), TRUE);
373 gtk_tooltips_set_tip(GTK_TOOLTIPS(tips), keep_backup_chk,
374 _("Keeping a backup will allow you to go back to an "
375 "older version, but may take a while if you have "
376 "cached IMAP or News data, and will take some extra "
377 "room on your disk."),
380 g_signal_connect(G_OBJECT(keep_backup_chk), "toggled",
381 G_CALLBACK(chk_update_val), &backup);
383 if (alertpanel_full(_("Migration of configuration"), message,
384 GTK_STOCK_NO, "+" GTK_STOCK_YES, NULL, FALSE,
385 keep_backup_chk, ALERT_QUESTION, G_ALERTDEFAULT) != G_ALERTALTERNATE) {
389 /* we can either do a fast migration requiring not any extra disk
390 * space, or a slow one that copies the old configuration and leaves
394 window = label_window_create(_("Copying configuration... This may take a while..."));
397 r = copy_dir(old_cfg_dir, new_cfg_dir);
398 label_window_destroy(window);
400 /* if copy failed, we'll remove the partially copied
403 alertpanel_error(_("Migration failed!"));
404 remove_dir_recursive(new_cfg_dir);
407 /* fast mode failed, but we don't want backup */
408 remove_dir_recursive(old_cfg_dir);
412 window = label_window_create(_("Migrating configuration..."));
415 r = g_rename(old_cfg_dir, new_cfg_dir);
416 label_window_destroy(window);
418 /* if g_rename failed, we'll try to copy */
420 FILE_OP_ERROR(new_cfg_dir, "g_rename failed, trying copy\n");
427 static void migrate_common_rc(const gchar *old_rc, const gchar *new_rc)
430 gchar *plugin_path, *old_plugin_path, *new_plugin_path;
432 oldfp = g_fopen(old_rc, "r");
435 newfp = g_fopen(new_rc, "w");
441 plugin_path = g_strdup(get_plugin_dir());
442 new_plugin_path = g_strdup(plugin_path);
444 if (strstr(plugin_path, "/claws-mail/")) {
445 gchar *end = g_strdup(strstr(plugin_path, "/claws-mail/")+strlen("/claws-mail/"));
446 *(strstr(plugin_path, "/claws-mail/")) = '\0';
447 old_plugin_path = g_strconcat(plugin_path, "/sylpheed-claws/", end, NULL);
450 old_plugin_path = g_strdup(new_plugin_path);
452 debug_print("replacing %s with %s\n", old_plugin_path, new_plugin_path);
453 while (fgets(buf, sizeof(buf), oldfp)) {
454 if (strncmp(buf, old_plugin_path, strlen(old_plugin_path))) {
457 debug_print("->replacing %s", buf);
458 debug_print(" with %s%s", new_plugin_path, buf+strlen(old_plugin_path));
459 fputs(new_plugin_path, newfp);
460 fputs(buf+strlen(old_plugin_path), newfp);
464 g_free(new_plugin_path);
465 g_free(old_plugin_path);
472 sc_client_set_value (MainWindow *mainwin,
483 prop.num_vals = num_vals;
487 if (mainwin->smc_conn)
488 SmcSetProperties ((SmcConn) mainwin->smc_conn, 1, proplist);
491 static void sc_die_callback (SmcConn smc_conn, SmPointer client_data)
496 static void sc_save_complete_callback(SmcConn smc_conn, SmPointer client_data)
500 static void sc_shutdown_cancelled_callback (SmcConn smc_conn, SmPointer client_data)
502 MainWindow *mainwin = (MainWindow *)client_data;
503 if (mainwin->smc_conn)
504 SmcSaveYourselfDone ((SmcConn) mainwin->smc_conn, TRUE);
507 static void sc_save_yourself_callback (SmcConn smc_conn,
508 SmPointer client_data,
514 MainWindow *mainwin = (MainWindow *)client_data;
515 if (mainwin->smc_conn)
516 SmcSaveYourselfDone ((SmcConn) mainwin->smc_conn, TRUE);
519 static IceIOErrorHandler sc_ice_installed_handler;
521 static void sc_ice_io_error_handler (IceConn connection)
523 if (sc_ice_installed_handler)
524 (*sc_ice_installed_handler) (connection);
526 static gboolean sc_process_ice_messages (GIOChannel *source,
527 GIOCondition condition,
530 IceConn connection = (IceConn) data;
531 IceProcessMessagesStatus status;
533 status = IceProcessMessages (connection, NULL, NULL);
535 if (status == IceProcessMessagesIOError) {
536 IcePointer context = IceGetConnectionContext (connection);
538 if (context && GTK_IS_OBJECT (context)) {
539 guint disconnect_id = g_signal_lookup ("disconnect", G_OBJECT_TYPE (context));
541 if (disconnect_id > 0)
542 g_signal_emit (context, disconnect_id, 0);
544 IceSetShutdownNegotiation (connection, False);
545 IceCloseConnection (connection);
552 static void new_ice_connection (IceConn connection, IcePointer client_data, Bool opening,
553 IcePointer *watch_data)
559 /* Make sure we don't pass on these file descriptors to any
561 fcntl(IceConnectionNumber(connection),F_SETFD,
562 fcntl(IceConnectionNumber(connection),F_GETFD,0) | FD_CLOEXEC);
564 channel = g_io_channel_unix_new (IceConnectionNumber (connection));
565 input_id = g_io_add_watch (channel,
566 G_IO_IN | G_IO_HUP | G_IO_ERR | G_IO_PRI,
567 sc_process_ice_messages,
569 g_io_channel_unref (channel);
571 *watch_data = (IcePointer) GUINT_TO_POINTER (input_id);
573 input_id = GPOINTER_TO_UINT ((gpointer) *watch_data);
574 g_source_remove (input_id);
578 static void sc_session_manager_connect(MainWindow *mainwin)
580 static gboolean connected = FALSE;
581 SmcCallbacks callbacks;
583 IceIOErrorHandler default_handler;
590 sc_ice_installed_handler = IceSetIOErrorHandler (NULL);
591 default_handler = IceSetIOErrorHandler (sc_ice_io_error_handler);
593 if (sc_ice_installed_handler == default_handler)
594 sc_ice_installed_handler = NULL;
596 IceAddConnectionWatch (new_ice_connection, NULL);
599 callbacks.save_yourself.callback = sc_save_yourself_callback;
600 callbacks.die.callback = sc_die_callback;
601 callbacks.save_complete.callback = sc_save_complete_callback;
602 callbacks.shutdown_cancelled.callback = sc_shutdown_cancelled_callback;
604 callbacks.save_yourself.client_data =
605 callbacks.die.client_data =
606 callbacks.save_complete.client_data =
607 callbacks.shutdown_cancelled.client_data = (SmPointer) mainwin;
608 if (g_getenv ("SESSION_MANAGER")) {
609 gchar error_string_ret[256] = "";
611 mainwin->smc_conn = (gpointer)
612 SmcOpenConnection (NULL, mainwin,
613 SmProtoMajor, SmProtoMinor,
614 SmcSaveYourselfProcMask | SmcDieProcMask |
615 SmcSaveCompleteProcMask |
616 SmcShutdownCancelledProcMask,
619 256, error_string_ret);
621 if (error_string_ret[0] || mainwin->smc_conn == NULL)
622 g_warning ("While connecting to session manager:\n%s.",
626 vals = g_new (SmPropValue, 1);
627 vals[0].length = strlen(argv0);
628 vals[0].value = argv0;
629 sc_client_set_value (mainwin, SmCloneCommand, SmLISTofARRAY8, 1, vals);
630 sc_client_set_value (mainwin, SmRestartCommand, SmLISTofARRAY8, 1, vals);
631 sc_client_set_value (mainwin, SmProgram, SmARRAY8, 1, vals);
633 vals[0].length = strlen(g_get_user_name()?g_get_user_name():"");
634 vals[0].value = g_strdup(g_get_user_name()?g_get_user_name():"");
635 sc_client_set_value (mainwin, SmUserID, SmARRAY8, 1, vals);
641 static gboolean sc_exiting = FALSE;
642 static gboolean show_at_startup = TRUE;
643 static gboolean claws_crashed_bool = FALSE;
645 gboolean claws_crashed(void) {
646 return claws_crashed_bool;
649 void main_set_show_at_startup(gboolean show)
651 show_at_startup = show;
655 static void main_vol_mount_cb(GnomeVFSVolumeMonitor *vfs, GnomeVFSVolume *vol, MainWindow *mainwin)
657 gchar *uri = gnome_vfs_volume_get_activation_uri (vol);
658 gchar *mount_path = uri?gnome_vfs_get_local_path_from_uri (uri):NULL;
661 if(!strcmp(mount_path, prefs_common.data_root)) {
662 gtk_widget_set_sensitive(mainwin->window, TRUE);
668 static void main_vol_unmount_cb(GnomeVFSVolumeMonitor *vfs, GnomeVFSVolume *vol, MainWindow *mainwin)
670 gchar *uri = gnome_vfs_volume_get_activation_uri (vol);
671 gchar *mount_path = uri?gnome_vfs_get_local_path_from_uri (uri):NULL;
674 if(!strcmp(mount_path, prefs_common.data_root)) {
675 gtk_widget_set_sensitive(mainwin->window, FALSE);
684 static FILE* win32_debug_fp=NULL;
685 static guint win32_log_handler_app_id;
686 static guint win32_log_handler_glib_id;
687 static guint win32_log_handler_gtk_id;
689 static void win32_print_stdout(const gchar *string)
691 if (win32_debug_fp) {
692 fprintf(win32_debug_fp, string);
693 fflush(win32_debug_fp);
697 static void win32_print_stderr(const gchar *string)
699 if (win32_debug_fp) {
700 fprintf(win32_debug_fp, string);
701 fflush(win32_debug_fp);
705 static void win32_log(const gchar *log_domain, GLogLevelFlags log_level, const gchar* message, gpointer user_data)
707 if (win32_debug_fp) {
710 switch(log_level & G_LOG_LEVEL_MASK)
712 case G_LOG_LEVEL_ERROR:
715 case G_LOG_LEVEL_CRITICAL:
718 case G_LOG_LEVEL_WARNING:
721 case G_LOG_LEVEL_MESSAGE:
724 case G_LOG_LEVEL_INFO:
727 case G_LOG_LEVEL_DEBUG:
734 fprintf(win32_debug_fp, "%s: %s: %s", log_domain, type, message);
736 fprintf(win32_debug_fp, "%s: %s", type, message);
737 fflush(win32_debug_fp);
741 static void win32_open_log(void)
743 if (is_file_exist("claws-win32.log")) {
744 if (rename_force("claws-win32.log", "claws-win32.log.bak") < 0)
745 FILE_OP_ERROR("claws-win32.log", "rename");
747 win32_debug_fp = fopen("claws-win32.log", "w");
750 g_set_print_handler(win32_print_stdout);
751 g_set_printerr_handler(win32_print_stdout);
752 win32_log_handler_app_id = g_log_set_handler(NULL, G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
753 | G_LOG_FLAG_RECURSION, win32_log, NULL);
754 win32_log_handler_glib_id = g_log_set_handler("GLib", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
755 | G_LOG_FLAG_RECURSION, win32_log, NULL);
756 win32_log_handler_gtk_id = g_log_set_handler("Gtk", G_LOG_LEVEL_MASK | G_LOG_FLAG_FATAL
757 | G_LOG_FLAG_RECURSION, win32_log, NULL);
761 static void win32_close_log(void)
765 g_log_remove_handler("", win32_log_handler_app_id);
766 g_log_remove_handler("GLib", win32_log_handler_glib_id);
767 g_log_remove_handler("Gtk", win32_log_handler_gtk_id);
768 fclose(win32_debug_fp);
774 int main(int argc, char *argv[])
777 osso_context_t *osso_context;
778 osso_return_t result;
782 FolderView *folderview;
784 gboolean crash_file_present = FALSE;
785 gint num_folder_class = 0;
786 gboolean asked_for_migration = FALSE;
787 gboolean start_done = TRUE;
789 START_TIMING("startup");
796 if (!claws_init(&argc, &argv)) {
803 prefs_prepare_cache();
804 prog_version = PROG_VERSION;
805 argv0 = g_strdup(argv[0]);
807 parse_cmd_opt(argc, argv);
812 gtk_init(&argc, &argv);
813 crash_main(cmd.crash_params);
819 crash_install_handlers();
821 install_basic_sighandlers();
824 /* check and create unix domain socket for remote operation */
826 lock_socket = prohibit_duplicate_launch();
827 if (lock_socket < 0) {
828 #ifdef HAVE_STARTUP_NOTIFICATION
829 if(gtk_init_check(&argc, &argv))
830 startup_notification_complete(TRUE);
835 if (cmd.status || cmd.status_full) {
836 puts("0 Claws Mail not running.");
837 lock_socket_remove();
844 if (!g_thread_supported())
848 gtk_init(&argc, &argv);
851 osso_context = osso_initialize(OSSO_SERVICE, "2.8.1", TRUE, NULL);
852 if (osso_context == NULL) {
855 static_hildonprogram = HILDON_PROGRAM(hildon_program_get_instance());
856 static_osso_context = osso_context;
859 gtk_widget_set_default_colormap(gdk_rgb_get_colormap());
860 gtk_widget_set_default_visual(gdk_rgb_get_visual());
862 if (!g_thread_supported()) {
863 g_error(_("g_thread is not supported by glib.\n"));
866 /* check that we're not on a too recent/old gtk+ */
867 #if GTK_CHECK_VERSION(2, 9, 0)
868 if (gtk_check_version(2, 9, 0) != NULL) {
869 alertpanel_error(_("Claws Mail has been compiled with "
870 "a more recent GTK+ library than is "
871 "currently available. This will cause "
872 "crashes. You need to upgrade GTK+ or "
873 "recompile Claws Mail."));
880 if (gtk_check_version(2, 9, 0) == NULL) {
881 alertpanel_error(_("Claws Mail has been compiled with "
882 "an older GTK+ library than is "
883 "currently available. This will cause "
884 "crashes. You need to recompile "
892 /* parse gtkrc files */
893 userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtkrc-2.0",
895 gtk_rc_parse(userrc);
897 userrc = g_strconcat(get_home_dir(), G_DIR_SEPARATOR_S, ".gtk",
898 G_DIR_SEPARATOR_S, "gtkrc-2.0", NULL);
899 gtk_rc_parse(userrc);
903 CHDIR_EXEC_CODE_RETURN_VAL_IF_FAIL(get_home_dir(), 1, win32_close_log(););
905 CHDIR_RETURN_VAL_IF_FAIL(get_home_dir(), 1);
908 /* no config dir exists. See if we can migrate an old config. */
909 if (!is_dir_exist(RC_DIR)) {
910 prefs_destroy_cache();
913 /* if one of the old dirs exist, we'll ask if the user
914 * want to migrates, and r will be TRUE if he said yes
915 * and migration succeeded, and FALSE otherwise.
917 if (is_dir_exist(OLD_GTK2_RC_DIR)) {
918 r = migrate_old_config(OLD_GTK2_RC_DIR, RC_DIR, _("Sylpheed-Claws 2.6.0 (or older)"));
919 asked_for_migration = TRUE;
920 } else if (is_dir_exist(OLDER_GTK2_RC_DIR)) {
921 r = migrate_old_config(OLDER_GTK2_RC_DIR, RC_DIR, _("Sylpheed-Claws 1.9.15 (or older)"));
922 asked_for_migration = TRUE;
923 } else if (is_dir_exist(OLD_GTK1_RC_DIR)) {
924 r = migrate_old_config(OLD_GTK1_RC_DIR, RC_DIR, _("Sylpheed-Claws 1.0.5 (or older)"));
925 asked_for_migration = TRUE;
926 } else if (is_dir_exist(SYLPHEED_RC_DIR)) {
927 r = migrate_old_config(SYLPHEED_RC_DIR, RC_DIR, "Sylpheed");
928 asked_for_migration = TRUE;
931 /* If migration failed or the user didn't want to do it,
932 * we create a new one (and we'll hit wizard later).
934 if (r == FALSE && !is_dir_exist(RC_DIR) && make_dir(RC_DIR) < 0) {
943 if (!is_file_exist(RC_DIR G_DIR_SEPARATOR_S COMMON_RC) &&
944 is_file_exist(RC_DIR G_DIR_SEPARATOR_S OLD_COMMON_RC)) {
945 /* post 2.6 name change */
946 migrate_common_rc(RC_DIR G_DIR_SEPARATOR_S OLD_COMMON_RC,
947 RC_DIR G_DIR_SEPARATOR_S COMMON_RC);
951 plugin_load_all("Common");
953 userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, "gtkrc-2.0", NULL);
954 gtk_rc_parse(userrc);
957 userrc = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
958 gtk_accel_map_load (userrc);
962 CHDIR_EXEC_CODE_RETURN_VAL_IF_FAIL(get_rc_dir(), 1, win32_close_log(););
964 CHDIR_RETURN_VAL_IF_FAIL(get_rc_dir(), 1);
967 MAKE_DIR_IF_NOT_EXIST(get_mail_base_dir());
968 MAKE_DIR_IF_NOT_EXIST(get_imap_cache_dir());
969 MAKE_DIR_IF_NOT_EXIST(get_news_cache_dir());
970 MAKE_DIR_IF_NOT_EXIST(get_mime_tmp_dir());
971 MAKE_DIR_IF_NOT_EXIST(get_tmp_dir());
972 MAKE_DIR_IF_NOT_EXIST(UIDL_DIR);
974 crash_file_present = is_file_exist(get_crashfile_name());
975 /* remove temporary files */
976 remove_all_files(get_tmp_dir());
977 remove_all_files(get_mime_tmp_dir());
979 if (!cmd.crash && crash_file_present)
980 claws_crashed_bool = TRUE;
982 if (is_file_exist("claws.log")) {
983 if (rename_force("claws.log", "claws.log.bak") < 0)
984 FILE_OP_ERROR("claws.log", "rename");
986 set_log_file(LOG_PROTOCOL, "claws.log");
988 if (is_file_exist("filtering.log")) {
989 if (rename_force("filtering.log", "filtering.log.bak") < 0)
990 FILE_OP_ERROR("filtering.log", "rename");
992 set_log_file(LOG_DEBUG_FILTERING, "filtering.log");
995 CHDIR_EXEC_CODE_RETURN_VAL_IF_FAIL(get_home_dir(), 1, win32_close_log(););
997 CHDIR_RETURN_VAL_IF_FAIL(get_home_dir(), 1);
1000 folder_system_init();
1001 prefs_common_read_config();
1003 prefs_themes_init();
1005 prefs_ext_prog_init();
1006 prefs_wrapping_init();
1007 prefs_compose_writing_init();
1008 prefs_msg_colors_init();
1009 image_viewer_init();
1010 prefs_image_viewer_init();
1012 prefs_summaries_init();
1013 prefs_message_init();
1015 prefs_logging_init();
1016 prefs_receive_init();
1020 gtkaspell_checkers_init();
1021 prefs_spelling_init();
1024 sock_set_io_timeout(prefs_common.io_timeout_secs);
1025 prefs_actions_read_config();
1026 prefs_display_header_read_config();
1027 /* prefs_filtering_read_config(); */
1028 addressbook_read_file();
1029 renderer_read_config();
1031 gtkut_widget_init();
1032 stock_pixbuf_gdk(NULL, STOCK_PIXMAP_CLAWS_MAIL_ICON, &icon);
1033 gtk_window_set_default_icon(icon);
1035 folderview_initialize();
1041 mainwin = main_window_create();
1044 appdata = g_new0(AppData, 1);
1045 appdata->program = static_hildonprogram;
1046 appdata->window = mainwin->window;
1047 appdata->osso_context = osso_context;
1048 result = osso_rpc_set_cb_f(appdata->osso_context,
1052 dbus_req_handler, appdata);
1053 if (result != OSSO_OK) {
1057 /* Add handler for Exit D-BUS messages */
1058 result = osso_application_set_exit_cb(appdata->osso_context,
1060 (gpointer) appdata);
1061 if (result != OSSO_OK) {
1065 manage_window_focus_in(mainwin->window, NULL, NULL);
1066 folderview = mainwin->folderview;
1068 gtk_clist_freeze(GTK_CLIST(mainwin->folderview->ctree));
1069 folder_item_update_freeze();
1071 /* register the callback of unix domain socket input */
1073 lock_socket_tag = gdk_input_add(lock_socket,
1074 GDK_INPUT_READ | GDK_INPUT_EXCEPTION,
1075 lock_socket_input_cb,
1079 prefs_account_init();
1080 account_read_config_all();
1082 /* If we can't read a folder list or don't have accounts,
1083 * it means the configuration's not done. Either this is
1084 * a brand new install, either a failed/refused migration.
1085 * So we'll start the wizard.
1087 if (folder_read_list() < 0) {
1088 prefs_destroy_cache();
1090 /* if run_wizard returns FALSE it's because it's
1091 * been cancelled. We can't do much but exit.
1092 * however, if the user was asked for a migration,
1093 * we remove the newly created directory so that
1094 * he's asked again for migration on next launch.*/
1095 if (!run_wizard(mainwin, TRUE)) {
1096 if (asked_for_migration)
1097 remove_dir_recursive(RC_DIR);
1103 main_window_reflect_prefs_all_now();
1104 folder_write_list();
1107 if (!account_get_list()) {
1108 prefs_destroy_cache();
1109 if (!run_wizard(mainwin, FALSE)) {
1110 if (asked_for_migration)
1111 remove_dir_recursive(RC_DIR);
1117 if(!account_get_list()) {
1118 exit_claws(mainwin);
1127 toolbar_main_set_sensitive(mainwin);
1128 main_window_set_menu_sensitive(mainwin);
1130 /* if crashed, show window early so that the user
1131 * sees what's happening */
1132 if (claws_crashed())
1133 main_window_popup(mainwin);
1135 #ifdef HAVE_LIBETPAN
1136 imap_main_init(prefs_common.skip_ssl_cert_check);
1137 imap_main_set_timeout(prefs_common.io_timeout_secs);
1139 account_set_missing_folder();
1140 folder_set_missing_folders();
1141 folderview_set(folderview);
1143 prefs_matcher_read_config();
1145 /* make one all-folder processing before using claws */
1146 main_window_cursor_wait(mainwin);
1147 folder_func_to_all_folders(initial_processing, (gpointer *)mainwin);
1149 /* if claws crashed, rebuild caches */
1150 if (claws_crashed()) {
1152 debug_print("Claws Mail crashed, checking for new messages in local folders\n");
1153 folder_item_update_thaw();
1154 folderview_check_new(NULL);
1155 folder_clean_cache_memory_force();
1156 folder_item_update_freeze();
1158 /* make the crash-indicator file */
1159 str_write_to_file("foo", get_crashfile_name());
1161 inc_autocheck_timer_init(mainwin);
1163 /* ignore SIGPIPE signal for preventing sudden death of program */
1165 signal(SIGPIPE, SIG_IGN);
1167 if (cmd.online_mode == ONLINE_MODE_OFFLINE) {
1168 main_window_toggle_work_offline(mainwin, TRUE, FALSE);
1170 if (cmd.online_mode == ONLINE_MODE_ONLINE) {
1171 main_window_toggle_work_offline(mainwin, FALSE, FALSE);
1174 if (cmd.status_folders) {
1175 g_ptr_array_free(cmd.status_folders, TRUE);
1176 cmd.status_folders = NULL;
1178 if (cmd.status_full_folders) {
1179 g_ptr_array_free(cmd.status_full_folders, TRUE);
1180 cmd.status_full_folders = NULL;
1183 claws_register_idle_function(claws_gtk_idle);
1185 prefs_toolbar_init();
1187 num_folder_class = g_list_length(folder_get_list());
1189 plugin_load_all("GTK2");
1191 if (g_list_length(folder_get_list()) != num_folder_class) {
1192 debug_print("new folders loaded, reloading processing rules\n");
1193 prefs_matcher_read_config();
1196 if (plugin_get_unloaded_list() != NULL) {
1197 main_window_cursor_normal(mainwin);
1198 alertpanel_warning(_("Some plugin(s) failed to load. "
1199 "Check the Plugins configuration "
1200 "for more information."));
1201 main_window_cursor_wait(mainwin);
1204 plugin_load_standard_plugins ();
1206 /* if not crashed, show window now */
1207 if (!claws_crashed()) {
1208 /* apart if something told not to show */
1209 if (show_at_startup)
1210 main_window_popup(mainwin);
1213 if (!folder_have_mailbox()) {
1214 prefs_destroy_cache();
1215 main_window_cursor_normal(mainwin);
1216 if (folder_get_list() != NULL) {
1217 alertpanel_error(_("Claws Mail has detected a configured "
1218 "mailbox, but it is incomplete. It is "
1219 "possibly due to a failing IMAP account. Use "
1220 "\"Rebuild folder tree\" on the mailbox parent "
1221 "folder's context menu to try to fix it."));
1223 alertpanel_error(_("Claws Mail has detected a configured "
1224 "mailbox, but could not load it. It is "
1225 "probably provided by an out-of-date "
1226 "external plugin. Please reinstall the "
1227 "plugin and try again."));
1228 exit_claws(mainwin);
1236 static_mainwindow = mainwin;
1239 if (prefs_common.data_root != NULL && *prefs_common.data_root != '\0') {
1240 GnomeVFSVolume *vol = NULL;
1241 gchar *uri, *mount_path;
1243 volmon = gnome_vfs_get_volume_monitor();
1244 vol = gnome_vfs_volume_monitor_get_volume_for_path(volmon, prefs_common.data_root);
1246 uri = gnome_vfs_volume_get_activation_uri (vol);
1247 mount_path = uri?gnome_vfs_get_local_path_from_uri (uri):NULL;
1250 if (vol == NULL || !gnome_vfs_volume_is_mounted(vol)
1251 || strcmp(mount_path, prefs_common.data_root)) {
1252 alertpanel_error(_("Claws Mail can not start without its data volume (%s)."),
1253 prefs_common.data_root);
1255 gnome_vfs_volume_unref(vol);
1256 exit_claws(mainwin);
1260 gnome_vfs_volume_unref(vol);
1261 g_signal_connect(G_OBJECT(volmon),
1262 "volume-mounted", G_CALLBACK(main_vol_mount_cb), mainwin);
1263 g_signal_connect(G_OBJECT(volmon),
1264 "volume-unmounted", G_CALLBACK(main_vol_unmount_cb), mainwin);
1268 #ifdef HAVE_STARTUP_NOTIFICATION
1269 startup_notification_complete(FALSE);
1272 sc_session_manager_connect(mainwin);
1274 folder_item_update_thaw();
1275 gtk_clist_thaw(GTK_CLIST(mainwin->folderview->ctree));
1276 main_window_cursor_normal(mainwin);
1278 if (!cmd.target && prefs_common.goto_last_folder_on_startup &&
1279 folder_find_item_from_identifier(prefs_common.last_opened_folder) != NULL &&
1281 cmd.target = prefs_common.last_opened_folder;
1284 if (cmd.receive_all && !cmd.target) {
1286 g_timeout_add(1000, defer_check_all, GINT_TO_POINTER(FALSE));
1287 } else if (prefs_common.chk_on_startup && !cmd.target) {
1289 g_timeout_add(1000, defer_check_all, GINT_TO_POINTER(TRUE));
1290 } else if (cmd.receive && !cmd.target) {
1292 g_timeout_add(1000, defer_check, NULL);
1294 gtk_widget_grab_focus(folderview->ctree);
1298 open_compose_new(cmd.compose_mailto, cmd.attach_files);
1300 if (cmd.attach_files) {
1301 ptr_array_free_strings(cmd.attach_files);
1302 g_ptr_array_free(cmd.attach_files, TRUE);
1303 cmd.attach_files = NULL;
1305 if (cmd.subscribe) {
1306 folder_subscribe(cmd.subscribe_uri);
1315 g_timeout_add(500, defer_jump, (gpointer)cmd.target);
1318 prefs_destroy_cache();
1320 compose_reopen_exit_drafts();
1323 sc_starting = FALSE;
1324 main_window_set_menu_sensitive(mainwin);
1325 toolbar_main_set_sensitive(mainwin);
1332 osso_deinitialize(osso_context);
1337 exit_claws(mainwin);
1342 static void save_all_caches(FolderItem *item, gpointer data)
1349 folder_item_close(item);
1352 folder_item_free_cache(item, TRUE);
1355 static void exit_claws(MainWindow *mainwin)
1361 debug_print("shutting down\n");
1362 inc_autocheck_timer_remove();
1364 if (prefs_common.clean_on_exit && !emergency_exit) {
1365 main_window_empty_trash(mainwin, prefs_common.ask_on_clean);
1368 /* save prefs for opened folder */
1369 if(mainwin->folderview->opened) {
1372 item = gtk_ctree_node_get_row_data(GTK_CTREE(mainwin->folderview->ctree), mainwin->folderview->opened);
1373 summary_save_prefs_to_folderitem(mainwin->folderview->summaryview, item);
1374 prefs_common.last_opened_folder = folder_item_get_identifier(item);
1377 /* save all state before exiting */
1378 folder_func_to_all_folders(save_all_caches, NULL);
1379 folder_write_list();
1381 main_window_get_size(mainwin);
1382 main_window_get_position(mainwin);
1384 prefs_common_write_config();
1385 account_write_config_all();
1386 addressbook_export_to_file();
1388 filename = g_strconcat(get_rc_dir(), G_DIR_SEPARATOR_S, MENU_RC, NULL);
1389 gtk_accel_map_save(filename);
1392 /* delete temporary files */
1393 remove_all_files(get_tmp_dir());
1394 remove_all_files(get_mime_tmp_dir());
1396 close_log_file(LOG_PROTOCOL);
1397 close_log_file(LOG_DEBUG_FILTERING);
1399 #ifdef HAVE_LIBETPAN
1402 /* delete crashfile */
1404 g_unlink(get_crashfile_name());
1406 lock_socket_remove();
1409 if (mainwin->smc_conn)
1410 SmcCloseConnection ((SmcConn)mainwin->smc_conn, 0, NULL);
1411 mainwin->smc_conn = NULL;
1414 main_window_destroy_all();
1416 plugin_unload_all("GTK2");
1418 prefs_toolbar_done();
1420 addressbook_destroy();
1422 prefs_themes_done();
1424 prefs_ext_prog_done();
1425 prefs_wrapping_done();
1426 prefs_compose_writing_done();
1427 prefs_msg_colors_done();
1428 prefs_image_viewer_done();
1429 image_viewer_done();
1431 prefs_summaries_done();
1432 prefs_message_done();
1434 prefs_receive_done();
1438 prefs_spelling_done();
1439 gtkaspell_checkers_quit();
1441 plugin_unload_all("Common");
1445 static void parse_cmd_opt(int argc, char *argv[])
1449 for (i = 1; i < argc; i++) {
1450 if (!strncmp(argv[i], "--receive-all", 13)) {
1451 cmd.receive_all = TRUE;
1452 } else if (!strncmp(argv[i], "--receive", 9)) {
1454 } else if (!strncmp(argv[i], "--compose", 9)) {
1455 const gchar *p = argv[i + 1];
1458 cmd.compose_mailto = NULL;
1459 if (p && *p != '\0' && *p != '-') {
1460 if (!strncmp(p, "mailto:", 7)) {
1461 cmd.compose_mailto = p + 7;
1463 cmd.compose_mailto = p;
1467 } else if (!strncmp(argv[i], "--subscribe", 11)) {
1468 const gchar *p = argv[i + 1];
1469 if (p && *p != '\0' && *p != '-') {
1470 cmd.subscribe = TRUE;
1471 cmd.subscribe_uri = p;
1473 } else if (!strncmp(argv[i], "--attach", 8)) {
1474 const gchar *p = argv[i + 1];
1477 while (p && *p != '\0' && *p != '-') {
1478 if (!cmd.attach_files) {
1479 cmd.attach_files = g_ptr_array_new();
1481 if ((file = g_filename_from_uri(p, NULL, NULL)) != NULL) {
1482 if (!is_file_exist(file)) {
1487 if (file == NULL && *p != G_DIR_SEPARATOR) {
1488 file = g_strconcat(claws_get_startup_dir(),
1491 } else if (file == NULL) {
1494 g_ptr_array_add(cmd.attach_files, file);
1498 } else if (!strncmp(argv[i], "--send", 6)) {
1500 } else if (!strncmp(argv[i], "--version", 9) ||
1501 !strncmp(argv[i], "-v", 2)) {
1502 g_print("Claws Mail version " VERSION);
1504 } else if (!strncmp(argv[i], "--status-full", 13)) {
1505 const gchar *p = argv[i + 1];
1507 cmd.status_full = TRUE;
1508 while (p && *p != '\0' && *p != '-') {
1509 if (!cmd.status_full_folders) {
1510 cmd.status_full_folders =
1513 g_ptr_array_add(cmd.status_full_folders,
1518 } else if (!strncmp(argv[i], "--status", 8)) {
1519 const gchar *p = argv[i + 1];
1522 while (p && *p != '\0' && *p != '-') {
1523 if (!cmd.status_folders)
1524 cmd.status_folders = g_ptr_array_new();
1525 g_ptr_array_add(cmd.status_folders,
1530 } else if (!strncmp(argv[i], "--online", 8)) {
1531 cmd.online_mode = ONLINE_MODE_ONLINE;
1532 } else if (!strncmp(argv[i], "--offline", 9)) {
1533 cmd.online_mode = ONLINE_MODE_OFFLINE;
1534 } else if (!strncmp(argv[i], "--help", 6) ||
1535 !strncmp(argv[i], "-h", 2)) {
1536 gchar *base = g_path_get_basename(argv[0]);
1537 g_print(_("Usage: %s [OPTION]...\n"), base);
1539 g_print("%s\n", _(" --compose [address] open composition window"));
1540 g_print("%s\n", _(" --subscribe [uri] subscribe to the given URI if possible"));
1541 g_print("%s\n", _(" --attach file1 [file2]...\n"
1542 " open composition window with specified files\n"
1544 g_print("%s\n", _(" --receive receive new messages"));
1545 g_print("%s\n", _(" --receive-all receive new messages of all accounts"));
1546 g_print("%s\n", _(" --send send all queued messages"));
1547 g_print("%s\n", _(" --status [folder]... show the total number of messages"));
1548 g_print("%s\n", _(" --status-full [folder]...\n"
1549 " show the status of each folder"));
1550 g_print("%s\n", _(" --select folder[/msg] jumps to the specified folder/message\n"
1551 " folder is a folder id like 'folder/sub_folder'"));
1552 g_print("%s\n", _(" --online switch to online mode"));
1553 g_print("%s\n", _(" --offline switch to offline mode"));
1554 g_print("%s\n", _(" --exit --quit -q exit Claws Mail"));
1555 g_print("%s\n", _(" --debug debug mode"));
1556 g_print("%s\n", _(" --help -h display this help and exit"));
1557 g_print("%s\n", _(" --version -v output version information and exit"));
1558 g_print("%s\n", _(" --config-dir output configuration directory"));
1562 } else if (!strncmp(argv[i], "--crash", 7)) {
1564 cmd.crash_params = g_strdup(argv[i + 1]);
1566 } else if (!strncmp(argv[i], "--config-dir", sizeof "--config-dir" - 1)) {
1569 } else if (!strncmp(argv[i], "--exit", 6) ||
1570 !strncmp(argv[i], "--quit", 6) ||
1571 !strncmp(argv[i], "-q", 2)) {
1573 } else if (!strncmp(argv[i], "--select", 8) && i+1 < argc) {
1574 cmd.target = argv[i+1];
1575 } else if (i == 1 && argc == 2) {
1576 /* only one parameter. Do something intelligent about it */
1577 if (strstr(argv[i], "@") && !strstr(argv[i], "://")) {
1578 const gchar *p = argv[i];
1581 cmd.compose_mailto = NULL;
1582 if (p && *p != '\0' && *p != '-') {
1583 if (!strncmp(p, "mailto:", 7)) {
1584 cmd.compose_mailto = p + 7;
1586 cmd.compose_mailto = p;
1589 } else if (strstr(argv[i], "://")) {
1590 const gchar *p = argv[i];
1591 if (p && *p != '\0' && *p != '-') {
1592 cmd.subscribe = TRUE;
1593 cmd.subscribe_uri = p;
1595 } else if (!strcmp(argv[i], "--sync")) {
1598 g_print(_("Unknown option\n"));
1604 if (cmd.attach_files && cmd.compose == FALSE) {
1606 cmd.compose_mailto = NULL;
1610 static void initial_processing(FolderItem *item, gpointer data)
1612 MainWindow *mainwin = (MainWindow *)data;
1615 g_return_if_fail(item);
1616 buf = g_strdup_printf(_("Processing (%s)..."),
1619 : _("top level folder"));
1623 if (item->prefs->enable_processing) {
1624 folder_item_apply_processing(item);
1627 STATUSBAR_POP(mainwin);
1630 static gboolean draft_all_messages(void)
1632 GList *compose_list = NULL;
1634 compose_clear_exit_drafts();
1635 compose_list = compose_get_compose_list();
1636 while (compose_list != NULL) {
1637 Compose *c = (Compose*)compose_list->data;
1638 if (!compose_draft(c, COMPOSE_DRAFT_FOR_EXIT))
1640 compose_list = compose_get_compose_list();
1644 gboolean clean_quit(gpointer data)
1646 static gboolean firstrun = TRUE;
1653 /*!< Good idea to have the main window stored in a
1654 * static variable so we can check that variable
1655 * to see if we're really allowed to do things
1656 * that actually the spawner is supposed to
1657 * do (like: sending mail, composing messages).
1658 * Because, really, if we're the spawnee, and
1659 * we touch GTK stuff, we're hosed. See the
1662 /* FIXME: Use something else to signal that we're
1663 * in the original spawner, and not in a spawned
1665 if (!static_mainwindow) {
1669 draft_all_messages();
1670 emergency_exit = TRUE;
1671 exit_claws(static_mainwindow);
1677 void app_will_exit(GtkWidget *widget, gpointer data)
1679 MainWindow *mainwin = data;
1681 if (sc_exiting == TRUE) {
1682 debug_print("exit pending\n");
1686 debug_print("exiting\n");
1687 if (compose_get_compose_list()) {
1688 if (!draft_all_messages()) {
1689 main_window_popup(mainwin);
1695 if (prefs_common.warn_queued_on_exit && procmsg_have_queued_mails_fast()) {
1696 if (alertpanel(_("Queued messages"),
1697 _("Some unsent messages are queued. Exit now?"),
1698 GTK_STOCK_CANCEL, GTK_STOCK_OK, NULL)
1699 != G_ALERTALTERNATE) {
1700 main_window_popup(mainwin);
1704 manage_window_focus_in(mainwin->window, NULL, NULL);
1708 #ifdef HAVE_VALGRIND
1709 if (RUNNING_ON_VALGRIND) {
1710 summary_clear_list(mainwin->summaryview);
1713 if (folderview_get_selected_item(mainwin->folderview))
1714 folder_item_close(folderview_get_selected_item(mainwin->folderview));
1718 gboolean claws_is_exiting(void)
1723 gboolean claws_is_starting(void)
1729 * CLAWS: want this public so crash dialog can delete the
1732 gchar *claws_get_socket_name(void)
1734 static gchar *filename = NULL;
1736 if (filename == NULL) {
1737 filename = g_strdup_printf("%s%cclaws-mail-%d",
1738 g_get_tmp_dir(), G_DIR_SEPARATOR,
1749 static gchar *get_crashfile_name(void)
1751 static gchar *filename = NULL;
1753 if (filename == NULL) {
1754 filename = g_strdup_printf("%s%cclaws-crashed",
1755 get_tmp_dir(), G_DIR_SEPARATOR);
1761 static gint prohibit_duplicate_launch(void)
1766 path = claws_get_socket_name();
1767 uxsock = fd_connect_unix(path);
1769 if (x_display == NULL)
1770 x_display = g_strdup(g_getenv("DISPLAY"));
1774 return fd_open_unix(path);
1777 /* remote command mode */
1779 debug_print("another Claws Mail instance is already running.\n");
1781 if (cmd.receive_all) {
1782 fd_write_all(uxsock, "receive_all\n", 12);
1783 } else if (cmd.receive) {
1784 fd_write_all(uxsock, "receive\n", 8);
1785 } else if (cmd.compose && cmd.attach_files) {
1786 gchar *str, *compose_str;
1789 if (cmd.compose_mailto) {
1790 compose_str = g_strdup_printf("compose_attach %s\n",
1791 cmd.compose_mailto);
1793 compose_str = g_strdup("compose_attach\n");
1796 fd_write_all(uxsock, compose_str, strlen(compose_str));
1797 g_free(compose_str);
1799 for (i = 0; i < cmd.attach_files->len; i++) {
1800 str = g_ptr_array_index(cmd.attach_files, i);
1801 fd_write_all(uxsock, str, strlen(str));
1802 fd_write_all(uxsock, "\n", 1);
1805 fd_write_all(uxsock, ".\n", 2);
1806 } else if (cmd.compose) {
1809 if (cmd.compose_mailto) {
1810 compose_str = g_strdup_printf
1811 ("compose %s\n", cmd.compose_mailto);
1813 compose_str = g_strdup("compose\n");
1816 fd_write_all(uxsock, compose_str, strlen(compose_str));
1817 g_free(compose_str);
1818 } else if (cmd.subscribe) {
1819 gchar *str = g_strdup_printf("subscribe %s\n", cmd.subscribe_uri);
1820 fd_write_all(uxsock, str, strlen(str));
1822 } else if (cmd.send) {
1823 fd_write_all(uxsock, "send\n", 5);
1824 } else if (cmd.online_mode == ONLINE_MODE_ONLINE) {
1825 fd_write(uxsock, "online\n", 6);
1826 } else if (cmd.online_mode == ONLINE_MODE_OFFLINE) {
1827 fd_write(uxsock, "offline\n", 7);
1828 } else if (cmd.status || cmd.status_full) {
1829 gchar buf[BUFFSIZE];
1831 const gchar *command;
1835 command = cmd.status_full ? "status-full\n" : "status\n";
1836 folders = cmd.status_full ? cmd.status_full_folders :
1839 fd_write_all(uxsock, command, strlen(command));
1840 for (i = 0; folders && i < folders->len; ++i) {
1841 folder = g_ptr_array_index(folders, i);
1842 fd_write_all(uxsock, folder, strlen(folder));
1843 fd_write_all(uxsock, "\n", 1);
1845 fd_write_all(uxsock, ".\n", 2);
1847 fd_gets(uxsock, buf, sizeof(buf));
1848 if (!strncmp(buf, ".\n", 2)) break;
1851 } else if (cmd.exit) {
1852 fd_write_all(uxsock, "exit\n", 5);
1853 } else if (cmd.target) {
1854 gchar *str = g_strdup_printf("select %s\n", cmd.target);
1855 fd_write_all(uxsock, str, strlen(str));
1859 fd_write_all(uxsock, "get_display\n", 12);
1860 memset(buf, 0, sizeof(buf));
1861 fd_gets(uxsock, buf, sizeof(buf));
1862 if (strcmp2(buf, x_display)) {
1863 g_print("Claws Mail is already running on display %s.\n",
1867 uxsock = fd_connect_unix(path);
1868 fd_write_all(uxsock, "popup\n", 6);
1876 static gint lock_socket_remove(void)
1881 if (lock_socket < 0) {
1885 if (lock_socket_tag > 0) {
1886 gdk_input_remove(lock_socket_tag);
1888 fd_close(lock_socket);
1889 filename = claws_get_socket_name();
1896 static GPtrArray *get_folder_item_list(gint sock)
1898 gchar buf[BUFFSIZE];
1900 GPtrArray *folders = NULL;
1903 fd_gets(sock, buf, sizeof(buf));
1904 if (!strncmp(buf, ".\n", 2)) {
1909 folders = g_ptr_array_new();
1911 item = folder_find_item_from_identifier(buf);
1913 g_ptr_array_add(folders, item);
1915 g_warning("no such folder: %s\n", buf);
1922 static void lock_socket_input_cb(gpointer data,
1924 GdkInputCondition condition)
1926 MainWindow *mainwin = (MainWindow *)data;
1928 gchar buf[BUFFSIZE];
1930 sock = fd_accept(source);
1931 fd_gets(sock, buf, sizeof(buf));
1933 if (!strncmp(buf, "popup", 5)) {
1934 main_window_popup(mainwin);
1935 } else if (!strncmp(buf, "get_display", 11)) {
1936 fd_write_all(sock, x_display, strlen(x_display));
1937 } else if (!strncmp(buf, "receive_all", 11)) {
1938 inc_all_account_mail(mainwin, FALSE,
1939 prefs_common.newmail_notify_manu);
1940 } else if (!strncmp(buf, "receive", 7)) {
1941 inc_mail(mainwin, prefs_common.newmail_notify_manu);
1942 } else if (!strncmp(buf, "compose_attach", 14)) {
1946 mailto = g_strdup(buf + strlen("compose_attach") + 1);
1947 files = g_ptr_array_new();
1948 while (fd_gets(sock, buf, sizeof(buf)) > 0) {
1949 if (buf[0] == '.' && buf[1] == '\n') {
1953 g_ptr_array_add(files, g_strdup(buf));
1955 open_compose_new(mailto, files);
1956 ptr_array_free_strings(files);
1957 g_ptr_array_free(files, TRUE);
1959 } else if (!strncmp(buf, "compose", 7)) {
1960 open_compose_new(buf + strlen("compose") + 1, NULL);
1961 } else if (!strncmp(buf, "subscribe", 9)) {
1962 main_window_popup(mainwin);
1963 folder_subscribe(buf + strlen("subscribe") + 1);
1964 } else if (!strncmp(buf, "send", 4)) {
1966 } else if (!strncmp(buf, "online", 6)) {
1967 main_window_toggle_work_offline(mainwin, FALSE, FALSE);
1968 } else if (!strncmp(buf, "offline", 7)) {
1969 main_window_toggle_work_offline(mainwin, TRUE, FALSE);
1970 } else if (!strncmp(buf, "status-full", 11) ||
1971 !strncmp(buf, "status", 6)) {
1975 folders = get_folder_item_list(sock);
1976 status = folder_get_status
1977 (folders, !strncmp(buf, "status-full", 11));
1978 fd_write_all(sock, status, strlen(status));
1979 fd_write_all(sock, ".\n", 2);
1981 if (folders) g_ptr_array_free(folders, TRUE);
1982 } else if (!strncmp(buf, "select ", 7)) {
1983 const gchar *target = buf+7;
1984 mainwindow_jump_to(target, TRUE);
1985 } else if (!strncmp(buf, "exit", 4)) {
1986 app_will_exit(NULL, mainwin);
1992 static void open_compose_new(const gchar *address, GPtrArray *attach_files)
1997 Xstrdup_a(addr, address, return);
2001 compose_new(NULL, addr, attach_files);
2004 static void send_queue(void)
2007 gchar *errstr = NULL;
2008 gboolean error = FALSE;
2009 for (list = folder_get_list(); list != NULL; list = list->next) {
2010 Folder *folder = list->data;
2012 if (folder->queue) {
2013 gint res = procmsg_send_queue
2014 (folder->queue, prefs_common.savemsg,
2018 folder_item_scan(folder->queue);
2026 alertpanel_error_log(_("Some errors occurred "
2027 "while sending queued messages:\n%s"), errstr);
2030 alertpanel_error_log("Some errors occurred "
2031 "while sending queued messages.");
2035 static void quit_signal_handler(int sig)
2037 debug_print("Quitting on signal %d\n", sig);
2039 g_timeout_add(0, clean_quit, NULL);
2042 static void install_basic_sighandlers()
2046 struct sigaction act;
2051 sigaddset(&mask, SIGTERM);
2054 sigaddset(&mask, SIGINT);
2057 sigaddset(&mask, SIGHUP);
2060 act.sa_handler = quit_signal_handler;
2065 sigaction(SIGTERM, &act, 0);
2068 sigaction(SIGINT, &act, 0);
2071 sigaction(SIGHUP, &act, 0);
2074 sigprocmask(SIG_UNBLOCK, &mask, 0);
2075 #endif /* !G_OS_WIN32 */
2079 HildonProgram *hildon_program(void)
2081 return static_hildonprogram;
2083 osso_context_t *get_osso_context(void)
2085 return static_osso_context;