1 /*
2  * LibSylph -- E-Mail client library
3  * Copyright (C) 1999-2010 Hiroyuki Yamamoto
4  *
5  * This library is free software; you can redistribute it and/or
6  * modify it under the terms of the GNU Lesser General Public
7  * License as published by the Free Software Foundation; either
8  * version 2.1 of the License, or (at your option) any later version.
9  *
10  * This library 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 GNU
13  * Lesser General Public License for more details.
14  *
15  * You should have received a copy of the GNU Lesser General Public
16  * License along with this library; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  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 
29 #ifdef G_OS_UNIX
30 #  include <signal.h>
31 #endif
32 
33 #if HAVE_LOCALE_H
34 #  include <locale.h>
35 #endif
36 
37 #include "sylmain.h"
38 #include "syl-marshal.h"
39 #include "prefs_common.h"
40 #include "account.h"
41 #include "filter.h"
42 #include "folder.h"
43 #include "socket.h"
44 #include "codeconv.h"
45 #include "utils.h"
46 
47 #if USE_SSL
48 #  include "ssl.h"
49 #endif
50 
51 #ifndef PACKAGE
52 #  define PACKAGE	GETTEXT_PACKAGE
53 #endif
54 
55 G_DEFINE_TYPE(SylApp, syl_app, G_TYPE_OBJECT);
56 
57 enum {
58 	INIT_DONE,
59 	APP_EXIT,
60 	APP_FORCE_EXIT,
61 	ADD_MSG,
62 	REMOVE_MSG,
63 	REMOVE_ALL_MSG,
64 	REMOVE_FOLDER,
65 	MOVE_FOLDER,
66 	FOLDERLIST_UPDATED,
67 	ACCOUNT_UPDATED,
68 	LAST_SIGNAL
69 };
70 
71 static guint app_signals[LAST_SIGNAL] = { 0 };
72 
73 static GObject *app = NULL;
74 
75 
syl_app_init(SylApp * self)76 static void syl_app_init(SylApp *self)
77 {
78 }
79 
syl_app_class_init(SylAppClass * klass)80 static void syl_app_class_init(SylAppClass *klass)
81 {
82 	GObjectClass *gobject_class = G_OBJECT_CLASS(klass);
83 
84 	app_signals[INIT_DONE] =
85 		g_signal_new("init-done",
86 			     G_TYPE_FROM_CLASS(gobject_class),
87 			     G_SIGNAL_RUN_FIRST,
88 			     0,
89 			     NULL, NULL,
90 			     syl_marshal_VOID__VOID,
91 			     G_TYPE_NONE,
92 			     0);
93 	app_signals[APP_EXIT] =
94 		g_signal_new("app-exit",
95 			     G_TYPE_FROM_CLASS(gobject_class),
96 			     G_SIGNAL_RUN_FIRST,
97 			     0,
98 			     NULL, NULL,
99 			     syl_marshal_VOID__VOID,
100 			     G_TYPE_NONE,
101 			     0);
102 	app_signals[APP_FORCE_EXIT] =
103 		g_signal_new("app-force-exit",
104 			     G_TYPE_FROM_CLASS(gobject_class),
105 			     G_SIGNAL_RUN_FIRST,
106 			     0,
107 			     NULL, NULL,
108 			     syl_marshal_VOID__VOID,
109 			     G_TYPE_NONE,
110 			     0);
111 	app_signals[ADD_MSG] =
112 		g_signal_new("add-msg",
113 			     G_TYPE_FROM_CLASS(gobject_class),
114 			     G_SIGNAL_RUN_FIRST,
115 			     0,
116 			     NULL, NULL,
117 			     syl_marshal_VOID__POINTER_STRING_UINT,
118 			     G_TYPE_NONE,
119 			     3,
120 			     G_TYPE_POINTER,
121 			     G_TYPE_STRING,
122 			     G_TYPE_UINT);
123 	app_signals[REMOVE_MSG] =
124 		g_signal_new("remove-msg",
125 			     G_TYPE_FROM_CLASS(gobject_class),
126 			     G_SIGNAL_RUN_FIRST,
127 			     0,
128 			     NULL, NULL,
129 			     syl_marshal_VOID__POINTER_STRING_UINT,
130 			     G_TYPE_NONE,
131 			     3,
132 			     G_TYPE_POINTER,
133 			     G_TYPE_STRING,
134 			     G_TYPE_UINT);
135 	app_signals[REMOVE_ALL_MSG] =
136 		g_signal_new("remove-all-msg",
137 			     G_TYPE_FROM_CLASS(gobject_class),
138 			     G_SIGNAL_RUN_FIRST,
139 			     0,
140 			     NULL, NULL,
141 			     syl_marshal_VOID__POINTER,
142 			     G_TYPE_NONE,
143 			     1,
144 			     G_TYPE_POINTER);
145 	app_signals[REMOVE_FOLDER] =
146 		g_signal_new("remove-folder",
147 			     G_TYPE_FROM_CLASS(gobject_class),
148 			     G_SIGNAL_RUN_FIRST,
149 			     0,
150 			     NULL, NULL,
151 			     syl_marshal_VOID__POINTER,
152 			     G_TYPE_NONE,
153 			     1,
154 			     G_TYPE_POINTER);
155 	app_signals[MOVE_FOLDER] =
156 		g_signal_new("move-folder",
157 			     G_TYPE_FROM_CLASS(gobject_class),
158 			     G_SIGNAL_RUN_FIRST,
159 			     0,
160 			     NULL, NULL,
161 			     syl_marshal_VOID__POINTER_STRING_STRING,
162 			     G_TYPE_NONE,
163 			     3,
164 			     G_TYPE_POINTER,
165 			     G_TYPE_STRING,
166 			     G_TYPE_STRING);
167 	app_signals[FOLDERLIST_UPDATED] =
168 		g_signal_new("folderlist-updated",
169 			     G_TYPE_FROM_CLASS(gobject_class),
170 			     G_SIGNAL_RUN_FIRST,
171 			     0,
172 			     NULL, NULL,
173 			     syl_marshal_VOID__VOID,
174 			     G_TYPE_NONE,
175 			     0);
176 	app_signals[ACCOUNT_UPDATED] =
177 		g_signal_new("account-updated",
178 			     G_TYPE_FROM_CLASS(gobject_class),
179 			     G_SIGNAL_RUN_FIRST,
180 			     0,
181 			     NULL, NULL,
182 			     syl_marshal_VOID__VOID,
183 			     G_TYPE_NONE,
184 			     0);
185 }
186 
syl_app_create(void)187 GObject *syl_app_create(void)
188 {
189 	if (!app)
190 		app = g_object_new(SYL_TYPE_APP, NULL);
191 	return app;
192 }
193 
syl_app_get(void)194 GObject *syl_app_get(void)
195 {
196 	return app;
197 }
198 
syl_init(void)199 void syl_init(void)
200 {
201 #ifdef G_OS_WIN32
202 	gchar *newpath;
203 	const gchar *lang_env;
204 
205 	/* disable locale variable such as "LANG=1041" */
206 
207 #define DISABLE_DIGIT_LOCALE(envstr)			\
208 {							\
209 	lang_env = g_getenv(envstr);			\
210 	if (lang_env && g_ascii_isdigit(lang_env[0]))	\
211 		g_unsetenv(envstr);			\
212 }
213 
214 	DISABLE_DIGIT_LOCALE("LC_ALL");
215 	DISABLE_DIGIT_LOCALE("LANG");
216 	DISABLE_DIGIT_LOCALE("LC_CTYPE");
217 	DISABLE_DIGIT_LOCALE("LC_MESSAGES");
218 
219 #undef DISABLE_DIGIT_LOCALE
220 
221 	g_unsetenv("LANGUAGE");
222 #endif /* G_OS_WIN32 */
223 
224 #ifdef HAVE_LOCALE_H
225 	setlocale(LC_ALL, "");
226 #endif
227 
228 	set_startup_dir();
229 
230 #ifdef G_OS_WIN32
231 	/* include startup directory into %PATH% for GSpawn */
232 	newpath = g_strconcat(get_startup_dir(), ";", g_getenv("PATH"), NULL);
233 	g_setenv("PATH", newpath, TRUE);
234 	g_free(newpath);
235 #endif
236 
237 #ifdef ENABLE_NLS
238 	syl_init_gettext(PACKAGE, LOCALEDIR);
239 	textdomain(PACKAGE);
240 #endif
241 
242 	sock_init();
243 
244 #ifdef G_OS_UNIX
245 	/* ignore SIGPIPE signal for preventing sudden death of program */
246 	signal(SIGPIPE, SIG_IGN);
247 #endif
248 }
249 
250 #define MAKE_DIR_IF_NOT_EXIST(dir)					\
251 {									\
252 	if (!is_dir_exist(dir)) {					\
253 		if (is_file_exist(dir)) {				\
254 			g_warning("File '%s' already exists. "		\
255 				  "Can't create folder.", dir);		\
256 			return -1;					\
257 		}							\
258 		if (make_dir(dir) < 0)					\
259 			return -1;					\
260 	}								\
261 }
262 
syl_init_gettext(const gchar * package,const gchar * dirname)263 void syl_init_gettext(const gchar *package, const gchar *dirname)
264 {
265 #ifdef ENABLE_NLS
266 	if (g_path_is_absolute(dirname))
267 		bindtextdomain(package, dirname);
268 	else {
269 		gchar *locale_dir;
270 
271 		locale_dir = g_strconcat(get_startup_dir(), G_DIR_SEPARATOR_S,
272 					 dirname, NULL);
273 #ifdef G_OS_WIN32
274 		{
275 			gchar *locale_dir_;
276 
277 			locale_dir_ = g_locale_from_utf8(locale_dir, -1,
278 							 NULL, NULL, NULL);
279 			if (locale_dir_) {
280 				g_free(locale_dir);
281 				locale_dir = locale_dir_;
282 			}
283 		}
284 #endif /* G_OS_WIN32 */
285 		bindtextdomain(package, locale_dir);
286 		g_free(locale_dir);
287 	}
288 
289 	bind_textdomain_codeset(package, CS_UTF_8);
290 #endif /* ENABLE_NLS */
291 }
292 
syl_setup_rc_dir(void)293 gint syl_setup_rc_dir(void)
294 {
295 	if (!is_dir_exist(get_rc_dir())) {
296 		if (make_dir_hier(get_rc_dir()) < 0)
297 			return -1;
298 	}
299 
300 	MAKE_DIR_IF_NOT_EXIST(get_mail_base_dir());
301 
302 	CHDIR_RETURN_VAL_IF_FAIL(get_rc_dir(), -1);
303 
304 	MAKE_DIR_IF_NOT_EXIST(get_imap_cache_dir());
305 	MAKE_DIR_IF_NOT_EXIST(get_news_cache_dir());
306 	MAKE_DIR_IF_NOT_EXIST(get_mime_tmp_dir());
307 	MAKE_DIR_IF_NOT_EXIST(get_tmp_dir());
308 	MAKE_DIR_IF_NOT_EXIST(UIDL_DIR);
309 	MAKE_DIR_IF_NOT_EXIST(PLUGIN_DIR);
310 
311 	/* remove temporary files */
312 	remove_all_files(get_tmp_dir());
313 	remove_all_files(get_mime_tmp_dir());
314 
315 	return 0;
316 }
317 
syl_save_all_state(void)318 void syl_save_all_state(void)
319 {
320 	folder_write_list();
321 	prefs_common_write_config();
322 	filter_write_config();
323 	account_write_config_all();
324 }
325 
syl_cleanup(void)326 void syl_cleanup(void)
327 {
328 	/* remove temporary files */
329 	remove_all_files(get_tmp_dir());
330 	remove_all_files(get_mime_tmp_dir());
331 #if GLIB_CHECK_VERSION(2, 6, 0)
332 	g_log_set_default_handler(g_log_default_handler, NULL);
333 #endif
334 	close_log_file();
335 
336 	sock_cleanup();
337 
338 	if (app) {
339 		g_object_unref(app);
340 		app = NULL;
341 	}
342 }
343