commit-mailutils
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[SCM] GNU Mailutils branch, master, updated. release-2.2-278-g8f8d903


From: Sergey Poznyakoff
Subject: [SCM] GNU Mailutils branch, master, updated. release-2.2-278-g8f8d903
Date: Thu, 09 Dec 2010 08:30:28 +0000

This is an automated email from the git hooks/post-receive script. It was
generated because a ref change was pushed to the repository containing
the project "GNU Mailutils".

http://git.savannah.gnu.org/cgit/mailutils.git/commit/?id=8f8d9036cc943e4884b21ad050a1d443e102e47e

The branch, master has been updated
       via  8f8d9036cc943e4884b21ad050a1d443e102e47e (commit)
       via  aa1caef5a181287fcd68a4ec9a600e4927a40833 (commit)
       via  55086f9411acfcf185f8f535b301b52600c48c68 (commit)
      from  e20d435c8e310046c15acbdf47fa458fe7ead1ae (commit)

Those revisions listed above that are new to this repository have
not appeared on any other notification email; so we list those
revisions in full, below.

- Log -----------------------------------------------------------------
commit 8f8d9036cc943e4884b21ad050a1d443e102e47e
Author: Sergey Poznyakoff <address@hidden>
Date:   Thu Dec 9 10:01:06 2010 +0200

    Implement filter chains. Revamp filter output length support.
    
    * include/mailutils/filter.h (mu_filter_chain_create_pred)
    (mu_filter_chain_create): New prototypes.
    (_mu_filter_record)<max_line_length>: Remove.
    * libmailutils/filter/fltchain.c: New file.
    * libmailutils/filter/Makefile.am (libfilter_la_SOURCES): Add fltchain.c.
    * libmailutils/filter/base64.c: Implement line length limit for encoder.
    (base64_state): New enum.
    (base64_line): New struct.
    (_base64_encoder): xd brings a pointer to struct base64_line. Use it
    to limit the output line length.
    (alloc_state): New function.
    (_base64_filter): Register alloc_state.
    (_base64_filter, _B_filter): Remove max_line_length initialization.
    
    * libmailutils/filter/binflt.c: Remove max_line_length initialization.
    * libmailutils/filter/crlfflt.c: Likewise.
    * libmailutils/filter/dot.c: Likewise.
    * libmailutils/filter/fromflt.c: Likewise.
    * libmailutils/filter/header.c: Likewise.
    * libmailutils/filter/inline-comment.c: Likewise.
    * libmailutils/filter/linecon.c: Likewise.
    * libmailutils/filter/qpflt.c: Likewise.
    
    * libmailutils/filter/linelenflt.c: Redo line filter as a regular filter.
    (mu_linelen_filter): New global.
    
    * libmailutils/filter/filter.c (mu_filter_get_list): Register 
mu_linelen_filter.
    (filter_create_rd, filter_create_wr): Remove.
    (mu_filter_create_args): Use mu_filter_stream_create directly.
    
    * examples/base64.c: Re-implement the -l option via filter chains.
    
    * libmailutils/tests/fltst.c: Remove the linelen option.
    * libmailutils/tests/base64d.at: Remove the linelen option from fltst
    invocations.
    * mu/filter.c: Remove the --line-length option.  Not needed now, its
    effect is achieved by "FLT + [~]linelen" chain.

commit aa1caef5a181287fcd68a4ec9a600e4927a40833
Author: Sergey Poznyakoff <address@hidden>
Date:   Wed Dec 8 20:58:52 2010 +0200

    Minor improvement
    
    * examples/config/dot.biffrc: Update.
    * comsat/comsat.c (main): In test mode, normalize biffrc names that
    begin with ./ or ../

commit 55086f9411acfcf185f8f535b301b52600c48c68
Author: Sergey Poznyakoff <address@hidden>
Date:   Wed Dec 8 20:36:48 2010 +0200

    comsat: provide a fine-grained control over where biffrc errors are output
    
    * comsat/comsat.c (biffrc_errors): New variable.
    (comsat_cfg_param): New statements: biffrc-errors-to-tty and
    biffrc-errors-to-err
    (main): In test mode, set biffrc_errors to BIFFRC_ERRORS_TO_ERR.
    * comsat/comsat.h (BIFFRC_ERRORS_TO_TTY)
    (BIFFRC_ERRORS_TO_ERR): New flags.
    (biffrc_errors): New variable.
    * comsat/action.c (report_error): Consult biffrc_errors.

-----------------------------------------------------------------------

Summary of changes:
 comsat/action.c                      |   20 ++--
 comsat/comsat.c                      |   41 +++++++-
 comsat/comsat.h                      |    5 +
 examples/base64.c                    |   50 ++++-----
 examples/config/dot.biffrc           |   27 ++++-
 include/mailutils/filter.h           |   11 ++-
 libmailutils/filter/Makefile.am      |    1 +
 libmailutils/filter/base64.c         |  102 ++++++++++++++++--
 libmailutils/filter/binflt.c         |    3 -
 libmailutils/filter/crlfdot.c        |    1 -
 libmailutils/filter/crlfflt.c        |    2 -
 libmailutils/filter/dot.c            |    1 -
 libmailutils/filter/filter.c         |   85 +--------------
 libmailutils/filter/fltchain.c       |  187 ++++++++++++++++++++++++++++++++++
 libmailutils/filter/fromflt.c        |    1 -
 libmailutils/filter/header.c         |    1 -
 libmailutils/filter/inline-comment.c |    1 -
 libmailutils/filter/linecon.c        |    1 -
 libmailutils/filter/linelenflt.c     |   31 ++++++
 libmailutils/filter/qpflt.c          |    2 -
 libmailutils/tests/base64d.at        |    4 +-
 libmailutils/tests/fltst.c           |   29 +-----
 mu/filter.c                          |   31 ------
 23 files changed, 428 insertions(+), 209 deletions(-)
 create mode 100644 libmailutils/filter/fltchain.c

