From fed684880e2a47aaa0ee109bd8df0db1a5589c79 Mon Sep 17 00:00:00 2001 From: NotZed Date: Mon, 1 May 2000 19:47:12 +0000 Subject: More message cleanup. Flags now work, are saved, and the delete flag causes an expunge to expunge the deleted messages. 2000-05-01 NotZed * providers/mbox/camel-mbox-summary.c (camel_mbox_summary_set_flags_by_uid): New function to update the flags in the summary. (camel_mbox_summary_expunge): Expunge messages from a folder. (offset_content): Re-align offsets of summary when messages added/removed to an existing summary. (camel_mbox_summary_remove_uid): Remove a message summary entry by uid. (index_folder): Restore flags from X-Evolution header, if they are set. * providers/mbox/camel-mbox-folder.c (_get_message_by_uid): Connect to the message_changed signal. (_init): Set permanent flags to something reasonable. No user flags yet ... (message_changed): If the flags of the message change, update the flags in the summary. (mbox_expunge): Implement the expunge. (camel_mbox_folder_class_init): Renamed all leading _'s to mbox_'s * camel-folder.c (_finalize): Uh, dont free permanent_flags anymore (this wouldn't failed anyway, it was a GList !!!) * camel-folder.h (struct _CamelFolder): Change permanent_flags to a bitfield. (list_permanent_flags): Renamed to get_permanent_flags, and returns a bitfield. (camel_folder_expunge): Changed expunge to a void type. The messages would no longer be useful after they have been removed ... * camel-mime-message.c (set_flag): Removed. (camel_mime_message_set_flag): Removed. (get_flag): Removed. (camel_mime_message_get_flag): Removed. (add_flag_to_list): Removed. (get_flag_list): Removed. (camel_mime_message_get_flag_list): Removed. (camel_mime_message_get_flags): New interface to get system flags. (camel_mime_message_set_flags): " to set ". (camel_mime_message_get_user_flag): To get a user flag. (camel_mime_message_set_user_flag): To set a user flag. (finalize): Hmm, the old one free'd the key and data, not good when the data is a boolean ... svn path=/trunk/; revision=2716 --- camel/providers/mbox/camel-mbox-summary.c | 225 +++++++++++++++++++++++++++++- 1 file changed, 224 insertions(+), 1 deletion(-) (limited to 'camel/providers/mbox/camel-mbox-summary.c') diff --git a/camel/providers/mbox/camel-mbox-summary.c b/camel/providers/mbox/camel-mbox-summary.c index 5608afc3df..4d10709fcd 100644 --- a/camel/providers/mbox/camel-mbox-summary.c +++ b/camel/providers/mbox/camel-mbox-summary.c @@ -29,6 +29,8 @@ #include +#include + #include #include #include @@ -374,6 +376,7 @@ message_struct_new(CamelMimeParser *mp, CamelMboxMessageContentInfo *parent, int ms->info.content = (CamelMessageContentInfo *)body_part_new(mp, parent, start, body); ms->xev_offset = xev_offset; + return ms; } @@ -674,6 +677,10 @@ error: #define SAVEIT +/* TODO: Allow to sync with current summary info, without over-writing flags if they + already exist there */ +/* TODO: Lazy sync, make this read-only, and dont write out xev headers unless we need + to? */ static int index_folder(CamelMboxSummary *s, int startoffset) { CamelMimeParser *mp; @@ -705,7 +712,7 @@ static int index_folder(CamelMboxSummary *s, int startoffset) int write_offset = 0; /* how much does the dest differ from the source pos */ int old_offset = 0; - guint32 newuid; + guint32 newuid, newflags; off_t xevoffset = -1; char *tmpname; @@ -761,6 +768,7 @@ static int index_folder(CamelMboxSummary *s, int startoffset) case HSCAN_MULTIPART: case HSCAN_HEADER: /* starting a new header */ newuid=~0; + newflags=0; if (!toplevel) { char name[32]; unsigned int olduid, oldflags; @@ -775,6 +783,7 @@ static int index_folder(CamelMboxSummary *s, int startoffset) if (header_evolution_decode(xev, &olduid, &oldflags) != ~0) { d(printf(" uid = %d = %x\n", olduid, olduid)); newuid = olduid; + newflags = oldflags; #if 0 while (camel_mime_parser_step(mp, &data, &datalen) != HSCAN_FROM_END) ; @@ -834,6 +843,7 @@ static int index_folder(CamelMboxSummary *s, int startoffset) parent = (CamelMboxMessageContentInfo *)message->info.content; if (newuid != ~0) { message->info.uid = g_strdup_printf("%u", newuid); + message->info.flags = newflags; } else { g_warning("This shouldn't happen?"); } @@ -848,6 +858,7 @@ static int index_folder(CamelMboxSummary *s, int startoffset) body = (CamelMboxMessageContentInfo *)message->info.content; if (newuid != ~0) { message->info.uid = g_strdup_printf("%u", newuid); + message->info.flags = newflags; } else { g_warning("This shouldn't happen?"); } @@ -1259,6 +1270,218 @@ guint32 camel_mbox_summary_set_uid(CamelMboxSummary *s, guint32 uid) return s->nextuid; } +void camel_mbox_summary_set_flags_by_uid(CamelMboxSummary *s, const char *uid, guint32 flags) +{ + CamelMessageInfo *info; + + info = (CamelMessageInfo *)camel_mbox_summary_uid(s, uid); + if (info != NULL) { + if (info->flags != flags) { + info->flags = flags | CAMEL_MESSAGE_FOLDER_FLAGGED; + s->dirty = TRUE; + } + } else { + g_warning("Message has dissapeared from summary? uid %s", uid); + } +} + +/* update offsets in the summary to take account deleted parts */ +static void +offset_content(CamelMboxMessageContentInfo *content, off_t offset) +{ + content->pos -= offset; + content->bodypos -= offset; + content->endpos -= offset; + content = (CamelMboxMessageContentInfo *)content->info.childs; + while (content) { + offset_content(content, offset); + content = (CamelMboxMessageContentInfo *)content->info.next; + } +} + +void camel_mbox_summary_remove_uid(CamelMboxSummary *s, const char *uid) +{ + CamelMboxMessageInfo *oldinfo; + char *olduid; + + if (g_hash_table_lookup_extended(s->message_uid, uid, (void *)&olduid, (void *)&oldinfo)) { +#if 0 + /* FIXME: this code should be executed to update the summary info, + however, only if we're not depending on the info not changing yet */ + off_t offset = info->endpos - info->pos; + int i, count, got = FALSE; + + count = s->messages->len; + for (i=0;imessages, i); + if (got) { + offset_content(minfo, offset); + } else if (minfo == info) { + got = TRUE; + } + } +#endif + g_hash_table_remove(s->message_uid, uid); + g_ptr_array_remove(s->messages, oldinfo); + message_struct_free(oldinfo); + g_free(olduid); + } +} + +/* perform expunge/update xev headers, etc */ +/* TODO: merge this with the indexing code, so that it can index new parts + without having to reread everything again? */ +/* TODO: sync with the mbox, if it has changed */ +int +camel_mbox_summary_expunge(CamelMboxSummary *s) +{ + int quick = TRUE, work=FALSE; + int i, count; + CamelMboxMessageInfo *info; + + printf("Executing expunge ...\n"); + + count = camel_mbox_summary_message_count(s); + for (i=0;quick && ixev_offset == -1 || info->info.flags & CAMEL_MESSAGE_DELETED) + quick = FALSE; + else + work |= (info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) != 0; + } + if (quick) { + int fd; + char name[32]; + + if (!work) + return 0; + + camel_mbox_summary_save(s); + + fd = open(s->folder_path, O_WRONLY); + + if (fd == -1) { + g_error("Cannot open folder for update: %s", strerror(errno)); + return -1; + } + + /* poke in the new xev info */ + for (i=0;ixev_offset != -1); + if (info->info.flags & CAMEL_MESSAGE_FOLDER_FLAGGED) { + printf("Setting new flags to message %s = %04x\n", info->info.uid, info->info.flags & 0xffff); + lseek(fd, info->xev_offset, SEEK_SET); + sprintf(name, "X-Evolution: %08x-%04x\n\n", (unsigned int)strtoul(info->info.uid, NULL, 10), info->info.flags & 0xffff); + write(fd, name, strlen(name)); + info->info.flags &= ~CAMEL_MESSAGE_FOLDER_FLAGGED; + } + } + close(fd); + } else { + char *tmpname; + int fd, fdout; + int last_write = 0, offset = 0, summary_end = 0, last_start = 0; + CamelMboxMessageContentInfo *content; + struct stat st; + + printf("We must expunge messages and/or write headers\n"); + + /* FIXME: This should check the current summary is correct */ + + /* we have to write out new headers or delete messages, starting from message i */ + + fd = open(s->folder_path, O_RDONLY); + if (fd == -1) { + g_error("Cannot open folder for read: %s", strerror(errno)); + return -1; + } + + tmpname = g_strdup_printf("%s.tmp", s->folder_path); + fdout = open(tmpname, O_WRONLY|O_CREAT|O_TRUNC, 0600); + if (fdout == -1) { + g_error("Cannot open tmp file for write: %s", strerror(errno)); + close(fd); + g_free(tmpname); + return -1; + } + + for (i=0;iinfo.content); + + content = (CamelMboxMessageContentInfo *)info->info.content; + + /* FIXME: Must also write out xev headers etc, as appropriate? */ + + /* we need to use the end of the previous message, becuase the beginning of + this message doesn't include the "^From " line. */ + + /* do we remove this message? */ + if (info->info.flags & CAMEL_MESSAGE_DELETED) { + printf("Deleting message: %s\n", info->info.uid); + camel_mbox_summary_copy_block(fd, fdout, last_write, last_start-last_write); + last_write = content->endpos; + last_start = last_write; + offset += (content->endpos - content->pos); + + /* remove this message from the index */ + if (s->index) { + char name[32]; + + sprintf(name, "%x", info->info.uid); + ibex_unindex(s->index, name); + } + + camel_mbox_summary_remove_uid(s, info->info.uid); + i--; /* redo this index */ + count--; + } else { + printf("Keeping message: %s\n", info->info.uid); + last_start = content->endpos; + offset_content(content, offset); + summary_end = content->endpos; + } + } + /* copy the rest of the file ... */ + camel_mbox_summary_copy_block(fd, fdout, last_write, INT_MAX); + + close(fd); + if (close(fdout) == -1) { + g_error("Cannot close tmp folder: %s", strerror(errno)); + unlink(tmpname); + g_free(tmpname); + return -1; + } + + if (rename(tmpname, s->folder_path) == -1) { + g_error("Cannot rename folder: %s", strerror(errno)); + unlink(tmpname); + g_free(tmpname); + return -1; + } + + /* force an index sync */ + if (s->index) { + ibex_write(s->index); + } + + /* update summary size to match the actual (written) folder size ... */ + s->size = summary_end; + /* and the time to match the newly written time, so we dont update needlessly */ + if (stat(s->folder_path, &st) == 0) { + s->time = st.st_mtime; + } + + camel_mbox_summary_save(s); + } + + return 0; +} + + #if 0 int main(int argc, char **argv) { -- cgit v1.2.3