aboutsummaryrefslogtreecommitdiffstats
path: root/camel
diff options
context:
space:
mode:
authorNot Zed <NotZed@HelixCode.com>2000-11-04 10:34:46 +0800
committerMichael Zucci <zucchi@src.gnome.org>2000-11-04 10:34:46 +0800
commit338344b2e4b2e2844c30af556d99b5cef594faaa (patch)
tree3e8e4c4f6de760d3f00fa11bb28dcb5c0586267f /camel
parent055dab430c5ec0ca2f54ee4c5c2d0e9e299d9f89 (diff)
downloadgsoc2013-evolution-338344b2e4b2e2844c30af556d99b5cef594faaa.tar.gz
gsoc2013-evolution-338344b2e4b2e2844c30af556d99b5cef594faaa.tar.zst
gsoc2013-evolution-338344b2e4b2e2844c30af556d99b5cef594faaa.zip
Set the preface/postface from the parser into the multipart object.
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. svn path=/trunk/; revision=6388
Diffstat (limited to 'camel')
-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);