diff --git a/comsat/action.c b/comsat/action.c
index 2d9aa39..59f3c6f 100644
--- a/comsat/action.c
+++ b/comsat/action.c
@@ -314,15 +314,19 @@ struct biffrc_environ
 static void
 report_error (struct biffrc_environ *env, const char *fmt, ...)
 {
-  va_list ap;
-  va_start (ap, fmt);
-  mu_vasnprintf (&env->errbuf, &env->errsize, fmt, ap);
-  mu_stream_printf (env->logstr, "%s\n", env->errbuf);
-  mu_diag_output (MU_DIAG_ERROR, "%s", env->errbuf);
-  va_end (ap);
+  if (biffrc_errors)
+    {
+      va_list ap;
+      va_start (ap, fmt);
+      mu_vasnprintf (&env->errbuf, &env->errsize, fmt, ap);
+      if (biffrc_errors & BIFFRC_ERRORS_TO_TTY)
+       mu_stream_printf (env->logstr, "%s\n", env->errbuf);
+      if (biffrc_errors & BIFFRC_ERRORS_TO_ERR)
+       mu_diag_output (MU_DIAG_ERROR, "%s", env->errbuf);
+      va_end (ap);
+    }
 }
-                 
-  
+
 static void
 action_beep (struct biffrc_environ *env, size_t argc, char **argv)
 {
diff --git a/comsat/comsat.c b/comsat/comsat.c
index d16106c..8d57999 100644
--- a/comsat/comsat.c
+++ b/comsat/comsat.c
@@ -54,7 +54,7 @@ typedef struct utmp UTMP;
 #define MAX_TTY_SIZE (sizeof (PATH_TTY_PFX) + sizeof (((UTMP*)0)->ut_line))
 
 const char *program_version = "comsatd (" PACKAGE_STRING ")";
-static char doc[] = N_("GNU comsatd -- the Comsat daemon.");
+static char doc[] = N_("GNU comsatd -- notify users about incoming mail");
 static char args_doc[] = N_("\n--test MBOX-URL MSG-QID");
 
 #define OPT_FOREGROUND 256
@@ -100,6 +100,7 @@ int maxlines = 5;
 char *hostname;
 const char *username;
 int require_tty;
+int biffrc_errors = BIFFRC_ERRORS_TO_TTY | BIFFRC_ERRORS_TO_ERR;
 mu_m_server_t server;
 
 static void comsat_init (void);
@@ -114,11 +115,45 @@ static int reload = 0;
 int test_mode;
 char *biffrc = BIFF_RC;
 
+static int
+biffrc_error_ctl (mu_config_value_t *val, int flag)
+{
+  int res;
+  
+  if (mu_cfg_assert_value_type (val, MU_CFG_STRING))
+    return 1;
+  if (mu_cfg_parse_boolean (val->v.string, &res))
+    mu_diag_output (MU_LOG_ERROR, _("not a boolean"));
+  else if (res)
+    biffrc_errors |= flag;
+  else
+    biffrc_errors &= ~flag;
+  return 0;
+}
+    
+static int
+cb_biffrc_errors_to_tty (void *data, mu_config_value_t *val)
+{
+  return biffrc_error_ctl (val, BIFFRC_ERRORS_TO_TTY);
+}
+
+static int
+cb_biffrc_errors_to_err (void *data, mu_config_value_t *val)
+{
+  return biffrc_error_ctl (val, BIFFRC_ERRORS_TO_ERR);
+}
+
 struct mu_cfg_param comsat_cfg_param[] = {
   { "allow-biffrc", mu_cfg_bool, &allow_biffrc, 0, NULL,
     N_("Read .biffrc file from the user home directory.") },
   { "require-tty", mu_cfg_bool, &require_tty, 0, NULL,
     N_("Notify only if the user is logged on one of the ttys.") },
+  { "biffrc-errors-to-tty", mu_cfg_callback, NULL, 0, cb_biffrc_errors_to_tty,
+    N_("Send biffrc errors to user's tty."),
+    N_("arg: bool") },
+  { "biffrc-errors-to-err", mu_cfg_callback, NULL, 0, cb_biffrc_errors_to_err,
+    N_("Send biffrc errors to Mailutils error output."),
+    N_("arg: bool") },
   { "max-lines", mu_cfg_int, &maxlines, 0, NULL,
     N_("Maximum number of message body lines to be output.") },
   { "max-requests", mu_cfg_uint, &maxrequests, 0, NULL,
@@ -548,6 +583,7 @@ main (int argc, char **argv)
       argv += ind;
   
       mu_stdstream_strerr_setup (MU_STRERR_STDERR);
+      biffrc_errors = BIFFRC_ERRORS_TO_ERR;
       if (argc < 2 || argc > 2)
        {
          mu_error (_("mailbox URL and message QID are required in test mode"));
@@ -570,7 +606,8 @@ main (int argc, char **argv)
            }
        }
 
-      if (biffrc[0] == '.' && biffrc[1] == '/')
+      if (biffrc[0] == '.' && (biffrc[1] == '/' ||
+                              (biffrc[1] == '.' && biffrc[2] == '/')))
        {
          char *cwd = mu_getcwd ();
          biffrc = mu_make_file_name (cwd, biffrc);
diff --git a/comsat/comsat.h b/comsat/comsat.h
index ff43819..2fa3257 100644
--- a/comsat/comsat.h
+++ b/comsat/comsat.h
@@ -68,6 +68,10 @@
 
 #define BIFF_RC ".biffrc"
 
+/* Where to report biffrc errors to: */
+#define BIFFRC_ERRORS_TO_TTY 0x01  /* Send them to the user's tty */
+#define BIFFRC_ERRORS_TO_ERR 0x02  /* Send them to strerr */
+
 extern int allow_biffrc;
 extern unsigned maxrequests;
 extern time_t request_control_interval;
@@ -78,6 +82,7 @@ extern const char *username;
 extern char *hostname;
 extern struct daemon_param daemon_param;
 extern char *biffrc;
+extern int biffrc_errors;
 
 void run_user_action (const char *device, mu_message_t msg);
 
diff --git a/examples/base64.c b/examples/base64.c
index 2e80a60..97d34a2 100644
--- a/examples/base64.c
+++ b/examples/base64.c
@@ -93,23 +93,6 @@ c_copy (mu_stream_t out, mu_stream_t in)
     }
 }
 
-/* Set the maximum line length for the filter NAME to LENGTH.
-   FIXME: This is a kludge. Perhaps API should provide a function
-   for that. */
-static void
-reset_line_length (const char *name, size_t length)
-{
-  mu_list_t list;
-  int status;
-  mu_filter_record_t frec;
-  
-  mu_filter_get_list (&list);
-  status = mu_list_locate (list, (void*)name, (void**)&frec);
-  if (status == 0)
-    frec->max_line_length = length;
-  /* don't bail out, leave that to mu_filter_create */
-}
-
 int
 main (int argc, char * argv [])
 {
@@ -120,8 +103,9 @@ main (int argc, char * argv [])
   char *input = NULL, *output = NULL;
   char *encoding = "base64";
   mu_off_t shift = 0;
-  size_t line_length;
-  int line_length_option = 0;
+  char *line_length_option = NULL;
+  char *fargv[5];
+  size_t fargc = 0;
   
   while ((c = getopt (argc, argv, "deE:hi:l:o:ps:vw")) != EOF)
     switch (c)
@@ -147,8 +131,7 @@ main (int argc, char * argv [])
        break;
 
       case 'l':
-       line_length = strtoul (optarg, NULL, 10);
-       line_length_option = 1;
+       line_length_option = optarg;
        break;
        
       case 'p':
@@ -186,22 +169,33 @@ main (int argc, char * argv [])
   else
     MU_ASSERT (mu_stdio_stream_create (&out, MU_STDOUT_FD, 0));
 
-  if (line_length_option)
-    reset_line_length (encoding, line_length);
+  fargv[fargc++] = encoding;
+  if (line_length_option && strcmp (line_length_option, "0"))
+    {
+      if (mu_c_strcasecmp (encoding, "base64") == 0)
+       fargv[0] = "B"; /* B encoding has no length limit */
+      fargv[fargc++] = "+";
+      fargv[fargc++] = (mode == MU_FILTER_DECODE) ? "~linelen" : "linelen";
+      fargv[fargc++] = line_length_option;
+    }
+  fargv[fargc] = NULL;
   
   if (flags == MU_STREAM_READ)
     {
-      MU_ASSERT (mu_filter_create (&flt, in, encoding, mode,
-                                  MU_STREAM_READ|MU_STREAM_SEEK|
-                                  MU_STREAM_AUTOCLOSE));
+      MU_ASSERT (mu_filter_chain_create (&flt, in, mode,
+                                        MU_STREAM_READ|MU_STREAM_SEEK,
+                                        fargc, fargv));
+      mu_stream_unref (in);
       if (shift)
        MU_ASSERT (mu_stream_seek (flt, shift, MU_SEEK_SET, NULL));
       c_copy (out, flt);
     }
   else
     {
-      MU_ASSERT (mu_filter_create (&flt, out, encoding, mode,
-                                  MU_STREAM_WRITE|MU_STREAM_AUTOCLOSE));
+      MU_ASSERT (mu_filter_chain_create (&flt, out, mode,
+                                        MU_STREAM_WRITE,
+                                        fargc, fargv));
+      mu_stream_unref (out);
       if (shift)
        MU_ASSERT (mu_stream_seek (in, shift, MU_SEEK_SET, NULL));
       c_copy (flt, in);
diff --git a/examples/config/dot.biffrc b/examples/config/dot.biffrc
index 755cc8f..1f74c80 100644
--- a/examples/config/dot.biffrc
+++ b/examples/config/dot.biffrc
@@ -3,11 +3,28 @@
 # the user and have permissions 0600
 # Each line specifies an action to be taken upon arrival of
 # a message. A backslash can be used to escape the newlines.
-# Actions could be:
-#  beep              --  Produce audible signal
-#  echo STRING       --  Output STRING to the user's tty
-#  exec PROG ARGS... --  Execute given program 
 #
+# Valid actions are:
+# * beep
+#     Produces audible signal.
+# * echo [-n] ARGS
+#     Outputs ARGS to the tty.  The -n option suppresses trailing newline.
+# * exec PROG ARGS...
+#     Executes the program PROG with the given arguments.
+# * default
+#     Executes the default (built-in) actions.
+# * tty NAME [[~]FLT [ARGS] [+ [~]FLT [ARGS]...]
+#     Opens the file NAME and assigns it as a tty for subsequent commands.
+#     NAME can be any type of file, the only requirement being that it
+#     must exist.  Optional arguments insert a chain of filters before
+#     writing to that file or device.  For the list of available filters
+#     run `mu filter --list'.  Filters are applied from right to left.
+#     The ~ in front of a filter name means open this filter in decode more
+#     (by default, filters are opened in encode mode).
+#     Default settings correspond to:
+#          tty /dev/tty 7bit + ?crlf
+#     The ? means apply next filter only if the device needs CR to be output
+#     before each LF.
 
 # This is the default action
 echo "Mail to address@hidden
@@ -15,7 +32,7 @@ From: $H{from}\n\
 Subject: $H{Subject}\n\
 ---\n\
 $B(,5)\n\
----\n"
+---"
 
 # For users of X windows system: produce a bell and open an xmessage window
 beep
diff --git a/include/mailutils/filter.h b/include/mailutils/filter.h
index 8c7f2e8..d936688 100644
--- a/include/mailutils/filter.h
+++ b/include/mailutils/filter.h
@@ -81,11 +81,19 @@ int mu_filter_stream_create (mu_stream_t *pflt,
                             void *xdata, 
                             int flags);
 
+int mu_filter_chain_create_pred (mu_stream_t *pret, mu_stream_t transport,
+                                int defmode, int flags,
+                                size_t argc, char **argv,
+                                int (*pred) (void *, mu_stream_t,
+                                             const char *),
+                                void *closure);
+int mu_filter_chain_create (mu_stream_t *pret, mu_stream_t transport,
+                           int defmode, int flags,
+                           size_t argc, char **argv);
 
 struct _mu_filter_record
 {
   const char *name;
-  size_t max_line_length;
   mu_filter_new_data_t newdata;
   mu_filter_xcode_t encoder;
   mu_filter_xcode_t decoder;
@@ -111,6 +119,7 @@ extern mu_filter_record_t mu_from_filter;
 extern mu_filter_record_t mu_inline_comment_filter;
 extern mu_filter_record_t mu_header_filter;
 extern mu_filter_record_t mu_linecon_filter;
+extern mu_filter_record_t mu_linelen_filter;
 
 enum mu_iconv_fallback_mode
   {
diff --git a/libmailutils/filter/Makefile.am b/libmailutils/filter/Makefile.am
index 38d9101..2d5659b 100644
--- a/libmailutils/filter/Makefile.am
+++ b/libmailutils/filter/Makefile.am
@@ -26,6 +26,7 @@ libfilter_la_SOURCES =\
  dot.c\
  filter.c\
  filter_iconv.c\
+ fltchain.c\
  fromflt.c\
  header.c\
  inline-comment.c\
diff --git a/libmailutils/filter/base64.c b/libmailutils/filter/base64.c
index 2b65cad..0208576 100644
--- a/libmailutils/filter/base64.c
+++ b/libmailutils/filter/base64.c
@@ -175,25 +175,54 @@ _base64_decoder (void *xd MU_ARG_UNUSED,
   return mu_filter_ok;
 }
 
+enum base64_state
+{
+  base64_init,
+  base64_newline,
+  base64_rollback
+};
+
+struct base64_line
+{
+  enum base64_state state;
+  size_t max_len;
+  size_t cur_len;
+  char save[3];
+  int idx;
+};
+
 static enum mu_filter_result
-_base64_encoder (void *xd MU_ARG_UNUSED,
+_base64_encoder (void *xd,
                 enum mu_filter_command cmd,
                 struct mu_filter_io *iobuf)
 {
+  struct base64_line bline, *lp = xd;
   size_t consumed = 0;
   int pad = 0;
-  const unsigned char *ptr = (const unsigned char*) iobuf->input;
+  const unsigned char *ptr;
   size_t nbytes = 0;
   size_t isize;
   char *optr;
   size_t osize;
   enum mu_filter_result res;
-  
+
+  if (!lp)
+    {
+      lp = &bline;
+      lp->max_len = 0;
+      lp->state = base64_init;
+    }
   switch (cmd)
     {
     case mu_filter_init:
+      lp->state = base64_init;
+      lp->cur_len = 0;
+      lp->idx = 3;
+      return mu_filter_ok;
+      
     case mu_filter_done:
       return mu_filter_ok;
+      
     default:
       break;
     }
@@ -214,15 +243,48 @@ _base64_encoder (void *xd MU_ARG_UNUSED,
       return mu_filter_moreoutput;
     }
       
+  ptr = (const unsigned char*) iobuf->input;
   isize = iobuf->isize;
   optr = iobuf->output;
   osize = iobuf->osize;
 
-  while ((consumed + 3 <= isize && nbytes + 4 <= osize) || pad)
+  while (nbytes < osize)
     {
       unsigned char c1 = 0, c2 = 0, x = '=', y = '=';
+
+      if (lp->max_len && lp->cur_len == lp->max_len)
+       {
+         if (lp->state == base64_init)
+           lp->idx = 3;
+         lp->state = base64_newline;
+       }
+      switch (lp->state)
+       {
+       case base64_init:
+         break;
+       case base64_newline:
+         *optr++ = '\n';
+         nbytes++;
+         lp->cur_len = 0;
+         lp->state = base64_rollback;
+         /* Fall through */
+       case base64_rollback:
+         if (lp->idx < 3)
+           {
+             *optr++ = lp->save[lp->idx++];
+             nbytes++;
+             lp->cur_len++;
+             continue;
+           }
+         lp->state = base64_init;
+       }
+
+      if (!(consumed + 3 <= isize || pad))
+       break;
        
       *optr++ = b64tab[ptr[0] >> 2];
+      nbytes++;
+      lp->cur_len++;
       consumed++;
       switch (isize - consumed)
        {
@@ -235,20 +297,22 @@ _base64_encoder (void *xd MU_ARG_UNUSED,
          x = b64tab[((ptr[1] << 2) + c2) & 0x3f];
          c1 = (ptr[1] >> 4);
        case 0:
-         *optr++ = b64tab[((ptr[0] << 4) + c1) & 0x3f];
-         *optr++ = x;
-         *optr++ = y;
+         lp->save[0] = b64tab[((ptr[0] << 4) + c1) & 0x3f];
+         lp->save[1] = x;
+         lp->save[2] = y;
+         lp->idx = 0;
+         lp->state = base64_rollback;
        }
       
       ptr += 3;
-      nbytes += 4;
       pad = 0;
     }
 
   /* Consumed may grow bigger than isize if cmd is mu_filter_lastbuf */
   if (consumed > iobuf->isize)
     consumed = iobuf->isize;
-  if (cmd == mu_filter_lastbuf && consumed < iobuf->isize)
+  if (cmd == mu_filter_lastbuf &&
+      (consumed < iobuf->isize || lp->state == base64_rollback))
     res = mu_filter_again;
   else
     res = mu_filter_ok;
@@ -257,10 +321,25 @@ _base64_encoder (void *xd MU_ARG_UNUSED,
   return res;
 }
 
+static int
+alloc_state (void **pret, int mode, int argc, const char **argv)
+{
+  if (mode == MU_FILTER_ENCODE)
+    {
+      struct base64_line *lp = malloc (sizeof (*lp));
+      if (!lp)
+       return ENOMEM;
+      lp->max_len = 76;
+      *pret = lp;
+    }
+  else
+    *pret = NULL;
+  return 0;
+}
+
 static struct _mu_filter_record _base64_filter = {
   "base64",
-  76,
-  NULL,
+  alloc_state,
   _base64_encoder,
   _base64_decoder
 };
@@ -269,7 +348,6 @@ mu_filter_record_t mu_base64_filter = &_base64_filter;
 
 static struct _mu_filter_record _B_filter = {
   "B",
-  0,
   NULL,
   _base64_encoder,
   _base64_decoder
diff --git a/libmailutils/filter/binflt.c b/libmailutils/filter/binflt.c
index 1faf88c..c0df9be 100644
--- a/libmailutils/filter/binflt.c
+++ b/libmailutils/filter/binflt.c
@@ -83,7 +83,6 @@ _bit7_coder (void *xd MU_ARG_UNUSED,
 
 static struct _mu_filter_record _binary_filter = {
   "binary",
-  0,
   NULL,
   _copy_codec,
   _copy_codec
@@ -94,7 +93,6 @@ mu_filter_record_t mu_binary_filter = &_binary_filter;
 
 static struct _mu_filter_record _bit8_filter = {
   "8bit",
-  0,
   NULL,
   _copy_codec,
   _copy_codec
@@ -104,7 +102,6 @@ mu_filter_record_t mu_bit8_filter = &_bit8_filter;
 
 static struct _mu_filter_record _bit7_filter = {
   "7bit",
-  0,
   NULL,
   _bit7_coder,
   _copy_codec
diff --git a/libmailutils/filter/crlfdot.c b/libmailutils/filter/crlfdot.c
index a0295c7..f6af819 100644
--- a/libmailutils/filter/crlfdot.c
+++ b/libmailutils/filter/crlfdot.c
@@ -327,7 +327,6 @@ alloc_state (void **pret, int mode MU_ARG_UNUSED,
 
 static struct _mu_filter_record _crlfdot_filter = {
   "CRLFDOT",
-  0,
   alloc_state,
   _crlfdot_encoder,
   _crlfdot_decoder
diff --git a/libmailutils/filter/crlfflt.c b/libmailutils/filter/crlfflt.c
index ea5b8ce..a527f38 100644
--- a/libmailutils/filter/crlfflt.c
+++ b/libmailutils/filter/crlfflt.c
@@ -160,7 +160,6 @@ alloc_state (void **pret, int mode,
 
 static struct _mu_filter_record _crlf_filter = {
   "CRLF",
-  0,
   alloc_state,
   _crlf_encoder,
   _crlf_decoder
@@ -172,7 +171,6 @@ mu_filter_record_t mu_crlf_filter = &_crlf_filter;
 /* For compatibility with previous versions */
 static struct _mu_filter_record _rfc822_filter = {
   "RFC822",
-  0,
   alloc_state,
   _crlf_encoder,
   _crlf_decoder
diff --git a/libmailutils/filter/dot.c b/libmailutils/filter/dot.c
index b962161..072576e 100644
--- a/libmailutils/filter/dot.c
+++ b/libmailutils/filter/dot.c
@@ -259,7 +259,6 @@ alloc_state (void **pret, int mode MU_ARG_UNUSED,
 
 static struct _mu_filter_record _dot_filter = {
   "DOT",
-  0,
   alloc_state,
   _dot_encoder,
   _dot_decoder
diff --git a/libmailutils/filter/filter.c b/libmailutils/filter/filter.c
index 1ebd4e9..7a375fe 100644
--- a/libmailutils/filter/filter.c
+++ b/libmailutils/filter/filter.c
@@ -81,6 +81,7 @@ mu_filter_get_list (mu_list_t *plist)
       mu_list_append (filter_list, mu_inline_comment_filter);
       mu_list_append (filter_list, mu_header_filter);
       mu_list_append (filter_list, mu_linecon_filter);
+      mu_list_append (filter_list, mu_linelen_filter);
       /* FIXME: add the default encodings?  */
     }
   *plist = filter_list;
@@ -88,77 +89,6 @@ mu_filter_get_list (mu_list_t *plist)
   return 0;
 }
 
-static int
-filter_create_rd (mu_stream_t *pstream, mu_stream_t stream,
-                 size_t max_line_length,
-                 int mode,
-                 mu_filter_xcode_t xcode, void *xdata,
-                 int flags)
-{
-  int status;
-  mu_stream_t fltstream;
-
-  flags &= ~MU_STREAM_AUTOCLOSE;
-  
-  status = mu_filter_stream_create (&fltstream, stream,
-                                   mode, xcode, xdata,
-                                   flags);
-  if (status == 0)
-    {
-      if (max_line_length)
-       {
-         status = mu_linelen_filter_create (pstream, fltstream,
-                                            max_line_length,
-                                            flags);
-         mu_stream_unref (fltstream);
-         if (status)
-           return status;
-       }
-      else
-       *pstream = fltstream;
-
-      if (flags & MU_STREAM_AUTOCLOSE)
-       mu_stream_unref (stream);
-    }
-  return status;
-}
-
-static int
-filter_create_wr (mu_stream_t *pstream, mu_stream_t stream,
-                 size_t max_line_length,
-                 int mode,
-                 mu_filter_xcode_t xcode, void *xdata,
-                 int flags)
-{
-  int status;
-  mu_stream_t fltstream, instream = NULL, tmpstr;
-  
-  flags &= ~MU_STREAM_AUTOCLOSE;
-
-  if (max_line_length)
-    {
-      status = mu_linelen_filter_create (&instream, stream,
-                                        max_line_length,
-                                        flags);
-      if (status)
-       return status;
-      tmpstr = instream;
-    }
-  else
-    tmpstr = stream;
-  
-  status = mu_filter_stream_create (&fltstream, tmpstr,
-                                   mode, xcode, xdata,
-                                   flags);
-  mu_stream_unref (instream);
-  if (status)
-    return status;
-  *pstream = fltstream;
-  if (flags & MU_STREAM_AUTOCLOSE)
-    mu_stream_unref (stream);
-  return status;
-}
-
 int
 mu_filter_create_args (mu_stream_t *pstream, mu_stream_t stream,
                       const char *name, int argc, const char **argv,
@@ -189,15 +119,12 @@ mu_filter_create_args (mu_stream_t *pstream, mu_stream_t 
stream,
        return status;
     }
 
-  status = ((flags & MU_STREAM_WRITE) ? filter_create_wr : filter_create_rd)
-                   (pstream, stream,
-                   mode == MU_FILTER_ENCODE ? frec->max_line_length : 0,
-                   mode,
-                   xcode,
-                   xdata,
-                   flags);
+  status = mu_filter_stream_create (pstream, stream,
+                                   mode, xcode, xdata,
+                                   flags);
   if (status)
-    free (xdata);
+    free (xdata);  
+
   return status;
 }
 
diff --git a/libmailutils/filter/fltchain.c b/libmailutils/filter/fltchain.c
new file mode 100644
index 0000000..b2c2120
--- /dev/null
+++ b/libmailutils/filter/fltchain.c
@@ -0,0 +1,187 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+   Copyright (C) 1999, 2000, 2001, 2004, 2005, 2007, 2009, 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, see 
+   <http://www.gnu.org/licenses/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#include <mailutils/filter.h>
+#include <mailutils/stream.h>
+#include <mailutils/errno.h>
+
+static int
+negate_filter_mode (int mode)
+{
+  if (mode == MU_FILTER_DECODE)
+    return MU_FILTER_ENCODE;
+  else if (mode == MU_FILTER_ENCODE)
+    return MU_FILTER_DECODE;
+  abort ();
+}
+
+static int
+_add_next_link (mu_stream_t *pret, mu_stream_t transport,
+               int defmode, int flags,
+               size_t argc, char **argv,
+               int (*pred) (void *, mu_stream_t, const char *),
+               void *closure)
+{
+  int mode;
+  int qmark = 0;
+  char *fltname;
+  int status = 0;
+      
+  fltname = argv[0];
+  if (fltname[0] == '?')
+    {
+      if (pred)
+       qmark = 1;
+      fltname++;
+    }
+  
+  if (fltname[0] == '~')
+    {
+      mode = negate_filter_mode (defmode);
+      fltname++;
+    }
+  else
+    mode = defmode;
+      
+  if (qmark == 0 || pred (closure, transport, fltname))
+    {
+      status = mu_filter_create_args (pret, transport, fltname,
+                                     argc, (const char **)argv,
+                                     mode, flags);
+      mu_stream_unref (transport);
+    }
+  return status;
+}
+
+int
+_filter_chain_create (mu_stream_t *pret, mu_stream_t transport,
+                     int defmode,
+                     int flags,
+                     size_t argc, char **argv,
+                     int (*pred) (void *, mu_stream_t, const char *),
+                     void *closure)
+{
+  while (argc)
+    {
+      size_t i;
+      int status;
+      mu_stream_t stream;
+
+      for (i = 1; i < argc; i++)
+       if (strcmp (argv[i], "+") == 0)
+         break;
+
+      status = _add_next_link (&stream, transport,
+                              defmode, flags,
+                              i, argv,
+                              pred, closure);
+      if (status)
+       return status;
+      transport = stream;
+
+      argc -= i;
+      argv += i;
+      if (argc)
+       {
+         argc--;
+         argv++;
+       }
+    }
+  *pret = transport;
+  return 0;
+}
+
+int
+_filter_chain_create_rev (mu_stream_t *pret, mu_stream_t transport,
+                         int defmode,
+                         int flags,
+                         size_t argc, char **argv,
+                         int (*pred) (void *, mu_stream_t, const char *),
+                         void *closure)
+{
+  size_t pos;
+
+  for (pos = argc; pos > 0;)
+    {
+      size_t i;
+      int status;
+      mu_stream_t stream;
+
+      for (i = pos; i > 0; i--)
+       {
+         if (strcmp (argv[i - 1], "+") == 0)
+           break;
+       }
+
+      status = _add_next_link (&stream, transport,
+                              defmode, flags,
+                              pos - i, argv + i,
+                              pred, closure);
+      if (status)
+       return status;
+      transport = stream;
+      if (i > 0)
+       i--;
+      pos = i;
+    }
+  *pret = transport;
+  return 0;
+}
+  
+int
+mu_filter_chain_create_pred (mu_stream_t *pret, mu_stream_t transport,
+                            int defmode,
+                            int flags,
+                            size_t argc, char **argv,
+                            int (*pred) (void *, mu_stream_t, const char *),
+                            void *closure)
+{
+  int rc;
+  
+  mu_stream_ref (transport);
+  if (flags & MU_STREAM_WRITE)
+    rc = _filter_chain_create_rev (pret, transport,
+                                  defmode, flags,
+                                  argc, argv,
+                                  pred, closure);
+  else 
+    rc = _filter_chain_create (pret, transport,
+                              defmode, flags,
+                              argc, argv, pred, closure);
+  if (rc)
+    mu_stream_unref (transport);
+  return rc;
+}
+
+int
+mu_filter_chain_create (mu_stream_t *pret, mu_stream_t transport,
+                       int defmode, int flags,
+                       size_t argc, char **argv)
+{
+  return mu_filter_chain_create_pred (pret, transport, defmode, flags,
+                                     argc, argv, NULL, NULL);
+}
+
diff --git a/libmailutils/filter/fromflt.c b/libmailutils/filter/fromflt.c
index 902fe3c..5822c23 100644
--- a/libmailutils/filter/fromflt.c
+++ b/libmailutils/filter/fromflt.c
@@ -273,7 +273,6 @@ _from_alloc_state (void **pret, int mode,
 
 static struct _mu_filter_record _from_filter = {
   "FROM",
-  0,
   _from_alloc_state,
   _from_encoder,
   _from_decoder
diff --git a/libmailutils/filter/header.c b/libmailutils/filter/header.c
index 8369d6a..01b4b0c 100644
--- a/libmailutils/filter/header.c
+++ b/libmailutils/filter/header.c
@@ -112,7 +112,6 @@ alloc_state (void **pret, int mode MU_ARG_UNUSED,
 
 static struct _mu_filter_record _header_filter = {
   "HEADER",
-  0,
   alloc_state,
   NULL,
   _hflt_decoder
diff --git a/libmailutils/filter/inline-comment.c 
b/libmailutils/filter/inline-comment.c
index 8def8b7..61ee11b 100644
--- a/libmailutils/filter/inline-comment.c
+++ b/libmailutils/filter/inline-comment.c
@@ -487,7 +487,6 @@ alloc_state (void **pret, int mode MU_ARG_UNUSED, int argc, 
const char **argv)
 
 static struct _mu_filter_record _inline_comment_filter = {
   "INLINE-COMMENT",
-  0,
   alloc_state,
   _ilcmt_encoder,
   _ilcmt_decoder
diff --git a/libmailutils/filter/linecon.c b/libmailutils/filter/linecon.c
index f9ebffd..c9ca6bc 100644
--- a/libmailutils/filter/linecon.c
+++ b/libmailutils/filter/linecon.c
@@ -213,7 +213,6 @@ alloc_state (void **pret, int mode MU_ARG_UNUSED, int argc, 
const char **argv)
 
 static struct _mu_filter_record _linecon_filter = {
   "LINECON",
-  0,
   alloc_state,
   NULL,
   _linecon_decoder,
diff --git a/libmailutils/filter/linelenflt.c b/libmailutils/filter/linelenflt.c
index e3817de..8104915 100644
--- a/libmailutils/filter/linelenflt.c
+++ b/libmailutils/filter/linelenflt.c
@@ -107,4 +107,35 @@ mu_linelen_filter_create (mu_stream_t *pstream, 
mu_stream_t stream,
   return mu_filter_stream_create (pstream, stream,
                                  MU_FILTER_ENCODE, _ll_encoder, flt, flags);
 }
+
+static int
+alloc_state (void **pret, int mode MU_ARG_UNUSED, int argc, const char **argv)
+{
+  struct _mu_linelen_filter *flt = malloc (sizeof (flt[0]));
   
+  if (!flt)
+    return ENOMEM;
+  flt->cur_len = 0;
+  flt->max_len = 76;
+  if (argc > 1)
+    {
+      char *p;
+      flt->max_len = strtoul (argv[1], &p, 10);
+      if (*p)
+       {
+         free (flt);
+         return MU_ERR_PARSE;
+       }
+    }
+  *pret = flt;
+  return 0;
+}
+
+static struct _mu_filter_record _linelen_filter = {
+  "LINELEN",
+  alloc_state,
+  _ll_encoder,
+  NULL,
+};
+
+mu_filter_record_t mu_linelen_filter = &_linelen_filter;
diff --git a/libmailutils/filter/qpflt.c b/libmailutils/filter/qpflt.c
index aaada1e..3f2279f 100644
--- a/libmailutils/filter/qpflt.c
+++ b/libmailutils/filter/qpflt.c
@@ -243,7 +243,6 @@ _qp_encoder (void *xd MU_ARG_UNUSED,
 
 static struct _mu_filter_record _qp_filter = {
   "quoted-printable",
-  0,
   NULL,
   _qp_encoder,
   _qp_decoder
@@ -253,7 +252,6 @@ mu_filter_record_t mu_qp_filter = &_qp_filter;
 
 static struct _mu_filter_record _Q_filter = {
   "Q",
-  0,
   NULL,
   _qp_encoder,
   _qp_decoder
diff --git a/libmailutils/tests/base64d.at b/libmailutils/tests/base64d.at
index 9983f58..55ee955 100644
--- a/libmailutils/tests/base64d.at
+++ b/libmailutils/tests/base64d.at
@@ -19,7 +19,7 @@ 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],
+fltst base64 decode read < $abs_top_srcdir/libmailutils/tests/Decode],
 [0],
 [expout])
 
@@ -31,7 +31,7 @@ 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],
+fltst base64 decode write < $abs_top_srcdir/libmailutils/tests/Decode],
 [0],
 [expout])
 
diff --git a/libmailutils/tests/fltst.c b/libmailutils/tests/fltst.c
index a92f1ec..db73e9d 100644
--- a/libmailutils/tests/fltst.c
+++ b/libmailutils/tests/fltst.c
@@ -68,23 +68,6 @@ c_copy (mu_stream_t out, mu_stream_t in)
 
 }
 
-/* Set the maximum line length for the filter NAME to LENGTH.
-   FIXME: This is a kludge. Perhaps API should provide a function
-   for that. */
-static void
-reset_line_length (const char *name, size_t length)
-{
-  mu_list_t list;
-  int status;
-  mu_filter_record_t frec;
-  
-  mu_filter_get_list (&list);
-  status = mu_list_locate (list, (void*)name, (void**)&frec);
-  if (status == 0)
-    frec->max_line_length = length;
-  /* don't bail out, leave that to mu_filter_create */
-}
-
 void
 usage (const char *diag)
 {
@@ -99,7 +82,7 @@ usage (const char *diag)
     fp = stdout;
 
   fprintf (fp, "%s",
-          "usage: fltst FILTER {encode|decode} {read|write} [shift=N] 
[linelen=N] [verbose] [printable] [nl] [-- args]\n");
+          "usage: fltst FILTER {encode|decode} {read|write} [shift=N] 
[verbose] [printable] [nl] [-- args]\n");
   exit (diag ? 1 : 0);
 }
 
@@ -112,8 +95,6 @@ main (int argc, char * argv [])
   int flags = MU_STREAM_READ;
   char *fltname;
   mu_off_t shift = 0;
-  size_t line_length;
-  int line_length_option = 0;
   int newline_option = 0;
   
   if (argc == 1)
@@ -141,11 +122,6 @@ main (int argc, char * argv [])
     {
       if (strncmp (argv[i], "shift=", 6) == 0)
        shift = strtoul (argv[i] + 6, NULL, 0); 
-      else if (strncmp (argv[i], "linelen=", 8) == 0)
-       {
-         line_length = strtoul (argv[i] + 8, NULL, 10);
-         line_length_option = 1;
-       }
       else if (strcmp (argv[i], "verbose") == 0)
        verbose++;
       else if (strcmp (argv[i], "printable") == 0)
@@ -167,9 +143,6 @@ main (int argc, char * argv [])
   MU_ASSERT (mu_stdio_stream_create (&in, MU_STDIN_FD, 0));
   MU_ASSERT (mu_stdio_stream_create (&out, MU_STDOUT_FD, 0));
 
-  if (line_length_option)
-    reset_line_length (fltname, line_length);
-  
   if (flags == MU_STREAM_READ)
     {
       MU_ASSERT (mu_filter_create_args (&flt, in, fltname,
diff --git a/mu/filter.c b/mu/filter.c
index 8d9c222..0b40c4d 100644
--- a/mu/filter.c
+++ b/mu/filter.c
@@ -30,7 +30,6 @@ static char filter_args_doc[] = N_("[~]NAME [ARGS] [+ [~]NAME 
[ARGS]...]");
 static struct argp_option filter_options[] = {
   { "encode", 'e', NULL, 0, N_("encode the input (default)") },
   { "decode", 'd', NULL, 0, N_("decode the input") },
-  { "line-length", 'l', N_("NUMBER"), 0, N_("limit output line length") },
   { "newline", 'n', NULL, 0, N_("print additional newline") },
   { "list", 'L', NULL, 0, N_("list supported filters") },
   { NULL }
@@ -38,15 +37,11 @@ static struct argp_option filter_options[] = {
 
 static int filter_mode = MU_FILTER_ENCODE;
 static int newline_option = 0;
-static size_t line_length;
-static int line_length_option = 0;
 static int list_option;
 
 static error_t
 filter_parse_opt (int key, char *arg, struct argp_state *state)
 {
-  char *p;
-  
   switch (key)
     {
     case 'e':
@@ -61,13 +56,6 @@ filter_parse_opt (int key, char *arg, struct argp_state 
*state)
       newline_option = 1;
       break;
 
-    case 'l':
-      line_length = strtoul (arg, &p, 10);
-      if (*p)
-       argp_error (state, N_("not a number"));
-      line_length_option = 1;
-      break;
-
     case 'L':
       list_option = 1;
       break;
@@ -88,22 +76,6 @@ static struct argp filter_argp = {
   NULL
 };
 
-/* FIXME: This is definitely a kludge. The API should provide a function
-   for that. */
-static void
-reset_line_length (const char *name, size_t length)
-{
-  mu_list_t list;
-  int status;
-  mu_filter_record_t frec;
-  
-  mu_filter_get_list (&list);
-  status = mu_list_locate (list, (void*)name, (void**)&frec);
-  if (status == 0)
-    frec->max_line_length = length;
-  /* don't bail out, leave that to mu_filter_create */
-}
-
 static int
 filter_printer (void *item, void *data)
 {
@@ -184,9 +156,6 @@ mutool_filter (int argc, char **argv)
        if (strcmp (argv[i], "+") == 0)
          break;
       
-      if (line_length_option)
-       reset_line_length (fltname, line_length);
-
       rc = mu_filter_create_args (&flt, prev_stream, fltname,
                                  i, (const char **)argv,
                                  mode, MU_STREAM_READ);


hooks/post-receive
-- 
GNU Mailutils



reply via email to

[Prev in Thread] Current Thread [Next in Thread]