diff options
author | Sergey Poznyakoff <gray@gnu.org> | 2020-11-23 13:11:29 +0200 |
---|---|---|
committer | Sergey Poznyakoff <gray@gnu.org> | 2020-11-23 13:20:58 +0200 |
commit | 9763fd4a43128bcd08de8e88cce4142473d38d06 (patch) | |
tree | c4d298e58eb19dd46cc2a11652013827ef9c264d /libmailutils | |
parent | ae91979e9664d99204beb116b9b5e4122e43938e (diff) | |
download | mailutils-9763fd4a43128bcd08de8e88cce4142473d38d06.tar.gz mailutils-9763fd4a43128bcd08de8e88cce4142473d38d06.tar.bz2 |
Implement mboxrb format (a replacement for the mbox used currently)
* configure.ac: New format: mboxrb
* include/mailutils/filter.h (mu_fromrb_filter): New extern.
* include/mailutils/registrar.h (mu_mboxrb_record): New extern.
(mu_register_all_mbox_formats)
(mu_register_local_mbox_formats): Add mu_mboxrb_record.
* libmailutils/filter/filter.c (mu_filter_get_list): Add mu_fromrb_filter
* libproto/Makefile.am [MU_COND_SUPPORT_MBOXRB]: Add mboxrb
* bootstrap.conf: Remove special handling for testsuite/maildir (fixes
1d846d2d92).
* testsuite/mbop.c: Implement the -r (--read-only) option.
* include/mailutils/sys/Makefile.am: Add mboxrb.h
* include/mailutils/sys/mboxrb.h: New file.
* libmailutils/filter/Makefile.am (libfilter_la_SOURCES): Add fromrb.c
* libmailutils/filter/fromrb.c: New file.
* libmailutils/tests/Makefile.am: New file.
* libmailutils/tests/fromrb.at: New file.
* libmailutils/tests/testsuite.at: New file.
* libproto/mboxrb/Makefile.am: New file.
* libproto/mboxrb/mboxrb.c: New file.
* libproto/mboxrb/message.c: New file.
* libproto/mboxrb/tests/.gitignore: New file.
* libproto/mboxrb/tests/Makefile.am: New file.
* libproto/mboxrb/tests/atlocal.in: New file.
* libproto/mboxrb/tests/attr.at: New file.
* libproto/mboxrb/tests/autodetect.at: New file.
* libproto/mboxrb/tests/body.at: New file.
* libproto/mboxrb/tests/count.at: New file.
* libproto/mboxrb/tests/env.at: New file.
* libproto/mboxrb/tests/header.at: New file.
* libproto/mboxrb/tests/testsuite.at: New file.
Diffstat (limited to 'libmailutils')
-rw-r--r-- | libmailutils/filter/Makefile.am | 1 | ||||
-rw-r--r-- | libmailutils/filter/filter.c | 2 | ||||
-rw-r--r-- | libmailutils/filter/fromrb.c | 282 | ||||
-rw-r--r-- | libmailutils/tests/Makefile.am | 1 | ||||
-rw-r--r-- | libmailutils/tests/fromrb.at | 56 | ||||
-rw-r--r-- | libmailutils/tests/testsuite.at | 1 |
6 files changed, 343 insertions, 0 deletions
diff --git a/libmailutils/filter/Makefile.am b/libmailutils/filter/Makefile.am index 5a27dec15..353237b13 100644 --- a/libmailutils/filter/Makefile.am +++ b/libmailutils/filter/Makefile.am @@ -29,6 +29,7 @@ libfilter_la_SOURCES =\ filter.c\ fltchain.c\ fromflt.c\ + fromrb.c\ header.c\ htmlent.c\ iconvflt.c\ diff --git a/libmailutils/filter/filter.c b/libmailutils/filter/filter.c index e8d0b5ce7..381236b1e 100644 --- a/libmailutils/filter/filter.c +++ b/libmailutils/filter/filter.c @@ -87,6 +87,8 @@ mu_filter_get_list (mu_list_t *plist) mu_list_append (filter_list, mu_xml_filter); mu_list_append (filter_list, mu_percent_filter); mu_list_append (filter_list, mu_dq_filter); + mu_list_append (filter_list, mu_fromrb_filter); + /* FIXME: add the default encodings? */ } *plist = filter_list; diff --git a/libmailutils/filter/fromrb.c b/libmailutils/filter/fromrb.c new file mode 100644 index 000000000..40c1cae95 --- /dev/null +++ b/libmailutils/filter/fromrb.c @@ -0,0 +1,282 @@ +#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 + { + S_INIT, /* Initial state */ + S_BOL, /* Beginning of line */ + S_ESC, /* Collecting > escapes */ + S_FROM, /* Collecting "From " characters */ + }; + +struct transcoder +{ + int state; /* Transcoder state */ + int count; /* Number of consecutive '>' seen. */ + int len; /* Number of "From" charactes collected */ +}; + +static char from_line[] = "From "; + +/* Move min(isize,osize) bytes from iptr to optr, removing initial '>' + from each sequence '>+From ' at the beginning of line */ +static enum mu_filter_result +_fromrb_decoder (void *xd, + enum mu_filter_command cmd, + struct mu_filter_io *iobuf) +{ + const unsigned char *iptr; + size_t isize; + char *optr; + size_t osize; + struct transcoder *xcode = xd; + size_t i, j, k; + size_t len, reqlen; + + switch (cmd) + { + case mu_filter_init: + xcode->state = S_BOL; + xcode->count = 0; + xcode->len = 0; + return mu_filter_ok; + + case mu_filter_done: + return mu_filter_ok; + + default: + 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++; + + switch (xcode->state) + { + case S_INIT: + optr[j++] = c; + if (c == '\n') + xcode->state = S_BOL; + break; + + case S_BOL: + if (c == '>') + { + xcode->state = S_ESC; + xcode->count = 1; + } + else + { + optr[j++] = c; + xcode->state = S_INIT; + } + break; + + case S_ESC: + if (c == '>') + { + xcode->count++; + } + else if (c == from_line[0]) + { + xcode->state = S_FROM; + xcode->len = 1; + } + else + { + xcode->state = S_INIT; + goto emit; + } + break; + + case S_FROM: + if (from_line[xcode->len] == 0) + { + xcode->count--; + } + else if (c == from_line[xcode->len]) + { + xcode->len++; + continue; + } + else + { + //RESTORE + } + emit: + reqlen = xcode->len + xcode->count; + len = osize - j; + if (len < reqlen) + { + iobuf->osize = reqlen; + return mu_filter_moreoutput; + } + for (k = 0; k < xcode->count; k++, j++) + optr[j] = '>'; + memcpy (optr + j, from_line, xcode->len); + j += xcode->len; + + xcode->state = S_INIT; + xcode->count = xcode->len = 0; + i--; + iptr--; + } + } + iobuf->isize = i; + iobuf->osize = j; + return mu_filter_ok; +} + +static enum mu_filter_result +_fromrb_encoder (void *xd, + enum mu_filter_command cmd, + struct mu_filter_io *iobuf) +{ + const unsigned char *iptr; + size_t isize; + char *optr; + size_t osize; + struct transcoder *xcode = xd; + size_t i, j, k; + size_t len, reqlen; + + switch (cmd) + { + case mu_filter_init: + xcode->state = S_BOL; + xcode->count = 0; + xcode->len = 0; + return mu_filter_ok; + + case mu_filter_done: + return mu_filter_ok; + + default: + 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++; + + switch (xcode->state) + { + case S_INIT: + optr[j++] = c; + if (c == '\n') + xcode->state = S_BOL; + break; + + case S_BOL: + if (c == '>') + { + xcode->state = S_ESC; + xcode->count = 1; + } + else if (c == from_line[0]) + { + xcode->state = S_FROM; + xcode->count = 0; + xcode->len = 1; + } + else + { + optr[j++] = c; + xcode->state = S_INIT; + } + break; + + case S_ESC: + if (c == '>') + { + xcode->count++; + } + else if (c == from_line[0]) + { + xcode->state = S_FROM; + xcode->len = 1; + } + else + { + xcode->state = S_INIT; + goto emit; + } + break; + + case S_FROM: + if (from_line[xcode->len] == 0) + { + xcode->count++; + } + else if (c == from_line[xcode->len]) + { + xcode->len++; + continue; + } + else + { + //RESTORE + } + emit: + reqlen = xcode->len + xcode->count; + len = osize - j; + if (len < reqlen) + { + iobuf->osize = reqlen; + return mu_filter_moreoutput; + } + for (k = 0; k < xcode->count; k++, j++) + optr[j] = '>'; + memcpy (optr + j, from_line, xcode->len); + j += xcode->len; + + xcode->state = S_INIT; + xcode->count = xcode->len = 0; + i--; + iptr--; + } + } + iobuf->isize = i; + iobuf->osize = j; + return mu_filter_ok; +} + + +static int +_fromrb_alloc_state (void **pret, int mode, + int argc MU_ARG_UNUSED, const char **argv MU_ARG_UNUSED) +{ + *pret = malloc (sizeof (struct transcoder)); + if (!*pret) + return ENOMEM; + return 0; +} + +static struct _mu_filter_record _fromrb_filter = { + "FROMRB", + _fromrb_alloc_state, + _fromrb_encoder, + _fromrb_decoder +}; + +mu_filter_record_t mu_fromrb_filter = &_fromrb_filter; + + diff --git a/libmailutils/tests/Makefile.am b/libmailutils/tests/Makefile.am index 19aa995e6..6b5ea8bd5 100644 --- a/libmailutils/tests/Makefile.am +++ b/libmailutils/tests/Makefile.am @@ -103,6 +103,7 @@ TESTSUITE_AT += \ encode2047.at\ exp.at\ fromflt.at\ + fromrb.at\ fsaf.at\ fsaftomod.at\ fsfolder00.at\ diff --git a/libmailutils/tests/fromrb.at b/libmailutils/tests/fromrb.at new file mode 100644 index 000000000..022927bf2 --- /dev/null +++ b/libmailutils/tests/fromrb.at @@ -0,0 +1,56 @@ +AT_SETUP([FROMRB filter]) +AT_DATA([enc], +[From me +Fromme + From me +Fram me +From +> From me +>> From me +> >From me +>From me +>>From me +]) +AT_CHECK([fltst FROMRB encode read < enc], +[0], +[>From me +Fromme + From me +Fram me +From +> From me +>> From me +> >From me +>>From me +>>>From me +]) + +AT_DATA([dec], +[From me +>From me +>>From me +>>Fromme +> From me +>> From me +> >From me +>From +>FroM X +>FrOm X +>FRom X +]) +AT_CHECK([fltst FROMRB decode read < dec], +[0], +[From me +From me +>From me +>>Fromme +> From me +>> From me +> >From me +>From +>FroM X +>FrOm X +>FRom X +]) + +AT_CLEANUP diff --git a/libmailutils/tests/testsuite.at b/libmailutils/tests/testsuite.at index 6888f39e6..b78a61767 100644 --- a/libmailutils/tests/testsuite.at +++ b/libmailutils/tests/testsuite.at @@ -220,6 +220,7 @@ m4_include([encode2047.at]) AT_BANNER(Filters) m4_include([fromflt.at]) +m4_include([fromrb.at]) m4_include([inline-comment.at]) m4_include([hdrflt.at]) m4_include([hdrcpy.at]) |