aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--camel/ChangeLog50
-rw-r--r--camel/camel-mime-filter-charset.c2
-rw-r--r--camel/camel-mime-parser.c90
-rw-r--r--camel/camel-mime-parser.h4
-rw-r--r--camel/camel-mime-part-utils.c4
-rw-r--r--camel/camel-mime-utils.c19
-rw-r--r--camel/camel-multipart.c44
-rw-r--r--camel/camel-multipart.h2
-rw-r--r--camel/camel-stream-filter.c46
-rw-r--r--camel/providers/mbox/camel-mbox-folder.c21
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);