diff options
-rw-r--r-- | camel/ChangeLog | 17 | ||||
-rw-r--r-- | camel/camel-movemail.c | 250 | ||||
-rw-r--r-- | camel/providers/mbox/camel-mbox-folder.c | 21 | ||||
-rw-r--r-- | camel/providers/mbox/camel-mbox-summary.c | 11 |
4 files changed, 292 insertions, 7 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index 7eddc455a8..fbd9dcb092 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,20 @@ +2000-05-16 NotZed <NotZed@HelixCode.com> + + * providers/mbox/camel-mbox-folder.c (mbox_delete_message_by_uid): + Implement. + +2000-05-12 NotZed <NotZed@HelixCode.com> + + * camel-movemail.c (camel_movemail): Open the destination with + O_APPEND, so we dont blow away a partially transferred mbox. + (camel_movemail): Loop if we get errno=INTR, and not fail. + +2000-05-11 NotZed <NotZed@HelixCode.com> + + * providers/mbox/camel-mbox-summary.c (summary_rebuild): Update + the summarised file size, if everything went ok. + (camel_mbox_summary_expunge): Clear header flags after updating. + 2000-05-16 Chris Toshok <toshok@helixcode.com> * providers/nntp/camel-nntp-folder.c: diff --git a/camel/camel-movemail.c b/camel/camel-movemail.c index e15e26e7ae..3ba3ee9efb 100644 --- a/camel/camel-movemail.c +++ b/camel/camel-movemail.c @@ -26,16 +26,28 @@ #include <config.h> #include <sys/stat.h> +#include <sys/uio.h> #include <errno.h> #include <fcntl.h> #include <stdlib.h> #include <stdio.h> #include <time.h> #include <unistd.h> +#include <string.h> #include "camel-movemail.h" #include "camel-exception.h" +#include "camel-mime-parser.h" +#include "camel-mime-filter.h" +#include "camel-mime-filter-from.h" + +#define d(x) + +/* these could probably be exposed as a utility? (but only mbox needs it) */ +static int camel_movemail_copy_filter(int fromfd, int tofd, off_t start, size_t bytes, CamelMimeFilter *filter); +static int camel_movemail_copy(int fromfd, int tofd, off_t start, size_t bytes); + /** * camel_movemail: Copy an mbox file from a shared spool directory to a * new folder in a Camel store @@ -91,7 +103,7 @@ camel_movemail (const char *source, const char *dest, CamelException *ex) return -1; } - dfd = open (dest, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR); + dfd = open (dest, O_WRONLY | O_CREAT | O_APPEND, S_IRUSR | S_IWUSR); if (dfd == -1) { camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, "Could not open temporary mail " @@ -199,6 +211,8 @@ camel_movemail (const char *source, const char *dest, CamelException *ex) if (nread == 0) break; else if (nread == -1) { + if (errno == EINTR) + continue; camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, "Error reading mail file: %s", g_strerror (errno)); @@ -209,6 +223,8 @@ camel_movemail (const char *source, const char *dest, CamelException *ex) while (nread) { nwrote = write (dfd, buf + written, nread); if (nwrote == -1) { + if (errno == EINTR) + continue; /* continues inner loop */ camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, "Error writing " "mail temp file: %s", @@ -250,3 +266,235 @@ camel_movemail (const char *source, const char *dest, CamelException *ex) return error ? -1 : 1; } + +static int +camel_movemail_copy(int fromfd, int tofd, off_t start, size_t bytes) +{ + char buffer[4096]; + int written = 0; + + d(printf("writing %d bytes ... ", bytes)); + + if (lseek(fromfd, start, SEEK_SET) != start) + return -1; + + while (bytes>0) { + int toread, towrite; + + toread = bytes; + if (bytes>4096) + toread = 4096; + else + toread = bytes; + do { + towrite = read(fromfd, buffer, toread); + } while (towrite == -1 && errno == EINTR); + + if (towrite == -1) + return -1; + + /* check for 'end of file' */ + if (towrite == 0) { + d(printf("end of file?\n")); + break; + } + + do { + toread = write(tofd, buffer, towrite); + } while (toread == -1 && errno == EINTR); + + if (toread == -1) + return -1; + + written += toread; + bytes -= toread; + } + + d(printf("written %d bytes\n", written)); + + return written; +} + +#define PRE_SIZE (32) + +static int +camel_movemail_copy_filter(int fromfd, int tofd, off_t start, size_t bytes, CamelMimeFilter *filter) +{ + char buffer[4096+PRE_SIZE]; + int written = 0; + char *filterbuffer; + int filterlen, filterpre; + + d(printf("writing %d bytes ... ", bytes)); + + camel_mime_filter_reset(filter); + + if (lseek(fromfd, start, SEEK_SET) != start) + return -1; + + while (bytes>0) { + int toread, towrite; + + toread = bytes; + if (bytes>4096) + toread = 4096; + else + toread = bytes; + do { + towrite = read(fromfd, buffer+PRE_SIZE, toread); + } while (towrite == -1 && errno == EINTR); + + if (towrite == -1) + return -1; + + /* check for 'end of file' */ + if (towrite == 0) { + d(printf("end of file?\n")); + camel_mime_filter_complete(filter, buffer+PRE_SIZE, towrite, PRE_SIZE, + &filterbuffer, &filterlen, &filterpre); + towrite = filterlen; + if (towrite == 0) + break; + } else { + camel_mime_filter_filter(filter, buffer+PRE_SIZE, towrite, PRE_SIZE, + &filterbuffer, &filterlen, &filterpre); + towrite = filterlen; + } + + do { + toread = write(tofd, filterbuffer, towrite); + } while (toread == -1 && errno == EINTR); + + if (toread == -1) + return -1; + + written += toread; + bytes -= toread; + } + + d(printf("written %d bytes\n", written)); + + return written; +} + +/* write the headers back out again, but not he Content-Length header, because we dont + want to maintain it! */ +static int +solaris_header_write(int fd, struct _header_raw *header) +{ + struct iovec iv[4]; + int outlen = 0, len; + + iv[1].iov_base = ":"; + iv[1].iov_len = 1; + iv[3].iov_base = "\n"; + iv[3].iov_len = 1; + + while (header) { + if (strcasecmp(header->name, "Content-Length")) { + iv[0].iov_base = header->name; + iv[0].iov_len = strlen(header->name); + iv[2].iov_base = header->value; + iv[2].iov_len = strlen(header->value); + + do { + len = writev(fd, iv, 4); + } while (len == -1 && errno == EINTR); + + if (len == -1) + return -1; + outlen += len; + } + header = header->next; + } + + do { + len = write(fd, "\n", 1); + } while (len == -1 && errno == EINTR); + + if (len == -1) + return -1; + + outlen += 1; + + d(printf("Wrote %d bytes of headers\n", outlen)); + + return outlen; +} + +/* Well, since Solaris is a tad broken wrt its 'mbox' folder format, + we must convert it to a real mbox format. Thankfully this is + mostly pretty easy */ +static int +camel_movemail_solaris (int sfd, int dfd, CamelException *ex) +{ + CamelMimeParser *mp; + char *buffer; + int len; + CamelMimeFilterFrom *ffrom; + int ret = 1; + + mp = camel_mime_parser_new(); + camel_mime_parser_scan_from(mp, TRUE); + camel_mime_parser_init_with_fd(mp, sfd); + + ffrom = camel_mime_filter_from_new(); + + while (camel_mime_parser_step(mp, &buffer, &len) == HSCAN_FROM) { + if (camel_mime_parser_step(mp, &buffer, &len) != HSCAN_FROM_END) { + const char *cl; + int length; + int start, body; + off_t newpos; + + ret = 0; + + start = camel_mime_parser_tell_start_from(mp); + body = camel_mime_parser_tell(mp); + + /* write out headers, but NOT content-length header */ + solaris_header_write(dfd, camel_mime_parser_headers_raw(mp)); + + cl = camel_mime_parser_header(mp, "content-length", NULL); + if (cl == NULL) { + g_warning("Required Content-Length header is missing from solaris mail box @ %d", (int)camel_mime_parser_tell(mp)); + camel_mime_parser_drop_step(mp); + camel_mime_parser_drop_step(mp); + camel_mime_parser_step(mp, &buffer, &len); + camel_mime_parser_unstep(mp); + length = camel_mime_parser_tell_start_from(mp) - body; + newpos = -1; + } else { + length = atoi(cl); + camel_mime_parser_drop_step(mp); + camel_mime_parser_drop_step(mp); + newpos = length+body; + } + /* copy body->length converting From lines */ + if (camel_movemail_copy_filter(sfd, dfd, body, length, (CamelMimeFilter *)ffrom) == -1) + goto fail; + if (newpos != -1) + camel_mime_parser_seek(mp, newpos, SEEK_SET); + } else { + g_error("Inalid parser state: %d", camel_mime_parser_state(mp)); + } + } + + gtk_object_unref((GtkObject *)mp); + gtk_object_unref((GtkObject *)ffrom); + + return ret; + +fail: + camel_exception_setv (ex, CAMEL_EXCEPTION_SYSTEM, + "Error copying " + "mail temp file: %s", + g_strerror (errno)); + + + gtk_object_unref((GtkObject *)mp); + gtk_object_unref((GtkObject *)ffrom); + + return -1; +} + diff --git a/camel/providers/mbox/camel-mbox-folder.c b/camel/providers/mbox/camel-mbox-folder.c index 3403271e40..9d405bd1db 100644 --- a/camel/providers/mbox/camel-mbox-folder.c +++ b/camel/providers/mbox/camel-mbox-folder.c @@ -79,6 +79,8 @@ static void _copy_message_to (CamelFolder *folder, CamelMimeMessage *message, Ca static const gchar *_get_message_uid (CamelFolder *folder, CamelMimeMessage *message, CamelException *ex); #endif +static void mbox_delete_message_by_uid(CamelFolder *folder, const gchar *uid, CamelException *ex); + GPtrArray *summary_get_message_info (CamelFolder *folder, int first, int count); static const CamelMessageInfo *mbox_summary_get_by_uid(CamelFolder *f, const char *uid); @@ -110,11 +112,9 @@ camel_mbox_folder_class_init (CamelMboxFolderClass *camel_mbox_folder_class) camel_folder_class->append_message = mbox_append_message; camel_folder_class->get_uid_list = mbox_get_uid_list; camel_folder_class->expunge = mbox_expunge; -#if 0 - camel_folder_class->copy_message_to = _copy_message_to; - camel_folder_class->get_message_uid = _get_message_uid; -#endif + camel_folder_class->get_message_by_uid = mbox_get_message_by_uid; + camel_folder_class->delete_message_by_uid = mbox_delete_message_by_uid; camel_folder_class->search_by_expression = mbox_search_by_expression; @@ -824,6 +824,19 @@ mbox_get_message_by_number (CamelFolder *folder, gint number, CamelException *ex return mbox_get_message_by_uid (folder, info->info.uid, ex); } +static void +mbox_delete_message_by_uid(CamelFolder *folder, const gchar *uid, CamelException *ex) +{ + CamelMessageInfo *info; + CamelMboxFolder *mf = (CamelMboxFolder *)folder; + + info = camel_folder_summary_uid((CamelFolderSummary *)mf->summary, uid); + if (info) { + info->flags |= CAMEL_MESSAGE_DELETED | CAMEL_MESSAGE_FOLDER_FLAGGED; + camel_folder_summary_touch((CamelFolderSummary *)mf->summary); + } +} + /* track flag changes in the summary */ static void message_changed(CamelMimeMessage *m, int type, CamelMboxFolder *mf) diff --git a/camel/providers/mbox/camel-mbox-summary.c b/camel/providers/mbox/camel-mbox-summary.c index 56ff1cb198..dac2694f4c 100644 --- a/camel/providers/mbox/camel-mbox-summary.c +++ b/camel/providers/mbox/camel-mbox-summary.c @@ -299,6 +299,7 @@ summary_rebuild(CamelMboxSummary *mbs, off_t offset) } else { gtk_object_unref((GtkObject *)mp); /* end of file - no content? */ + printf("We radn out of file?\n"); return 0; } } @@ -308,6 +309,7 @@ summary_rebuild(CamelMboxSummary *mbs, off_t offset) info = camel_folder_summary_add_from_parser((CamelFolderSummary *)mbs, mp); if (info == NULL) { + printf("Could not build info from file?\n"); ok = -1; break; } @@ -315,6 +317,10 @@ summary_rebuild(CamelMboxSummary *mbs, off_t offset) g_assert(camel_mime_parser_step(mp, NULL, NULL) == HSCAN_FROM_END); } + /* update the file size in the summary */ + if (ok != -1) + mbs->folder_size = camel_mime_parser_seek(mp, 0, SEEK_CUR); + printf("updating folder size = %d\n", mbs->folder_size); gtk_object_unref((GtkObject *)mp); return ok; @@ -631,7 +637,7 @@ camel_mbox_summary_expunge(CamelMboxSummary *mbs) } xevok = TRUE; } - xevnew = header_evolution_encode(strtoul(info->info.uid, NULL, 10), info->info.flags); + xevnew = header_evolution_encode(strtoul(info->info.uid, NULL, 10), info->info.flags & 0xffff); if (quick) { if (!xevok) { g_error("The summary told me I had an X-Evolution header, but i dont!"); @@ -664,6 +670,7 @@ camel_mbox_summary_expunge(CamelMboxSummary *mbs) info->frompos = frompos; offset = bodypos - info->info.content->bodypos; } + info->info.flags &= 0xffff; g_free(xevnew); xevnew = NULL; camel_mime_parser_drop_step(mp); camel_mime_parser_drop_step(mp); @@ -703,7 +710,7 @@ camel_mbox_summary_expunge(CamelMboxSummary *mbs) if (stat(mbs->folder_path, &st) == -1) goto error; - s->flags |= CAMEL_SUMMARY_DIRTY; + camel_folder_summary_touch(s); s->time = st.st_mtime; mbs->folder_size = st.st_size; camel_folder_summary_save(s); |