1 /*
2  * This program is free software; you can redistribute it and/or modify it
3  * under the terms of the GNU Lesser General Public License as published by
4  * the Free Software Foundation.
5  *
6  * This program is distributed in the hope that it will be useful, but
7  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
8  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
9  * for more details.
10  *
11  * You should have received a copy of the GNU Lesser General Public License
12  * along with this program; if not, see <http://www.gnu.org/licenses/>.
13  *
14  *
15  * Authors:
16  *		Dan Winship <danw@ximian.com>
17  *		Peter Williams <peterw@ximian.com>
18  *		Jeffrey Stedfast <fejj@ximian.com>
19  *
20  * Copyright (C) 1999-2008 Novell, Inc. (www.novell.com)
21  *
22  */
23 
24 #include "evolution-config.h"
25 
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29 #include <ctype.h>
30 #include <errno.h>
31 #include <string.h>
32 
33 #include <glib/gstdio.h>
34 
35 #include <glib/gi18n.h>
36 
37 #include "e-util/e-util.h"
38 #include "e-mail-session.h"
39 #include "mail-folder-cache.h"
40 #include "mail-tools.h"
41 
42 /* **************************************** */
43 
44 #ifndef G_OS_WIN32
45 
46 static gchar *
mail_tool_get_local_movemail_path(CamelStore * store,GError ** error)47 mail_tool_get_local_movemail_path (CamelStore *store,
48                                    GError **error)
49 {
50 	const gchar *uid;
51 	guchar *safe_uid, *c;
52 	const gchar *data_dir;
53 	gchar *path, *full;
54 	struct stat st;
55 
56 	uid = camel_service_get_uid (CAMEL_SERVICE (store));
57 	safe_uid = (guchar *) g_strdup ((const gchar *) uid);
58 	for (c = safe_uid; *c; c++)
59 		if (strchr ("/:;=|%&#!*^()\\, ", *c) || !isprint ((gint) *c))
60 			*c = '_';
61 
62 	data_dir = mail_session_get_data_dir ();
63 	path = g_build_filename (data_dir, "spool", NULL);
64 
65 	if (g_stat (path, &st) == -1 && g_mkdir_with_parents (path, 0700) == -1) {
66 		g_set_error (
67 			error, G_FILE_ERROR,
68 			g_file_error_from_errno (errno),
69 			_("Could not create spool directory “%s”: %s"),
70 			path, g_strerror (errno));
71 		g_free (path);
72 		return NULL;
73 	}
74 
75 	full = g_strdup_printf ("%s/movemail.%s", path, safe_uid);
76 	g_free (path);
77 	g_free (safe_uid);
78 
79 	return full;
80 }
81 
82 #endif
83 
84 gchar *
mail_tool_do_movemail(CamelStore * store,GError ** error)85 mail_tool_do_movemail (CamelStore *store,
86                        GError **error)
87 {
88 #ifndef G_OS_WIN32
89 	CamelService *service;
90 	CamelProvider *provider;
91 	CamelSettings *settings;
92 	gchar *src_path;
93 	gchar *dest_path;
94 	struct stat sb;
95 	gboolean success;
96 
97 	g_return_val_if_fail (CAMEL_IS_STORE (store), NULL);
98 
99 	service = CAMEL_SERVICE (store);
100 	provider = camel_service_get_provider (service);
101 
102 	g_return_val_if_fail (provider != NULL, NULL);
103 
104 	if (g_strcmp0 (provider->protocol, "mbox") != 0) {
105 		/* This is really only an internal error anyway */
106 		g_set_error (
107 			error, CAMEL_SERVICE_ERROR,
108 			CAMEL_SERVICE_ERROR_URL_INVALID,
109 			_("Trying to movemail a non-mbox source “%s”"),
110 			camel_service_get_uid (CAMEL_SERVICE (store)));
111 		return NULL;
112 	}
113 
114 	settings = camel_service_ref_settings (service);
115 
116 	src_path = camel_local_settings_dup_path (
117 		CAMEL_LOCAL_SETTINGS (settings));
118 
119 	g_object_unref (settings);
120 
121 	/* Set up our destination. */
122 	dest_path = mail_tool_get_local_movemail_path (store, error);
123 	if (dest_path == NULL)
124 		return NULL;
125 
126 	/* Movemail from source to dest_path */
127 	success = camel_movemail (src_path, dest_path, error) != -1;
128 
129 	g_free (src_path);
130 
131 	if (g_stat (dest_path, &sb) < 0 || sb.st_size == 0) {
132 		g_unlink (dest_path); /* Clean up the movemail.foo file. */
133 		g_free (dest_path);
134 		return NULL;
135 	}
136 
137 	if (!success) {
138 		g_free (dest_path);
139 		return NULL;
140 	}
141 
142 	return dest_path;
143 #else
144 	/* Unclear yet whether camel-movemail etc makes any sense on
145 	 * Win32, at least it is not ported yet.
146 	 */
147 	g_warning ("%s: Not implemented", G_STRFUNC);
148 	return NULL;
149 #endif
150 }
151 
152 gchar *
mail_tool_generate_forward_subject(CamelMimeMessage * msg)153 mail_tool_generate_forward_subject (CamelMimeMessage *msg)
154 {
155 	const gchar *orig_subject;
156 	gchar *subject = NULL;
157 	gchar *fwd_subj;
158 	const gint max_subject_length = 1024;
159 	const gchar *format;
160 	GSettings *settings;
161 
162 	orig_subject = camel_mime_message_get_subject (msg);
163 
164 	if (orig_subject && *orig_subject) {
165 		gchar *utf8;
166 
167 		utf8 = e_util_utf8_make_valid (orig_subject);
168 		if (utf8 && *utf8) {
169 			/* Truncate insanely long subjects */
170 			if (g_utf8_strlen (utf8, -1) < max_subject_length) {
171 				subject = utf8;
172 				utf8 = NULL;
173 			} else {
174 				gchar *end = g_utf8_offset_to_pointer (utf8, max_subject_length);
175 
176 				if (end) {
177 					*end = '\0';
178 
179 					subject = g_strconcat (utf8, "...", NULL);
180 				}
181 			}
182 		}
183 
184 		g_free (utf8);
185 	}
186 
187 	if (!subject) {
188 		const CamelInternetAddress *from;
189 
190 		from = camel_mime_message_get_from (msg);
191 		if (from)
192 			subject = camel_address_format (CAMEL_ADDRESS (from));
193 	}
194 
195 	settings = e_util_ref_settings ("org.gnome.evolution.mail");
196 	if (g_settings_get_boolean (settings, "composer-use-localized-fwd-re")) {
197 		/* Translators: This is a subject attribution for forwarded messages. The %s is replaced with subject of the original message. */
198 		format = _("Fwd: %s");
199 	} else {
200 		/* Do not localize this string */
201 		format = "Fwd: %s";
202 	}
203 	g_clear_object (&settings);
204 
205 	fwd_subj = g_strdup_printf (format,
206 		/* Translators: This is a subject attribution for forwarded messages, used when there could not be used any subject.
207 	           It results in "[Fwd: No Subject]" being used as a subject of the forwarded message. */
208 		(subject && *subject) ? subject : _("No Subject"));
209 
210 	g_free (subject);
211 
212 	return fwd_subj;
213 }
214 
215 CamelNameValueArray *
mail_tool_remove_xevolution_headers(CamelMimeMessage * message)216 mail_tool_remove_xevolution_headers (CamelMimeMessage *message)
217 {
218 	CamelNameValueArray *orig_headers, *removed_headers = NULL;
219 	CamelMedium *medium;
220 	guint ii, len;
221 
222 	g_return_val_if_fail (CAMEL_IS_MIME_MESSAGE (message), NULL);
223 
224 	medium = CAMEL_MEDIUM (message);
225 	orig_headers = camel_medium_dup_headers (medium);
226 	len = camel_name_value_array_get_length (orig_headers);
227 
228 	for (ii = 0; ii < len; ii++) {
229 		const gchar *header_name = NULL, *header_value = NULL;
230 
231 		if (!camel_name_value_array_get (orig_headers, ii, &header_name, &header_value) || !header_name)
232 			continue;
233 
234 		if (g_ascii_strncasecmp (header_name, "X-Evolution", 11) == 0) {
235 			if (!removed_headers)
236 				removed_headers = camel_name_value_array_new ();
237 
238 			camel_name_value_array_append (removed_headers, header_name, header_value);
239 
240 			camel_medium_remove_header (medium, header_name);
241 		}
242 	}
243 
244 	camel_name_value_array_free (orig_headers);
245 
246 	return removed_headers;
247 }
248 
249 void
mail_tool_restore_xevolution_headers(CamelMimeMessage * message,CamelNameValueArray * headers)250 mail_tool_restore_xevolution_headers (CamelMimeMessage *message,
251                                       CamelNameValueArray *headers)
252 {
253 	CamelMedium *medium;
254 	guint ii, len;
255 
256 	g_return_if_fail (CAMEL_IS_MIME_MESSAGE (message));
257 
258 	if (!headers)
259 		return;
260 
261 	medium = CAMEL_MEDIUM (message);
262 	len = camel_name_value_array_get_length (headers);
263 
264 	for (ii = 0; ii < len; ii++) {
265 		const gchar *header_name = NULL, *header_value = NULL;
266 
267 		if (!camel_name_value_array_get (headers, ii, &header_name, &header_value) || !header_name)
268 			continue;
269 
270 		camel_medium_add_header (medium, header_name, header_value);
271 	}
272 }
273 
274 CamelMimePart *
mail_tool_make_message_attachment(CamelMimeMessage * message)275 mail_tool_make_message_attachment (CamelMimeMessage *message)
276 {
277 	CamelMimePart *part;
278 	const gchar *subject;
279 	gchar *desc;
280 
281 	subject = camel_mime_message_get_subject (message);
282 	if (subject)
283 		desc = g_strdup_printf (_("Forwarded message — %s"), subject);
284 	else
285 		desc = g_strdup (_("Forwarded message"));
286 
287 	/* rip off the X-Evolution headers */
288 	camel_name_value_array_free (mail_tool_remove_xevolution_headers (message));
289 
290 	/* remove Bcc headers */
291 	camel_medium_remove_header (CAMEL_MEDIUM (message), "Bcc");
292 
293 	part = camel_mime_part_new ();
294 	camel_mime_part_set_disposition (part, "inline");
295 	camel_mime_part_set_description (part, desc);
296 	camel_medium_set_content (
297 		CAMEL_MEDIUM (part), CAMEL_DATA_WRAPPER (message));
298 	camel_mime_part_set_content_type (part, "message/rfc822");
299 	g_free (desc);
300 
301 	return part;
302 }
303