diff options
-rw-r--r-- | camel/ChangeLog | 50 | ||||
-rw-r--r-- | camel/camel-mime-filter-charset.c | 2 | ||||
-rw-r--r-- | camel/camel-mime-parser.c | 90 | ||||
-rw-r--r-- | camel/camel-mime-parser.h | 4 | ||||
-rw-r--r-- | camel/camel-mime-part-utils.c | 4 | ||||
-rw-r--r-- | camel/camel-mime-utils.c | 19 | ||||
-rw-r--r-- | camel/camel-multipart.c | 44 | ||||
-rw-r--r-- | camel/camel-multipart.h | 2 | ||||
-rw-r--r-- | camel/camel-stream-filter.c | 46 | ||||
-rw-r--r-- | camel/providers/mbox/camel-mbox-folder.c | 21 |
10 files changed, 249 insertions, 33 deletions
diff --git a/camel/ChangeLog b/camel/ChangeLog index 7604681a96..cee5b9bf55 100644 --- a/camel/ChangeLog +++ b/camel/ChangeLog @@ -1,3 +1,53 @@ +2000-11-04 Not Zed <NotZed@HelixCode.com> + + * camel-mime-part-utils.c + (camel_mime_part_construct_content_from_parser): Set the + preface/postface from the parser into the multipart object. + + * camel-multipart.c (camel_multipart_set_postface): Function to + set the postface text on a multipart. + (camel_multipart_set_preface): Similarly for preface text. + + * camel-mime-parser.c (folder_scan_content): If we scan until a + boundary, then we do not include the \n that starts the boundary + line in the content. + (struct _header_scan_stack): Added a ByteArray to store the + multipart pre/post-text as we're scanning. + (folder_pull_part): Free pre/posttext if they are allocated. + (folder_scan_step): Build into the pre/posttext arrays as we + encounter data. + (camel_mime_parser_preface): REturn the multipart preface text, if + there is any scanned. + (camel_mime_parser_postface): Likewise for postface text. + (byte_array_to_string): helper function for above. + + * providers/mbox/camel-mbox-folder.c (mbox_append_message): Change + the from line to be "\nFrom ..." always, so no need to + check/append a \n to messages. + (mbox_append_message): Open the output stream with append mode + [assuming this is more efficient than seeking to the end] + And dont prepend \n on the From line if its the first in the + mbox. + (mbox_append_message): Pass the offset of the real start of the + "From " line when we perform the update (which may != 'seek') + + * camel-mime-filter-charset.c (complete): Removed the terminating + NUL 'fix'. + + * camel-stream-filter.c (do_read): Added some debug. + (do_flush): And here. + (do_write): And here too. + (do_write): ARGH!!! ARGH! Ok, so the filter stream was writing a + different number of bytes than the requester was asking it to + write (because of filtering, of course!). So instead of returning + the true number of written bytes, we'll return what they asked us + to write - unless there is an error in which case we return -1. + + * camel-mime-utils.c (base64_encode_close): Sigh, forgot to make + it unsigned. I think this is actually a gcc bug as (48 >> 2) + somehow ended up negative, when it obviously should not, even if + the data load was signed. + 2000-11-03 Jeffrey Stedfast <fejj@helixcode.com> * camel-url.c: Undo my incorrect fix - I misunderstood danw - diff --git a/camel/camel-mime-filter-charset.c b/camel/camel-mime-filter-charset.c index 5c7ae438d6..c91c7f061f 100644 --- a/camel/camel-mime-filter-charset.c +++ b/camel/camel-mime-filter-charset.c @@ -101,8 +101,6 @@ complete(CamelMimeFilter *mf, char *in, size_t len, size_t prespace, char **out, outbuf = mf->outbuf; outlen = mf->outsize; - outbuf[0] = '\0'; - if (inlen>0) { converted = unicode_iconv(f->ic, &inbuf, &inlen, &outbuf, &outlen); if (converted == -1) { diff --git a/camel/camel-mime-parser.c b/camel/camel-mime-parser.c index 17d24867f0..efa808170e 100644 --- a/camel/camel-mime-parser.c +++ b/camel/camel-mime-parser.c @@ -254,6 +254,11 @@ struct _header_scan_stack { struct _header_content_type *content_type; + /* I dont use GString's casue you can't efficiently append a buffer to them */ + GByteArray *pretext; /* for multipart types, save the pre-boundary data here */ + GByteArray *posttext; /* for multipart types, save the post-boundary data here */ + int prestage; /* used to determine if it is a pre-boundary or post-boundary data segment */ + char *boundary; /* for multipart/ * boundaries, including leading -- and trailing -- for the final part */ int boundarylen; /* length of boundary, including leading -- */ }; @@ -472,6 +477,60 @@ camel_mime_parser_headers_raw(CamelMimeParser *m) return NULL; } +static const char * +byte_array_to_string(GByteArray *array) +{ + if (array == NULL) + return NULL; + + if (array->len == 0 || array->data[array->len-1] != '\0') + g_byte_array_append(array, "", 1); + + return array->data; +} + +/** + * camel_mime_parser_preface: + * @m: + * + * Retrieve the preface text for the current multipart. + * Can only be used when the state is HSCAN_MULTIPART_END. + * + * Return value: The preface text, or NULL if there wasn't any. + **/ +const char * +camel_mime_parser_preface(CamelMimeParser *m) +{ + struct _header_scan_state *s = _PRIVATE(m); + + if (s->parts) + return byte_array_to_string(s->parts->pretext); + + return NULL; +} + +/** + * camel_mime_parser_postface: + * @m: + * + * Retrieve the postface text for the current multipart. + * Only returns valid data when the current state if + * HSCAN_MULTIPART_END. + * + * Return value: The postface text, or NULL if there wasn't any. + **/ +const char * +camel_mime_parser_postface(CamelMimeParser *m) +{ + struct _header_scan_state *s = _PRIVATE(m); + + if (s->parts) + return byte_array_to_string(s->parts->posttext); + + return NULL; +} + + /** * camel_mime_parser_init_with_fd: * @m: @@ -906,6 +965,10 @@ folder_pull_part(struct _header_scan_state *s) header_raw_clear(&h->headers); #endif header_content_type_unref(h->content_type); + if (h->pretext) + g_byte_array_free(h->pretext, TRUE); + if (h->posttext) + g_byte_array_free(h->posttext, TRUE); g_free(h); } else { g_warning("Header stack underflow!\n"); @@ -1219,6 +1282,7 @@ folder_scan_content(struct _header_scan_state *s, int *lastone, char **data, int int len; struct _header_scan_stack *part, *overpart = s->parts; int already_packed = FALSE; + int onboundary = FALSE; c(printf("scanning content\n")); @@ -1252,8 +1316,10 @@ retry: while (inptr<=inend) { if (!s->midline && (part = folder_boundary_check(s, inptr, lastone))) { - if ( (inptr-start) ) + if ( (inptr-start) ) { + onboundary = TRUE; goto content; + } goto normal_exit; } @@ -1335,7 +1401,11 @@ normal_exit: s->inptr = inptr; *data = start; - *length = inptr-start; + /* if we hit a boundary, we should not include the closing \n */ + if (onboundary) + *length = inptr-start-1; + else + *length = inptr-start; /* printf("got %scontent: %.*s", s->midline?"partial ":"", inptr-start, start);*/ @@ -1615,10 +1685,22 @@ tail_recurse: do { hb = folder_scan_content(s, &state, databuffer, datalength); if (*datalength>0) { - /* FIXME: needs a state to return this shit??? */ - d(printf("Multipart Content: '%.*s'\n", *datalength, *databuffer)); + /* instead of a new state, we'll just store it locally and provide + an accessor function */ + d(printf("Multipart %s Content %p: '%.*s'\n", + h->prestage>0?"post":"pre", h, *datalength, *databuffer)); + if (h->prestage > 0) { + if (h->posttext == NULL) + h->posttext = g_byte_array_new(); + g_byte_array_append(h->posttext, *databuffer, *datalength); + } else { + if (h->pretext == NULL) + h->pretext = g_byte_array_new(); + g_byte_array_append(h->pretext, *databuffer, *datalength); + } } } while (hb==h && *datalength>0); + h->prestage++; if (*datalength==0 && hb==h) { d(printf("got boundary: %s\n", hb->boundary)); folder_scan_skip_line(s); diff --git a/camel/camel-mime-parser.h b/camel/camel-mime-parser.h index 5baa58c88e..d9a6e8bbb3 100644 --- a/camel/camel-mime-parser.h +++ b/camel/camel-mime-parser.h @@ -103,6 +103,10 @@ const char *camel_mime_parser_header(CamelMimeParser *, const char *, int *offse /* get all raw headers. READ ONLY! */ struct _header_raw *camel_mime_parser_headers_raw(CamelMimeParser *); +/* get multipart pre/postface */ +const char *camel_mime_parser_preface(CamelMimeParser *m); +const char *camel_mime_parser_postface(CamelMimeParser *m); + /* add a processing filter for body contents */ int camel_mime_parser_filter_add(CamelMimeParser *, CamelMimeFilter *); void camel_mime_parser_filter_remove(CamelMimeParser *, int); diff --git a/camel/camel-mime-part-utils.c b/camel/camel-mime-part-utils.c index 81f17aa098..2809346a00 100644 --- a/camel/camel-mime-part-utils.c +++ b/camel/camel-mime-part-utils.c @@ -218,6 +218,10 @@ camel_mime_part_construct_content_from_parser(CamelMimePart *dw, CamelMimeParser camel_object_unref ((CamelObject *)bodypart); } + /* these are only return valid data in the MULTIPART_END state */ + camel_multipart_set_preface((CamelMultipart *)content, camel_mime_parser_preface(mp)); + camel_multipart_set_postface((CamelMultipart *)content, camel_mime_parser_postface(mp)); + d(printf("Created multi-part\n")); break; } default: diff --git a/camel/camel-mime-utils.c b/camel/camel-mime-utils.c index 40a81a11f6..6ecec61670 100644 --- a/camel/camel-mime-utils.c +++ b/camel/camel-mime-utils.c @@ -282,18 +282,19 @@ base64_encode_close(unsigned char *in, int inlen, gboolean break_lines, unsigned if (inlen>0) outptr += base64_encode_step(in, inlen, break_lines, outptr, state, save); - c1 = ((char *)save)[1]; - c2 = ((char *)save)[2]; + c1 = ((unsigned char *)save)[1]; + c2 = ((unsigned char *)save)[2]; switch (((char *)save)[0]) { case 2: - outptr[2] = base64_alphabet [ ( (c2 &0x0f) << 2 ) ]; + outptr[2] = base64_alphabet[ ( (c2 &0x0f) << 2 ) ]; + g_assert(outptr[2] != 0); goto skip; case 1: outptr[2] = '='; skip: - outptr[0] = base64_alphabet [ c1 >> 2 ]; - outptr[1] = base64_alphabet [ c2 >> 4 | ( (c1&0x3) << 4 )]; + outptr[0] = base64_alphabet[ c1 >> 2 ]; + outptr[1] = base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 )]; outptr[3] = '='; outptr += 4; break; @@ -345,10 +346,10 @@ base64_encode_step(unsigned char *in, int len, gboolean break_lines, unsigned ch c2 = *inptr++; skip2: c3 = *inptr++; - *outptr++ = base64_alphabet [ c1 >> 2 ]; - *outptr++ = base64_alphabet [ c2 >> 4 | ( (c1&0x3) << 4 ) ]; - *outptr++ = base64_alphabet [ ( (c2 &0x0f) << 2 ) | (c3 >> 6) ]; - *outptr++ = base64_alphabet [ c3 & 0x3f ]; + *outptr++ = base64_alphabet[ c1 >> 2 ]; + *outptr++ = base64_alphabet[ c2 >> 4 | ( (c1&0x3) << 4 ) ]; + *outptr++ = base64_alphabet[ ( (c2 &0x0f) << 2 ) | (c3 >> 6) ]; + *outptr++ = base64_alphabet[ c3 & 0x3f ]; /* this is a bit ugly ... */ if (break_lines && (++already)>=19) { *outptr++='\n'; diff --git a/camel/camel-multipart.c b/camel/camel-multipart.c index 018d90b509..c5a5f81b22 100644 --- a/camel/camel-multipart.c +++ b/camel/camel-multipart.c @@ -474,3 +474,47 @@ write_to_stream (CamelDataWrapper *data_wrapper, CamelStream *stream) return total; } + +/** + * camel_multipart_set_preface: + * @multipart: + * @preface: + * + * Set the preface text for this multipart. Will be written out infront + * of the multipart. This text should only include US-ASCII strings, and + * be relatively short, and will be ignored by any MIME mail client. + **/ +void +camel_multipart_set_preface(CamelMultipart *multipart, const char *preface) +{ + if (multipart->preface != preface) { + g_free(multipart->preface); + if (preface) + multipart->preface = g_strdup(preface); + else + multipart->preface = NULL; + } +} + +/** + * camel_multipart_set_postface: + * @multipart: + * @postface: + * + * Set the postfix text for this multipart. Will be written out after + * the last boundary of the multipart, and ignored by any MIME mail + * client. + * + * Generally postface texts should not be sent with multipart messages. + **/ +void +camel_multipart_set_postface(CamelMultipart *multipart, const char *postface) +{ + if (multipart->postface != postface) { + g_free(multipart->postface); + if (postface) + multipart->postface = g_strdup(postface); + else + multipart->postface = NULL; + } +} diff --git a/camel/camel-multipart.h b/camel/camel-multipart.h index 642cdb5255..3058b8f2e0 100644 --- a/camel/camel-multipart.h +++ b/camel/camel-multipart.h @@ -94,6 +94,8 @@ void camel_multipart_set_boundary (CamelMultipart *multipart, gchar *boundary); const gchar * camel_multipart_get_boundary (CamelMultipart *multipart); +void camel_multipart_set_preface (CamelMultipart *multipart, const char *preface); +void camel_multipart_set_postface (CamelMultipart *multipart, const char *postface); #ifdef __cplusplus } diff --git a/camel/camel-stream-filter.c b/camel/camel-stream-filter.c index 7d66928bf5..211db36e7f 100644 --- a/camel/camel-stream-filter.c +++ b/camel/camel-stream-filter.c @@ -21,6 +21,9 @@ #include "camel-stream-filter.h" +#define d(x) +/*#include <stdio.h>*/ + struct _filter { struct _filter *next; int id; @@ -233,9 +236,20 @@ do_read (CamelStream *stream, char *buffer, size_t n) f = p->filters; p->filtered = p->buffer; p->filteredlen = size; + + d(printf ("\n\nOriginal content: '")); + d(fwrite(p->filtered, sizeof(char), p->filteredlen, stdout)); + d(printf("'\n")); + while (f) { camel_mime_filter_filter(f->filter, p->filtered, p->filteredlen, presize, &p->filtered, &p->filteredlen, &presize); + + d(printf ("Filtered content (%s): '", + camel_type_to_name(((CamelObject *)f->filter)->s.type))); + d(fwrite(p->filtered, sizeof(char), p->filteredlen, stdout)); + d(printf("'\n")); + f = f->next; } } @@ -249,6 +263,9 @@ do_read (CamelStream *stream, char *buffer, size_t n) return size; } +/* Note: Since the caller expects to write out as much as they asked us to + write (for 'success'), we return what they asked us to write (for 'success') + rather than the true number of written bytes */ static ssize_t do_write (CamelStream *stream, const char *buf, size_t n) { @@ -257,17 +274,31 @@ do_write (CamelStream *stream, const char *buf, size_t n) struct _filter *f; int presize; char *buffer = (char *)buf; + size_t len = n; p->last_was_read = FALSE; + d(printf ("\n\nWriting: Original content: '")); + d(fwrite(buffer, sizeof(char), len, stdout)); + d(printf("'\n")); + f = p->filters; presize = 0; while (f) { - camel_mime_filter_filter(f->filter, buffer, n, presize, &buffer, &n, &presize); + camel_mime_filter_filter(f->filter, buffer, len, presize, &buffer, &len, &presize); + + d(printf ("Filtered content (%s): '", + camel_type_to_name(((CamelObject *)f->filter)->s.type))); + d(fwrite(buffer, sizeof(char), len, stdout)); + d(printf("'\n")); + f = f->next; } - return camel_stream_write(filter->source, buffer, n); + if (camel_stream_write(filter->source, buffer, len) != len) + return -1; + + return n; } static int @@ -288,8 +319,19 @@ do_flush (CamelStream *stream) len = 0; presize = 0; f = p->filters; + + d(printf ("\n\nFlushing: Original content: '")); + d(fwrite(buffer, sizeof(char), len, stdout)); + d(printf("'\n")); + while (f) { camel_mime_filter_complete(f->filter, buffer, len, presize, &buffer, &len, &presize); + + d(printf ("Filtered content (%s): '", + camel_type_to_name(((CamelObject *)f->filter)->s.type))); + d(fwrite(buffer, sizeof(char), len, stdout)); + d(printf("'\n")); + f = f->next; } if (len > 0 && camel_stream_write(filter->source, buffer, len) == -1) diff --git a/camel/providers/mbox/camel-mbox-folder.c b/camel/providers/mbox/camel-mbox-folder.c index 3b1f0a5030..44dfc7c6a4 100644 --- a/camel/providers/mbox/camel-mbox-folder.c +++ b/camel/providers/mbox/camel-mbox-folder.c @@ -303,29 +303,18 @@ mbox_append_message(CamelFolder *folder, CamelMimeMessage * message, const Camel CamelMessageInfo *newinfo; struct stat st; off_t seek = -1; - char *xev, last; + char *xev; guint32 uid; char *fromline = NULL; if (stat(mbox_folder->folder_file_path, &st) != 0) goto fail; - output_stream = camel_stream_fs_new_with_name(mbox_folder->folder_file_path, O_RDWR, 0600); + output_stream = camel_stream_fs_new_with_name(mbox_folder->folder_file_path, O_WRONLY|O_APPEND, 0600); if (output_stream == NULL) goto fail; - if (st.st_size) { - seek = camel_seekable_stream_seek((CamelSeekableStream *) output_stream, st.st_size - 1, SEEK_SET); - if (++seek != st.st_size) - goto fail; - - /* If the mbox doesn't end with a newline, fix that. */ - if (camel_stream_read(output_stream, &last, 1) != 1) - goto fail; - if (last != '\n') - camel_stream_write(output_stream, "\n", 1); - } else - seek = 0; + seek = st.st_size; /* assign a new x-evolution header/uid */ camel_medium_remove_header(CAMEL_MEDIUM(message), "X-Evolution"); @@ -337,7 +326,7 @@ mbox_append_message(CamelFolder *folder, CamelMimeMessage * message, const Camel /* we must write this to the non-filtered stream ... */ fromline = camel_mbox_summary_build_from(CAMEL_MIME_PART(message)->headers); - if (camel_stream_write_string(output_stream, fromline) == -1) + if (camel_stream_printf(output_stream, seek==0?"%s":"\n%s", fromline) == -1) goto fail; /* and write the content to the filtering stream, that translated '\nFrom' into '\n>From' */ @@ -357,7 +346,7 @@ mbox_append_message(CamelFolder *folder, CamelMimeMessage * message, const Camel g_free(fromline); /* force a summary update - will only update from the new position, if it can */ - if (camel_mbox_summary_update(mbox_folder->summary, seek, mbox_folder->changes) == 0) { + if (camel_mbox_summary_update(mbox_folder->summary, seek==0?seek:seek+1, mbox_folder->changes) == 0) { char uidstr[16]; sprintf(uidstr, "%u", uid); |