1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */
2 /* Various utilities for the mbox provider */
6 * Bertrand Guiheneuf <bertrand@helixcode.com>
8 * Copyright (C) 1999 Helix Code.
10 * This program is free software; you can redistribute it and/or
11 * modify it under the terms of the GNU General Public License as
12 * published by the Free Software Foundation; either version 2 of the
13 * License, or (at your option) any later version.
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
20 * You should have received a copy of the GNU General Public License
21 * along with this program; if not, write to the Free Software
22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
27 /* "xev" stands for x-evolution, which is the name of the
28 * evolution specific header where are stored informations
35 * The evolution line ha10s the following format :
41 * the UID is internally used as a 32 bits long integer, but only the first 24 bits are
42 * used. The UID is coded as a string on 4 characters. Each character is a 6 bits
43 * integer coded using the b64 alphabet.
48 #include <sys/types.h>
58 #include "camel-mbox-utils.h"
59 #include "camel-mbox-parser.h"
63 static gchar b64_alphabet[64] =
64 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
69 uid_to_string (guint32 uid, gchar string[4])
72 string [0] = b64_alphabet [(uid >> 18) & 0x3f];
73 string [1] = b64_alphabet [(uid >> 12) & 0x3f];
74 string [2] = b64_alphabet [(uid >> 6) & 0x3f];
75 string [3] = b64_alphabet [(uid ) & 0x3f];
80 string_to_uid (gchar *string)
85 (((string [0] >= 97) ? ( string [0] - 71 ) :
86 ((string [0] >= 65) ? ( string [0] - 65 ) :
87 ((string [0] >= 48) ? ( string [0] + 4 ) :
88 ((string [0] == 43) ? 62 : 63 )))) << 18)
90 + (((string [1] >= 97) ? ( string [1] - 71 ) :
91 ((string [1] >= 65) ? ( string [1] - 65 ) :
92 ((string [1] >= 48) ? ( string [1] + 4 ) :
93 ((string [1] == 43) ? 62 : 63 )))) << 12)
96 + ((((string [2] >= 97) ? ( string [2] - 71 ) :
97 ((string [2] >= 65) ? ( string [2] - 65 ) :
98 ((string [2] >= 48) ? ( string [2] + 4 ) :
99 ((string [2] == 43) ? 62 : 63 ))))) << 6)
102 + (((string [3] >= 97) ? ( string [3] - 71 ) :
103 ((string [3] >= 65) ? ( string [3] - 65 ) :
104 ((string [3] >= 48) ? ( string [3] + 4 ) :
105 ((string [3] == 43) ? 62 : 63 )))));
113 flag_to_string (guchar status)
115 return b64_alphabet [status & 0x3f];
120 string_to_flag (gchar string)
122 return (string >= 97) ? ( string - 71 ) :
123 ((string >= 65) ? ( string - 65 ) :
124 ((string >= 48) ? ( string + 4 ) :
125 ((string == 43) ? 62 : 63 )));
133 camel_mbox_xev_parse_header_content (gchar header_content[6],
138 /* we assume that the first 4 characters of the header content
139 are actually the uid stuff. If somebody messed with it ...
142 *uid = string_to_uid (header_content);
143 status = string_to_flag (header_content[5]);
147 camel_mbox_xev_write_header_content (gchar header_content[6],
151 uid_to_string (uid, header_content);
152 header_content[5] = flag_to_string (status);
153 header_content[4] = '-';
162 copy_file_chunk (gint fd_src,
172 nb_to_read = nb_bytes;
173 while (nb_to_read > 0) {
176 nb_read = read (fd_src, buffer, MIN (1000, nb_to_read));
177 } while (nb_read == -1 && errno == EINTR);
180 camel_exception_set (ex,
181 CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION,
182 "could read from the mbox file");
187 nb_to_read -= nb_read;
190 v = write (fd_dest, buffer, nb_read);
191 } while (v == -1 && errno == EINTR);
194 camel_exception_setv (ex,
195 CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION,
196 "could not write to the mbox copy file\n"
197 "Full error is : %s\n",
211 camel_mbox_write_xev (gchar *mbox_file_name,
212 GArray *summary_information,
217 CamelMboxParserMessageInfo *cur_msg_info;
219 guint bytes_to_copy = 0;
221 glong cur_offset = 0;
222 glong end_of_last_message;
224 gchar xev_header[20] = "X-Evolution:XXXX-X\n";
225 gchar *tmp_file_name;
226 gchar *tmp_file_name_secure;
230 tmp_file_name = g_strdup_printf ("%s__.ev_tmp", mbox_file_name);
231 tmp_file_name_secure = g_strdup_printf ("%s__.ev_tmp_secure", mbox_file_name);
233 fd1 = open (mbox_file_name, O_RDONLY);
234 fd2 = open (tmp_file_name, O_WRONLY | O_CREAT | O_TRUNC );
236 camel_exception_setv (ex,
237 CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION,
238 "could not create the temporary mbox copy file\n"
240 "Full error is : %s\n",
246 next_free_uid = next_uid;
247 for (cur_msg = 0; cur_msg < summary_information->len; cur_msg++) {
249 cur_msg_info = (CamelMboxParserMessageInfo *)(summary_information->data) + cur_msg;
250 end_of_last_message = cur_msg_info->message_position + cur_msg_info->size;
252 if ( !cur_msg_info->x_evolution) {
254 bytes_to_copy = cur_msg_info->message_position
255 + cur_msg_info->end_of_headers_offset
258 cur_pos = cur_msg_info->message_position
259 + cur_msg_info->end_of_headers_offset;
261 copy_file_chunk (fd1, fd2, bytes_to_copy, ex);
262 if (camel_exception_get_id (ex)) {
268 printf ("Writing the x-ev header\n");
269 printf ("Current message number : %d\n", cur_msg);
270 camel_mbox_xev_write_header_content (xev_header + 12, next_free_uid++, 0);
271 write (fd2, xev_header, 19);
273 cur_msg_info->size += 19;
274 cur_msg_info->x_evolution_offset = cur_msg_info->end_of_headers_offset;
275 cur_msg_info->x_evolution = g_strdup_printf ("%.6s", xev_header + 12);
276 cur_msg_info->end_of_headers_offset += 19;
278 cur_msg_info->message_position += cur_offset;
281 bytes_to_copy = end_of_last_message - cur_pos;
282 copy_file_chunk (fd1, fd2, bytes_to_copy, ex);
285 /* close the original file as well as the
292 /* replace the mbox file with the temporary
293 file we just created */
295 /* first rename the old mbox file to a temporary file */
296 rename_result = rename (mbox_file_name, tmp_file_name_secure);
297 if (rename_result == -1) {
298 camel_exception_set (ex,
299 CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION,
300 "could not rename the mbox file to a temporary file");
304 /* then rename the newly created mbox file to the name
305 of the original one */
306 rename_result = rename (tmp_file_name, mbox_file_name);
307 if (rename_result == -1) {
308 camel_exception_set (ex,
309 CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION,
310 "could not rename the X-Evolution fed file to the mbox file");
314 /* finally, remove the old renamed mbox file */
315 unlink_result = unlink (tmp_file_name_secure);
316 if (unlink_result == -1) {
317 camel_exception_set (ex,
318 CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION,
319 "could not remove the saved original mbox file");
324 end: /* free everything and return */
326 g_free (tmp_file_name);
327 g_free (tmp_file_name_secure);
328 return next_free_uid;