From 79cda322e2840620d98411c9d7ec9226c365b922 Mon Sep 17 00:00:00 2001 From: bertrand Date: Mon, 17 Jan 2000 05:25:36 +0000 Subject: A bunch of new funcs to handle x-evolution private header field. 2000-01-17 bertrand * camel/providers/mbox/camel-mbox-utils.c (camel_mbox_write_xev): (copy_file_chunk): (camel_mbox_xev_write_header_content): (camel_mbox_xev_parse_header_content): (string_to_flag): (flag_to_string): (string_to_uid): (uid_to_string): A bunch of new funcs to handle x-evolution private header field. Various others modifications and fixes. svn path=/trunk/; revision=1576 --- camel/providers/mbox/Makefile.am | 6 +- camel/providers/mbox/camel-mbox-folder.c | 3 +- camel/providers/mbox/camel-mbox-parser.c | 35 +++- camel/providers/mbox/camel-mbox-parser.h | 10 +- camel/providers/mbox/camel-mbox-utils.c | 313 +++++++++++++++++++++++++++++++ camel/providers/mbox/camel-mbox-utils.h | 59 ++++++ 6 files changed, 412 insertions(+), 14 deletions(-) create mode 100644 camel/providers/mbox/camel-mbox-utils.c create mode 100644 camel/providers/mbox/camel-mbox-utils.h (limited to 'camel/providers') diff --git a/camel/providers/mbox/Makefile.am b/camel/providers/mbox/Makefile.am index 3943cd7a8c..247ce55f1d 100644 --- a/camel/providers/mbox/Makefile.am +++ b/camel/providers/mbox/Makefile.am @@ -14,12 +14,14 @@ INCLUDES = -I.. -I$(srcdir)/.. -I$(includedir) \ libcamelmbox_la_SOURCES = \ camel-mbox-folder.c \ camel-mbox-store.c \ - camel-mbox-parser.c + camel-mbox-parser.c \ + camel-mbox-utils.c libcamelmboxinclude_HEADERS = \ camel-mbox-folder.h \ camel-mbox-store.h \ - camel-mbox-parser.h + camel-mbox-parser.h \ + camel-mbox-utils.h libcamelmbox_la_LDFLAGS = -version-info 0:0:0 -rpath $(libdir) diff --git a/camel/providers/mbox/camel-mbox-folder.c b/camel/providers/mbox/camel-mbox-folder.c index 674f56c193..c502a190fd 100644 --- a/camel/providers/mbox/camel-mbox-folder.c +++ b/camel/providers/mbox/camel-mbox-folder.c @@ -3,7 +3,7 @@ /* * - * Copyright (C) 1999 Bertrand Guiheneuf . + * Copyright (C) 1999 Helix Code . * * This program is free software; you can redistribute it and/or * modify it under the terms of the GNU General Public License as @@ -21,6 +21,7 @@ * USA */ +/* Author : Bertrand Guiheneuf */ #include diff --git a/camel/providers/mbox/camel-mbox-parser.c b/camel/providers/mbox/camel-mbox-parser.c index 2509a5a49a..87752be417 100644 --- a/camel/providers/mbox/camel-mbox-parser.c +++ b/camel/providers/mbox/camel-mbox-parser.c @@ -63,7 +63,7 @@ typedef struct { int fd; /* file descriptor of the mbox file */ - guint real_position; /* real position in the file */ + glong real_position; /* real position in the file */ gchar *message_delimiter; /* message delimiter string */ @@ -96,12 +96,20 @@ static void clear_message_info (CamelMboxParserMessageInfo *preparsing_info) { preparsing_info->message_position = 0; + preparsing_info->size = 0; preparsing_info->from = NULL; preparsing_info->date = NULL; preparsing_info->subject = NULL; preparsing_info->status = NULL; preparsing_info->priority = NULL; preparsing_info->references = NULL; + preparsing_info->body_summary = NULL; + preparsing_info->end_of_headers_offset = 0; + + preparsing_info->x_evolution = NULL; + preparsing_info->x_evolution_offset = 0; + /* reparsing_info->x_evolution_length = 0; */ + } @@ -153,7 +161,7 @@ new_parser (int fd, * information array, i.e. the preparsed_messages * field. **/ -void +static void parser_free (CamelMboxPreParser *parser) { g_free (parser->buffer); @@ -177,7 +185,7 @@ parser_free (CamelMboxPreParser *parser) **/ static void initialize_buffer (CamelMboxPreParser *parser, - guint first_position) + glong first_position) { gint seek_res; gint buf_nb_read; @@ -390,7 +398,6 @@ new_message_detected (CamelMboxPreParser *parser) * after the "\n" at the end of the header content. * **/ -*/ static void read_header (CamelMboxPreParser *parser, gchar **header_content) { @@ -548,7 +555,7 @@ read_message_begining (CamelMboxPreParser *parser, gchar **message_summary) GArray * camel_mbox_parse_file (int fd, const gchar *message_delimiter, - guint start_position, + glong start_position, gboolean get_message_summary, camel_mbox_preparser_status_callback *status_callback, double status_interval, @@ -559,7 +566,7 @@ camel_mbox_parse_file (int fd, gchar c; struct stat stat_buf; gint fstat_result; - guint total_file_size; + glong total_file_size; int last_status = 0; int real_interval; gboolean newline; @@ -672,11 +679,20 @@ camel_mbox_parse_file (int fd, MBOX_PARSER_X_EVOLUTION_KW, MBOX_PARSER_X_EVOLUTION_KW_SZ) == 0) { + /* in the case of the evolution private field, we store + the field position as well as its length because + we will have to change them */ + parser->current_message_info.x_evolution_offset = parser->real_position + - parser->current_message_info.message_position; advance_n_chars (parser, MBOX_PARSER_X_EVOLUTION_KW_SZ); read_header (parser, (gchar **) ((gchar *)parser + G_STRUCT_OFFSET (CamelMboxPreParser, current_message_info) + G_STRUCT_OFFSET (CamelMboxParserMessageInfo, x_evolution))); + /* + parser->current_message_info.x_evolution_length = + parser->real_position - parser->current_message_info.x_evolution_position; + */ newline = TRUE; continue; } @@ -687,6 +703,9 @@ camel_mbox_parse_file (int fd, /* is it an empty line ? */ if (parser->buffer[parser->current_position] == '\n') { + parser->current_message_info.end_of_headers_offset = + parser->real_position - parser->current_message_info.message_position; + goto_next_char (parser); if (get_message_summary) newline = read_message_begining (parser, (gchar **) ((gchar *)parser + @@ -708,9 +727,8 @@ camel_mbox_parse_file (int fd, G_STRUCT_OFFSET (CamelMboxPreParser, current_message_info), 1); } - - return_value = parser->preparsed_messages; + /* free the parser */ parser_free (parser); @@ -756,6 +774,7 @@ main (int argc, char **argv) test_file_fd = open (argv[1], O_RDONLY); message_positions = camel_mbox_parse_file (test_file_fd, "From ", + 0, TRUE, status, diff --git a/camel/providers/mbox/camel-mbox-parser.h b/camel/providers/mbox/camel-mbox-parser.h index b8d2e93dc6..a4b3af9aff 100644 --- a/camel/providers/mbox/camel-mbox-parser.h +++ b/camel/providers/mbox/camel-mbox-parser.h @@ -28,8 +28,8 @@ typedef struct { - guint message_position; - guint size; + glong message_position; + glong size; gchar *from; gchar *date; gchar *subject; @@ -37,7 +37,11 @@ typedef struct { gchar *priority; gchar *references; gchar *body_summary; + gshort end_of_headers_offset; + gchar *x_evolution; + gshort x_evolution_offset; + /* gshort x_evolution_length; */ } CamelMboxParserMessageInfo; @@ -48,7 +52,7 @@ typedef void camel_mbox_preparser_status_callback (double percentage_done, gpoin GArray * camel_mbox_parse_file (int fd, const gchar *message_delimiter, - guint start_position, + glong start_position, gboolean get_message_summary, camel_mbox_preparser_status_callback *status_callback, double status_interval, diff --git a/camel/providers/mbox/camel-mbox-utils.c b/camel/providers/mbox/camel-mbox-utils.c new file mode 100644 index 0000000000..9eb4bd1f0d --- /dev/null +++ b/camel/providers/mbox/camel-mbox-utils.c @@ -0,0 +1,313 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* Various utilities for the mbox provider */ + +/* + * Authors : + * Bertrand Guiheneuf + * + * Copyright (C) 1999 Helix Code. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + + +/* "xev" stands for x-evolution, which is the name of the + * evolution specific header where are stored informations + * like : + * - mail status + * - mail uid + * ... + * + * + * The evolution line ha10s the following format : + * + * X-Evolution:XXXXX-X + * \___/ \/ + * UID ---' `- Status + * + * the UID is internally used as a 32 bits long integer, but only the first 24 bits are + * used. The UID is coded as a string on 4 characters. Each character is a 6 bits + * integer coded using the b64 alphabet. + * + */ + + +#include +#include +#include +#include +#include +#include + + +#include +#include "camel-mbox-utils.h" +#include "camel-mbox-parser.h" + + + +static gchar b64_alphabet[64] = +"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + + + +static void +uid_to_string (guint32 uid, gchar string[4]) +{ + + string [0] = b64_alphabet [(uid >> 18) & 0x3f]; + string [1] = b64_alphabet [(uid >> 12) & 0x3f]; + string [2] = b64_alphabet [(uid >> 6) & 0x3f]; + string [3] = b64_alphabet [(uid ) & 0x3f]; +} + + +static guint32 +string_to_uid (gchar *string) +{ + guint32 i; + + i = + (((string [0] >= 97) ? ( string [0] - 71 ) : + ((string [0] >= 65) ? ( string [0] - 65 ) : + ((string [0] >= 48) ? ( string [0] + 4 ) : + ((string [0] == 43) ? 62 : 63 )))) << 18) + + + (((string [1] >= 97) ? ( string [1] - 71 ) : + ((string [1] >= 65) ? ( string [1] - 65 ) : + ((string [1] >= 48) ? ( string [1] + 4 ) : + ((string [1] == 43) ? 62 : 63 )))) << 12) + + + + ((((string [2] >= 97) ? ( string [2] - 71 ) : + ((string [2] >= 65) ? ( string [2] - 65 ) : + ((string [2] >= 48) ? ( string [2] + 4 ) : + ((string [2] == 43) ? 62 : 63 ))))) << 6) + + + + (((string [3] >= 97) ? ( string [3] - 71 ) : + ((string [3] >= 65) ? ( string [3] - 65 ) : + ((string [3] >= 48) ? ( string [3] + 4 ) : + ((string [3] == 43) ? 62 : 63 ))))); + + return i; + +} + + +static gchar +flag_to_string (guchar status) +{ + return b64_alphabet [status & 0x3f]; +} + + +static guchar +string_to_flag (gchar string) +{ + return (string >= 97) ? ( string - 71 ) : + ((string >= 65) ? ( string - 65 ) : + ((string >= 48) ? ( string + 4 ) : + ((string == 43) ? 62 : 63 ))); +} + + + + + +void +camel_mbox_xev_parse_header_content (gchar header_content[6], + guint32 *uid, + guchar status) +{ + + /* we assume that the first 4 characters of the header content + are actually the uid stuff. If somebody messed with it ... + toooo bad. + */ + *uid = string_to_uid (header_content); + status = string_to_flag (header_content[5]); +} + +void +camel_mbox_xev_write_header_content (gchar header_content[6], + guint32 uid, + guchar status) +{ + uid_to_string (uid, header_content); + header_content[5] = flag_to_string (status); + header_content[4] = '-'; +} + + + + + + +static void +copy_file_chunk (gint fd_src, + gint fd_dest, + glong nb_bytes, + CamelException *ex) +{ + gchar buffer [1000]; + glong nb_to_read; + glong nb_read, v; + + + nb_to_read = nb_bytes; + while (nb_to_read > 0) { + + do { + nb_read = read (fd_src, buffer, MAX (1000, nb_to_read)); + } while (nb_read == -1 && errno == EINTR); + + if (nb_read == -1) { + camel_exception_set (ex, + CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION, + "could read from the mbox file"); + return; + } + + + nb_to_read -= nb_read; + + do { + v = write (fd_dest, buffer, nb_read); + } while (v == -1 && errno == EINTR); + + if (v == -1) { + camel_exception_set (ex, + CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION, + "could write to the mbox copy file"); + return; + } + + + } + + + +} + + +glong +camel_mbox_write_xev (gchar *mbox_file_name, + GArray *summary_information, + glong next_uid, + CamelException *ex) +{ + gint cur_msg; + CamelMboxParserMessageInfo *cur_msg_info; + gint fd1, fd2; + guint bytes_to_copy = 0; + glong next_free_uid; + gchar xev_header[20] = "X-Evolution:XXXX-X\n"; + gchar *tmp_file_name; + gchar *tmp_file_name_secure; + gint rename_result; + gint unlink_result; + + tmp_file_name = g_strdup_printf ("__%s__.ev_tmp", mbox_file_name); + tmp_file_name_secure = g_strdup_printf ("__%s__.ev_tmp_secure", mbox_file_name); + + fd1 = open (mbox_file_name, O_RDONLY); + fd2 = open (tmp_file_name, O_RDWR); + + next_free_uid = next_uid; + for (cur_msg = 0; cur_msg < summary_information->len; cur_msg++) { + + cur_msg_info = (CamelMboxParserMessageInfo *)(summary_information->data) + cur_msg; + if (cur_msg_info->x_evolution) { + + bytes_to_copy += cur_msg_info->size; + } else { + + bytes_to_copy += cur_msg_info->end_of_headers_offset; + copy_file_chunk (fd1, fd2, bytes_to_copy, ex); + if (camel_exception_get_id (ex)) { + close (fd1); + close (fd2); + goto end; + } + + camel_mbox_xev_write_header_content (xev_header + 12, next_free_uid++, 0); + write (fd2, xev_header, 19); + bytes_to_copy = cur_msg_info->size - cur_msg_info->end_of_headers_offset; + cur_msg_info->size += 19; + cur_msg_info->x_evolution_offset = cur_msg_info->end_of_headers_offset; + cur_msg_info->x_evolution = g_strdup_printf ("%.6s", xev_header + 12); + cur_msg_info->end_of_headers_offset += 19; + } + } + + if (bytes_to_copy > 0) + copy_file_chunk (fd1, fd2, bytes_to_copy, ex); + + + /* close the original file as well as the + newly created one */ + close (fd1); + close (fd2); + + + + /* replace the mbox file with the temporary + file we just created */ + + /* first rename the old mbox file to a temporary file */ + rename_result = rename (mbox_file_name, tmp_file_name_secure); + if (rename_result == -1) { + camel_exception_set (ex, + CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION, + "could not rename the mbox file to a temporary file"); + goto end; + } + + /* then rename the newly created mbox file to the name + of the original one */ + rename_result = rename (tmp_file_name, mbox_file_name); + if (rename_result == -1) { + camel_exception_set (ex, + CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION, + "could not rename the X-Evolution fed file to the mbox file"); + goto end; + } + + /* finally, remove the old renamed mbox file */ + unlink_result = unlink (tmp_file_name_secure); + if (unlink_result == -1) { + camel_exception_set (ex, + CAMEL_EXCEPTION_FOLDER_INSUFFICIENT_PERMISSION, + "could not remove the saved original mbox file"); + goto end; + } + + + end: /* free everything and return */ + + g_free (tmp_file_name); + g_free (tmp_file_name_secure); + return next_free_uid; +} + + + + + + + + diff --git a/camel/providers/mbox/camel-mbox-utils.h b/camel/providers/mbox/camel-mbox-utils.h new file mode 100644 index 0000000000..cacabd2f19 --- /dev/null +++ b/camel/providers/mbox/camel-mbox-utils.h @@ -0,0 +1,59 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: t; c-basic-offset: 8 -*- */ +/* Various utilities for the mbox provider */ + +/* + * Authors : + * Bertrand Guiheneuf + * + * Copyright (C) 1999 Helix Code. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 + * USA + */ + + +#ifndef CAMEL_MBOX_UTILS_H +#define CAMEL_MBOX_UTILS_H 1 + + +#ifdef __cplusplus +extern "C" { +#pragma } +#endif /* __cplusplus }*/ + + +#include "camel-exception.h" + +void +camel_mbox_xev_parse_header_content (gchar header_content[6], + guint32 *uid, + guchar status); + +void +camel_mbox_xev_write_header_content (gchar header_content[6], + guint32 uid, + guchar status); + +glong +camel_mbox_write_xev (gchar *mbox_file_name, + GArray *summary_information, + glong last_uid, + CamelException *ex); + +#ifdef __cplusplus +} +#endif /* __cplusplus */ + +#endif /* CAMEL_MBOX_UTILS_H */ -- cgit v1.2.3