summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/mailutils/filter.h3
-rw-r--r--libmailutils/Makefile.am1
-rw-r--r--libmailutils/filter.c1
-rw-r--r--libmailutils/fromflt.c283
-rw-r--r--libmailutils/tests/Makefile.am1
-rw-r--r--libmailutils/tests/base64d.at4
-rw-r--r--libmailutils/tests/base64e.at4
-rw-r--r--libmailutils/tests/fltst.c2
-rw-r--r--libmailutils/tests/fromflt.at96
-rw-r--r--libmailutils/tests/testsuite.at1
-rw-r--r--libproto/mbox/mbox.c17
11 files changed, 403 insertions, 10 deletions
diff --git a/include/mailutils/filter.h b/include/mailutils/filter.h
index 120318d57..d9c53ca7f 100644
--- a/include/mailutils/filter.h
+++ b/include/mailutils/filter.h
@@ -100,13 +100,14 @@ extern mu_filter_record_t mu_qp_filter; /* quoted-printable. */
extern mu_filter_record_t mu_base64_filter;
extern mu_filter_record_t mu_binary_filter;
extern mu_filter_record_t mu_bit8_filter;
extern mu_filter_record_t mu_bit7_filter;
extern mu_filter_record_t mu_rfc_2047_Q_filter;
extern mu_filter_record_t mu_rfc_2047_B_filter;
-
+extern mu_filter_record_t mu_from_filter;
+
enum mu_iconv_fallback_mode
{
mu_fallback_none,
mu_fallback_copy_pass,
mu_fallback_copy_octal
};
diff --git a/libmailutils/Makefile.am b/libmailutils/Makefile.am
index 3f083e01d..07a0a4e54 100644
--- a/libmailutils/Makefile.am
+++ b/libmailutils/Makefile.am
@@ -80,12 +80,13 @@ libmailutils_la_SOURCES = \
file_stream.c\
filter.c\
filter_iconv.c\
fltstream.c\
folder.c\
freeitem.c\
+ fromflt.c\
gdebug.c\
getpass.c\
gocs.c\
hdritr.c\
header.c\
iostream.c\
diff --git a/libmailutils/filter.c b/libmailutils/filter.c
index 8fdc25f90..0008ba0f1 100644
--- a/libmailutils/filter.c
+++ b/libmailutils/filter.c
@@ -75,12 +75,13 @@ mu_filter_get_list (mu_list_t *plist)
mu_list_append (filter_list, mu_rfc822_filter);
mu_list_append (filter_list, mu_crlf_filter);
mu_list_append (filter_list, mu_crlfdot_filter);
mu_list_append (filter_list, mu_dot_filter);
mu_list_append (filter_list, mu_rfc_2047_Q_filter);
mu_list_append (filter_list, mu_rfc_2047_B_filter);
+ mu_list_append (filter_list, mu_from_filter);
/* FIXME: add the default encodings? */
}
*plist = filter_list;
mu_monitor_unlock (&filter_monitor);
return 0;
}
diff --git a/libmailutils/fromflt.c b/libmailutils/fromflt.c
new file mode 100644
index 000000000..d96d46d85
--- /dev/null
+++ b/libmailutils/fromflt.c
@@ -0,0 +1,283 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 2003, 2007, 2010 Free Software Foundation, Inc.
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 3 of the License, or (at your option) any later version.
+
+ This library is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General
+ Public License along with this library; if not, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <string.h>
+#include <mailutils/errno.h>
+#include <mailutils/filter.h>
+#include <mailutils/stream.h>
+
+enum from_decode_state
+ {
+ from_decode_init,
+ from_decode_nl,
+ from_decode_char
+ };
+
+#define GT_FROM_MARK_STR ">From "
+#define GT_FROM_MARK_LEN (sizeof (GT_FROM_MARK_STR) - 1)
+
+/* Move min(isize,osize) bytes from iptr to optr, replacing each '>From '
+ at the beginning of line with 'From '. */
+static enum mu_filter_result
+_from_decoder (void *xd,
+ enum mu_filter_command cmd,
+ struct mu_filter_io *iobuf)
+{
+ int *pstate = xd;
+ const unsigned char *iptr;
+ size_t isize;
+ char *optr;
+ size_t osize;
+ enum from_decode_state state;
+ size_t i, j;
+
+ switch (cmd)
+ {
+ case mu_filter_init:
+ *pstate = from_decode_init;
+ return mu_filter_ok;
+
+ case mu_filter_done:
+ return mu_filter_ok;
+
+ default:
+ state = *pstate;
+ break;
+ }
+
+ iptr = (const unsigned char *) iobuf->input;
+ isize = iobuf->isize;
+ optr = iobuf->output;
+ osize = iobuf->osize;
+
+ for (i = j = 0; i < isize && j < osize; i++)
+ {
+ unsigned char c = *iptr++;
+
+ if (c == '\n')
+ state = from_decode_nl;
+ else if (state == from_decode_init || state == from_decode_nl)
+ {
+ size_t len = isize - i;
+
+ if (len < GT_FROM_MARK_LEN)
+ {
+ if (memcmp (iptr - 1, GT_FROM_MARK_STR, len) == 0)
+ {
+ if (i == 0)
+ {
+ iobuf->isize = GT_FROM_MARK_LEN - len;
+ return mu_filter_moreinput;
+ }
+ break;
+ }
+ else
+ state = from_decode_char;
+ }
+ else if (memcmp (iptr - 1, GT_FROM_MARK_STR, GT_FROM_MARK_LEN) == 0)
+ {
+ /* Skip > */
+ state = from_decode_char;
+ continue;
+ }
+ }
+ optr[j++] = c;
+ }
+
+ *pstate = state;
+ iobuf->isize = i;
+ iobuf->osize = j;
+ return mu_filter_ok;
+}
+
+#define FROM_MARK_STR "From "
+#define FROM_MARK_LEN (sizeof (FROM_MARK_STR) - 1)
+
+enum from_encode_state
+ {
+ from_encode_init,
+ from_encode_nl,
+ from_encode_char,
+ from_encode_gt,
+ from_encode_f,
+ from_encode_r,
+ from_encode_o,
+ from_encode_m,
+ from_encode_sp
+ };
+
+static int length_to_state_tab[] = {
+ from_encode_gt,
+ from_encode_f,
+ from_encode_r,
+ from_encode_o,
+ from_encode_m,
+ from_encode_sp
+};
+
+static int state_to_length_tab[] = {
+ 0, 0, 0,
+ GT_FROM_MARK_LEN,
+ GT_FROM_MARK_LEN-1,
+ GT_FROM_MARK_LEN-2,
+ GT_FROM_MARK_LEN-3,
+ GT_FROM_MARK_LEN-4,
+ GT_FROM_MARK_LEN-5
+};
+
+/* Move min(isize,osize) bytes from iptr to optr, replacing each 'From '
+ at the beginning of line with '>From '. */
+
+static enum mu_filter_result
+_from_encoder (void *xd,
+ enum mu_filter_command cmd,
+ struct mu_filter_io *iobuf)
+{
+ int *pstate = xd;
+ const unsigned char *iptr;
+ size_t isize;
+ char *optr;
+ size_t osize;
+ enum from_encode_state state;
+ size_t i, j;
+
+ switch (cmd)
+ {
+ case mu_filter_init:
+ *pstate = from_encode_init;
+ return mu_filter_ok;
+
+ case mu_filter_done:
+ return mu_filter_ok;
+
+ default:
+ state = *pstate;
+ switch (state)
+ {
+ case from_encode_init:
+ case from_encode_nl:
+ case from_encode_char:
+ break;
+
+ default:
+ osize = state_to_length_tab[state];
+ if (iobuf->osize < osize)
+ {
+ iobuf->osize = osize;
+ return mu_filter_moreoutput;
+ }
+ memcpy (iobuf->output, GT_FROM_MARK_STR + GT_FROM_MARK_LEN - osize,
+ osize);
+ iobuf->osize = osize;
+ iobuf->isize = osize;
+ *pstate = from_encode_init;
+ return mu_filter_ok;
+ }
+ break;
+ }
+
+ iptr = (const unsigned char *) iobuf->input;
+ isize = iobuf->isize;
+ optr = iobuf->output;
+ osize = iobuf->osize;
+
+ for (i = j = 0; i < isize && j < osize; i++)
+ {
+ unsigned char c = *iptr++;
+
+ if (c == '\n')
+ state = from_encode_nl;
+ else if (state == from_encode_init || state == from_encode_nl)
+ {
+ size_t len = isize - i;
+
+ if (len < FROM_MARK_LEN)
+ {
+ if (memcmp (iptr - 1, FROM_MARK_STR, len) == 0)
+ {
+ if (i == 0)
+ {
+ iobuf->isize = FROM_MARK_LEN;
+ return mu_filter_moreinput;
+ }
+ break;
+ }
+ else
+ state = from_encode_char;
+ }
+ else if (memcmp (iptr - 1, FROM_MARK_STR, FROM_MARK_LEN) == 0)
+ {
+ size_t rest = osize - j;
+
+ if (rest > GT_FROM_MARK_LEN)
+ rest = GT_FROM_MARK_LEN;
+ else if (rest < 2)
+ {
+ if (i == 0)
+ {
+ iobuf->osize = GT_FROM_MARK_LEN;
+ return mu_filter_moreoutput;
+ }
+ break;
+ }
+
+ memcpy (optr + j, GT_FROM_MARK_STR, rest);
+ i += rest - 2;
+ iptr += rest - 2;
+ j += rest;
+ if (rest < GT_FROM_MARK_LEN)
+ state = length_to_state_tab[rest];
+ else
+ state = from_encode_char;
+ continue;
+ }
+ else
+ state = from_encode_char;
+ }
+ optr[j++] = c;
+ }
+ *pstate = state;
+ iobuf->isize = i;
+ iobuf->osize = j;
+ return mu_filter_ok;
+}
+
+static int
+_from_alloc_state (void **pret, int mode, void *data MU_ARG_UNUSED)
+{
+ *pret = malloc (sizeof (int));
+ if (!*pret)
+ return ENOMEM;
+ return 0;
+}
+
+static struct _mu_filter_record _from_filter = {
+ "FROM",
+ 0,
+ _from_alloc_state,
+ _from_encoder,
+ _from_decoder
+};
+
+mu_filter_record_t mu_from_filter = &_from_filter;
+
diff --git a/libmailutils/tests/Makefile.am b/libmailutils/tests/Makefile.am
index 7324e88e4..a8215fb5f 100644
--- a/libmailutils/tests/Makefile.am
+++ b/libmailutils/tests/Makefile.am
@@ -61,12 +61,13 @@ TESTSUITE_AT = \
address.at\
argcv.at\
base64d.at\
base64e.at\
decode2047.at\
encode2047.at\
+ fromflt.at\
list.at\
mailcap.at\
testsuite.at\
url.at
TESTSUITE = $(srcdir)/testsuite
diff --git a/libmailutils/tests/base64d.at b/libmailutils/tests/base64d.at
index b26c41591..df1efd31d 100644
--- a/libmailutils/tests/base64d.at
+++ b/libmailutils/tests/base64d.at
@@ -13,25 +13,25 @@
#
# You should have received a copy of the GNU General Public License
# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
# This file is part of Mailfromd testsuite.
AT_SETUP([base64 decoding (read)])
-AT_KEYWORDS([base64 base64d base64dr decode])
+AT_KEYWORDS([base64 base64d base64dr decode filter])
AT_CHECK([
cp $abs_top_srcdir/libmailutils/tests/Encode expout
fltst base64 decode read linelen=0 < $abs_top_srcdir/libmailutils/tests/Decode],
[0],
[expout])
AT_CLEANUP
AT_SETUP([base64 decoding (write)])
-AT_KEYWORDS([base64 base64d base64dw decode])
+AT_KEYWORDS([base64 base64d base64dw decode filter])
AT_CHECK([
cp $abs_top_srcdir/libmailutils/tests/Encode expout
fltst base64 decode write linelen=0 < $abs_top_srcdir/libmailutils/tests/Decode],
[0],
[expout])
diff --git a/libmailutils/tests/base64e.at b/libmailutils/tests/base64e.at
index c753471a1..b94522e41 100644
--- a/libmailutils/tests/base64e.at
+++ b/libmailutils/tests/base64e.at
@@ -13,25 +13,25 @@
#
# You should have received a copy of the GNU General Public License
# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
# This file is part of Mailfromd testsuite.
AT_SETUP([base64 encoding (read)])
-AT_KEYWORDS([base64 base64e base64er encode])
+AT_KEYWORDS([base64 base64e base64er encode filter])
AT_CHECK([
cp $abs_top_srcdir/libmailutils/tests/Decode expout
fltst base64 encode read nl < $abs_top_srcdir/libmailutils/tests/Encode],
[0],
[expout])
AT_CLEANUP
AT_SETUP([base64 encoding (write)])
-AT_KEYWORDS([base64 base64e base64ew encode])
+AT_KEYWORDS([base64 base64e base64ew encode filter])
AT_CHECK([
cp $abs_top_srcdir/libmailutils/tests/Decode expout
fltst base64 encode write nl < $abs_top_srcdir/libmailutils/tests/Encode],
[0],
[expout])
diff --git a/libmailutils/tests/fltst.c b/libmailutils/tests/fltst.c
index 8597dd5a0..d62a02b2e 100644
--- a/libmailutils/tests/fltst.c
+++ b/libmailutils/tests/fltst.c
@@ -111,13 +111,13 @@ main (int argc, char * argv [])
size_t line_length;
int line_length_option = 0;
int newline_option = 0;
if (argc == 1)
usage (NULL);
- if (argc < 3)
+ if (argc < 4)
usage ("not enough arguments");
fltname = argv[1];
if (strcmp (argv[2], "encode") == 0)
mode = MU_FILTER_ENCODE;
diff --git a/libmailutils/tests/fromflt.at b/libmailutils/tests/fromflt.at
new file mode 100644
index 000000000..a5b331375
--- /dev/null
+++ b/libmailutils/tests/fromflt.at
@@ -0,0 +1,96 @@
+# This file is part of GNU Mailutils. -*- Autotest -*-
+# Copyright (C) 2007, 2008, 2009, 2010 Free Software Foundation, Inc.
+#
+# GNU Mailutils is free software; you can redistribute it and/or
+# modify it under the terms of the GNU General Public License as
+# published by the Free Software Foundation; either version 3, or (at
+# your option) any later version.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
+# This file is part of Mailfromd testsuite.
+
+# -------------------------------------------
+# Data for 'From' filter tests.
+# -------------------------------------------
+
+m4_define([from_plain_text],[From this time on
+from that source
+ From stdin
+and
+From them
+])
+
+m4_define([from_encoded_text],[>From this time on
+from that source
+ From stdin
+and
+>From them
+])
+
+# -------------------------------------------
+# Test 'From' encoding
+# -------------------------------------------
+
+# Test read mode
+
+AT_SETUP([from filter encoding (read)])
+AT_KEYWORDS([from frome fromer encode])
+
+AT_CHECK([
+AT_DATA([input],from_plain_text)
+fltst from encode read < input
+],
+[0],
+[from_encoded_text])
+
+AT_CLEANUP
+
+# The same, in write mode
+
+AT_SETUP([from filter encoding (write)])
+AT_KEYWORDS([from frome fromew encode])
+
+AT_CHECK([
+AT_DATA([input],from_plain_text)
+fltst from encode write < input
+],
+[0],
+[from_encoded_text])
+
+AT_CLEANUP
+
+# -------------------------------------------
+# Test '>From' decoding
+# -------------------------------------------
+
+AT_SETUP([from filter decoding (read)])
+AT_KEYWORDS([from fromd fromdr decode])
+
+AT_CHECK([
+AT_DATA([input],from_encoded_text)
+fltst from decode read < input
+],
+[0],
+[from_plain_text])
+
+AT_CLEANUP
+
+# The same, in write mode
+
+AT_SETUP([from filter decoding (write)])
+AT_KEYWORDS([from fromd fromdw decode])
+
+AT_CHECK([
+AT_DATA([input],from_encoded_text)
+fltst from decode write < input
+],
+[0],
+[from_plain_text])
+
+AT_CLEANUP
diff --git a/libmailutils/tests/testsuite.at b/libmailutils/tests/testsuite.at
index 1de64b66b..fbdc7c99b 100644
--- a/libmailutils/tests/testsuite.at
+++ b/libmailutils/tests/testsuite.at
@@ -60,7 +60,8 @@ m4_include([argcv.at])
m4_include([url.at])
m4_include([mailcap.at])
m4_include([base64e.at])
m4_include([base64d.at])
m4_include([decode2047.at])
m4_include([encode2047.at])
+m4_include([fromflt.at])
diff --git a/libproto/mbox/mbox.c b/libproto/mbox/mbox.c
index 62507657e..cc412ff37 100644
--- a/libproto/mbox/mbox.c
+++ b/libproto/mbox/mbox.c
@@ -25,12 +25,13 @@
# include <config.h>
#endif
#include <mbox0.h>
#include <mailutils/cstr.h>
#include <mailutils/io.h>
+#include <mailutils/filter.h>
#define ATTRIBUTE_IS_DELETED(flag) (flag & MU_ATTRIBUTE_DELETED)
#define ATTRIBUTE_IS_EQUAL(flag1, flag2) (flag1 == flag2)
static int mbox_is_updated (mu_mailbox_t mailbox);
static int mbox_expunge0 (mu_mailbox_t mailbox, int remove_deleted);
@@ -1030,13 +1031,13 @@ uid_to_stream (mu_stream_t ostr, mu_message_t msg, mbox_data_t mud, int flags)
/* Append MSG to stream OSTR in its current position */
static int
append_message_to_stream (mu_stream_t ostr, mu_message_t msg,
mbox_data_t mud, int flags)
{
int status;
- mu_stream_t istr;
+ mu_stream_t istr, flt;
status = msg_envelope_to_stream (ostr, msg);
if (status)
return status;
if (flags & MBOX_EXPUNGE)
@@ -1081,16 +1082,24 @@ append_message_to_stream (mu_stream_t ostr, mu_message_t msg,
else
{
status = mu_message_get_streamref (msg, &istr);
if (status)
return status;
}
- status = mu_stream_copy (ostr, istr, 0, NULL);
- mu_stream_destroy (&istr);
+
+ status = mu_filter_create (&flt, istr, "FROM",
+ MU_FILTER_ENCODE, MU_STREAM_READ);
+ mu_stream_unref (istr);
if (status == 0)
- status = mu_stream_write (ostr, "\n", 1, NULL);
+ {
+ status = mu_stream_copy (ostr, flt, 0, NULL);
+ mu_stream_destroy (&flt);
+ if (status == 0)
+ status = mu_stream_write (ostr, "\n", 1, NULL);
+ }
+
return status;
}
static int
mbox_append_message (mu_mailbox_t mailbox, mu_message_t msg)
{

Return to:

Send suggestions and report system problems to the System administrator.