1 /*
2  *
3  * This program is free software; you can redistribute it and/or modify it
4  * under the terms of the GNU Lesser General Public License as published by
5  * the Free Software Foundation.
6  *
7  * This program is distributed in the hope that it will be useful, but
8  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
9  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
10  * for more details.
11  *
12  * You should have received a copy of the GNU Lesser General Public License
13  * along with this program; if not, see <http://www.gnu.org/licenses/>.
14  *
15  *
16  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
17  *
18  */
19 
20 #include "evolution-config.h"
21 
22 #include "e-composer-post-header.h"
23 
24 #include <string.h>
25 #include <glib/gi18n.h>
26 #include <camel/camel.h>
27 
28 #define E_COMPOSER_POST_HEADER_GET_PRIVATE(obj) \
29 	(G_TYPE_INSTANCE_GET_PRIVATE \
30 	((obj), E_TYPE_COMPOSER_POST_HEADER, EComposerPostHeaderPrivate))
31 
32 enum {
33 	PROP_0,
34 	PROP_MAIL_ACCOUNT
35 };
36 
37 struct _EComposerPostHeaderPrivate {
38 	ESource *mail_account;
39 	gchar *base_url;  /* derived from account */
40 	gboolean custom;
41 };
42 
G_DEFINE_TYPE(EComposerPostHeader,e_composer_post_header,E_TYPE_COMPOSER_TEXT_HEADER)43 G_DEFINE_TYPE (
44 	EComposerPostHeader,
45 	e_composer_post_header,
46 	E_TYPE_COMPOSER_TEXT_HEADER)
47 
48 static gchar *
49 composer_post_header_folder_name_to_string (EComposerPostHeader *header,
50                                             const gchar *url)
51 {
52 	gchar *res = NULL;
53 	const gchar *base_url = header->priv->base_url;
54 
55 	if (base_url != NULL) {
56 		gsize length = strlen (base_url);
57 
58 		if (g_ascii_strncasecmp (url, base_url, length) == 0) {
59 			res = g_uri_unescape_string (url + length, NULL);
60 			if (!res)
61 				res = g_strdup (url + length);
62 		}
63 	}
64 
65 	if (!res) {
66 		res = g_uri_unescape_string (url, NULL);
67 		if (!res)
68 			res = g_strdup (url);
69 	}
70 
71 	return res;
72 }
73 
74 static void
composer_post_header_set_base_url(EComposerPostHeader * header)75 composer_post_header_set_base_url (EComposerPostHeader *header)
76 {
77 	ESource *source;
78 	const gchar *uid;
79 
80 	source = header->priv->mail_account;
81 	if (source == NULL)
82 		return;
83 
84 	uid = e_source_get_uid (source);
85 	g_free (header->priv->base_url);
86 	header->priv->base_url = g_strdup_printf ("folder://%s", uid);
87 }
88 
89 static GList *
composer_post_header_split_csv(const gchar * csv)90 composer_post_header_split_csv (const gchar *csv)
91 {
92 	GList *list = NULL;
93 	gchar **strv;
94 	guint length, ii;
95 
96 	strv = g_strsplit (csv, ",", 0);
97 	length = g_strv_length (strv);
98 
99 	for (ii = 0; ii < length; ii++)
100 		if (*g_strstrip (strv[ii]) != '\0')
101 			list = g_list_prepend (list, g_strdup (strv[ii]));
102 
103 	g_strfreev (strv);
104 
105 	return g_list_reverse (list);
106 }
107 
108 static void
composer_post_header_set_property(GObject * object,guint property_id,const GValue * value,GParamSpec * pspec)109 composer_post_header_set_property (GObject *object,
110                                    guint property_id,
111                                    const GValue *value,
112                                    GParamSpec *pspec)
113 {
114 	switch (property_id) {
115 		case PROP_MAIL_ACCOUNT:
116 			e_composer_post_header_set_mail_account (
117 				E_COMPOSER_POST_HEADER (object),
118 				g_value_get_object (value));
119 			return;
120 	}
121 
122 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
123 }
124 
125 static void
composer_post_header_get_property(GObject * object,guint property_id,GValue * value,GParamSpec * pspec)126 composer_post_header_get_property (GObject *object,
127                                    guint property_id,
128                                    GValue *value,
129                                    GParamSpec *pspec)
130 {
131 	switch (property_id) {
132 		case PROP_MAIL_ACCOUNT:
133 			g_value_set_object (
134 				value,
135 				e_composer_post_header_get_mail_account (
136 				E_COMPOSER_POST_HEADER (object)));
137 			return;
138 	}
139 
140 	G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
141 }
142 
143 static void
composer_post_header_dispose(GObject * object)144 composer_post_header_dispose (GObject *object)
145 {
146 	EComposerPostHeaderPrivate *priv;
147 
148 	priv = E_COMPOSER_POST_HEADER_GET_PRIVATE (object);
149 	g_clear_object (&priv->mail_account);
150 
151 	/* Chain up to parent's dispose() method. */
152 	G_OBJECT_CLASS (e_composer_post_header_parent_class)->dispose (object);
153 }
154 
155 static void
composer_post_header_finalize(GObject * object)156 composer_post_header_finalize (GObject *object)
157 {
158 	EComposerPostHeaderPrivate *priv;
159 
160 	priv = E_COMPOSER_POST_HEADER_GET_PRIVATE (object);
161 
162 	g_free (priv->base_url);
163 
164 	/* Chain up to parent's finalize() method. */
165 	G_OBJECT_CLASS (e_composer_post_header_parent_class)->finalize (object);
166 }
167 
168 static void
composer_post_header_constructed(GObject * object)169 composer_post_header_constructed (GObject *object)
170 {
171 	/* Chain up to parent's constructed() method. */
172 	G_OBJECT_CLASS (e_composer_post_header_parent_class)->constructed (object);
173 
174 	e_composer_header_set_title_tooltip (
175 		E_COMPOSER_HEADER (object),
176 		_("Click here to select folders to post to"));
177 }
178 
179 static void
composer_post_header_changed(EComposerHeader * header)180 composer_post_header_changed (EComposerHeader *header)
181 {
182 	EComposerPostHeaderPrivate *priv;
183 
184 	priv = E_COMPOSER_POST_HEADER_GET_PRIVATE (header);
185 
186 	priv->custom = TRUE;
187 }
188 
189 static void
composer_post_header_clicked(EComposerHeader * header)190 composer_post_header_clicked (EComposerHeader *header)
191 {
192 	EComposerPostHeaderPrivate *priv;
193 
194 	priv = E_COMPOSER_POST_HEADER_GET_PRIVATE (header);
195 
196 	priv->custom = FALSE;
197 }
198 
199 static void
e_composer_post_header_class_init(EComposerPostHeaderClass * class)200 e_composer_post_header_class_init (EComposerPostHeaderClass *class)
201 {
202 	GObjectClass *object_class;
203 	EComposerHeaderClass *header_class;
204 
205 	g_type_class_add_private (class, sizeof (EComposerPostHeaderPrivate));
206 
207 	object_class = G_OBJECT_CLASS (class);
208 	object_class->set_property = composer_post_header_set_property;
209 	object_class->get_property = composer_post_header_get_property;
210 	object_class->dispose = composer_post_header_dispose;
211 	object_class->finalize = composer_post_header_finalize;
212 	object_class->constructed = composer_post_header_constructed;
213 
214 	header_class = E_COMPOSER_HEADER_CLASS (class);
215 	header_class->changed = composer_post_header_changed;
216 	header_class->clicked = composer_post_header_clicked;
217 
218 	g_object_class_install_property (
219 		object_class,
220 		PROP_MAIL_ACCOUNT,
221 		g_param_spec_object (
222 			"mail-account",
223 			NULL,
224 			NULL,
225 			E_TYPE_SOURCE,
226 			G_PARAM_READWRITE));
227 }
228 
229 static void
e_composer_post_header_init(EComposerPostHeader * header)230 e_composer_post_header_init (EComposerPostHeader *header)
231 {
232 	header->priv = E_COMPOSER_POST_HEADER_GET_PRIVATE (header);
233 }
234 
235 EComposerHeader *
e_composer_post_header_new(ESourceRegistry * registry,const gchar * label)236 e_composer_post_header_new (ESourceRegistry *registry,
237                             const gchar *label)
238 {
239 	g_return_val_if_fail (E_IS_SOURCE_REGISTRY (registry), NULL);
240 
241 	return g_object_new (
242 		E_TYPE_COMPOSER_POST_HEADER,
243 		"label", label, "button", TRUE,
244 		"registry", registry, NULL);
245 }
246 
247 GList *
e_composer_post_header_get_folders(EComposerPostHeader * header)248 e_composer_post_header_get_folders (EComposerPostHeader *header)
249 {
250 	GList *folders, *iter;
251 	gchar *base_url;
252 
253 	g_return_val_if_fail (E_IS_COMPOSER_POST_HEADER (header), NULL);
254 
255 	folders = composer_post_header_split_csv (
256 		e_composer_text_header_get_text (
257 		E_COMPOSER_TEXT_HEADER (header)));
258 
259 	base_url = header->priv->base_url;
260 	if (base_url == NULL)
261 		return folders;
262 
263 	for (iter = folders; iter != NULL; iter = iter->next) {
264 		/* Convert relative folder names to absolute. */
265 		/* XXX Should use CamelURL for this. */
266 		if (strstr (iter->data, ":/") == NULL) {
267 			gchar *abs_url;
268 
269 			abs_url = g_strconcat (base_url, iter->data, NULL);
270 			g_free (iter->data);
271 			iter->data = abs_url;
272 		}
273 	}
274 
275 	return folders;
276 }
277 
278 void
e_composer_post_header_set_folders(EComposerPostHeader * header,GList * folders)279 e_composer_post_header_set_folders (EComposerPostHeader *header,
280                                     GList *folders)
281 {
282 	GList *iter;
283 	gint ii = 0;
284 	gchar **strv;
285 	gchar *text;
286 	gboolean custom_save;
287 
288 	g_return_if_fail (E_IS_COMPOSER_POST_HEADER (header));
289 
290 	strv = g_new0 (gchar *, g_list_length (folders) + 1);
291 
292 	for (iter = folders; iter != NULL; iter = iter->next)
293 		strv[ii++] = composer_post_header_folder_name_to_string (
294 			header, iter->data);
295 
296 	text = g_strjoinv (", ", strv);
297 	custom_save = header->priv->custom;
298 	e_composer_text_header_set_text (
299 		E_COMPOSER_TEXT_HEADER (header), text);
300 	header->priv->custom = custom_save;
301 	g_free (text);
302 
303 	g_strfreev (strv);
304 }
305 
306 void
e_composer_post_header_set_folders_base(EComposerPostHeader * header,const gchar * base_url,const gchar * folders)307 e_composer_post_header_set_folders_base (EComposerPostHeader *header,
308                                          const gchar *base_url,
309                                          const gchar *folders)
310 {
311 	GList *list, *iter;
312 
313 	list = composer_post_header_split_csv (folders);
314 	for (iter = list; iter != NULL; iter = iter->next) {
315 		gchar *abs_url;
316 
317 		/* FIXME This doesn't handle all folder names properly. */
318 		abs_url = g_strdup_printf (
319 			"%s/%s", base_url, (gchar *) iter->data);
320 		g_free (iter->data);
321 		iter->data = abs_url;
322 	}
323 
324 	e_composer_post_header_set_folders (header, list);
325 	g_list_foreach (list, (GFunc) g_free, NULL);
326 	g_list_free (list);
327 }
328 
329 ESource *
e_composer_post_header_get_mail_account(EComposerPostHeader * header)330 e_composer_post_header_get_mail_account (EComposerPostHeader *header)
331 {
332 	g_return_val_if_fail (E_IS_COMPOSER_POST_HEADER (header), NULL);
333 
334 	return header->priv->mail_account;
335 }
336 
337 void
e_composer_post_header_set_mail_account(EComposerPostHeader * header,ESource * mail_account)338 e_composer_post_header_set_mail_account (EComposerPostHeader *header,
339                                          ESource *mail_account)
340 {
341 	GList *folders = NULL;
342 
343 	g_return_if_fail (E_IS_COMPOSER_POST_HEADER (header));
344 
345 	if (header->priv->mail_account == mail_account)
346 		return;
347 
348 	if (mail_account != NULL) {
349 		g_return_if_fail (E_IS_SOURCE (mail_account));
350 		g_object_ref (mail_account);
351 	}
352 
353 	if (!header->priv->custom)
354 		folders = e_composer_post_header_get_folders (header);
355 
356 	if (header->priv->mail_account != NULL)
357 		g_object_unref (header->priv->mail_account);
358 
359 	header->priv->mail_account = mail_account;
360 	composer_post_header_set_base_url (header);
361 
362 	/* Make folders relative to the new account. */
363 	if (!header->priv->custom) {
364 		e_composer_post_header_set_folders (header, folders);
365 		g_list_foreach (folders, (GFunc) g_free, NULL);
366 		g_list_free (folders);
367 	}
368 
369 	g_object_notify (G_OBJECT (header), "mail-account");
370 }
371