summaryrefslogtreecommitdiff
path: root/libmailutils/filter.c
diff options
context:
space:
mode:
Diffstat (limited to 'libmailutils/filter.c')
-rw-r--r--libmailutils/filter.c193
1 files changed, 193 insertions, 0 deletions
diff --git a/libmailutils/filter.c b/libmailutils/filter.c
new file mode 100644
index 000000000..8fdc25f90
--- /dev/null
+++ b/libmailutils/filter.c
@@ -0,0 +1,193 @@
+/* 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, write to the
+ Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301 USA */
+
+/* Notes:
+ First draft: Alain Magloire.
+ Complete rewrite: Sergey Poznyakoff.
+*/
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+
+#include <errno.h>
+#include <string.h>
+#include <stdlib.h>
+
+#ifdef HAVE_STRINGS_H
+# include <strings.h>
+#endif
+
+#include <mailutils/filter.h>
+#include <mailutils/monitor.h>
+#include <mailutils/list.h>
+#include <mailutils/stream.h>
+#include <mailutils/errno.h>
+#include <mailutils/cstr.h>
+
+/* NOTE: We will leak here since the monitor of the filter will never
+ be release. That's ok we can leave with this, it's only done once. */
+static mu_list_t filter_list;
+struct mu_monitor filter_monitor = MU_MONITOR_INITIALIZER;
+
+static int
+filter_name_cmp (const void *item, const void *data)
+{
+ struct _mu_filter_record const *rec = item;
+ char const *name = data;
+ return mu_c_strcasecmp (rec->name, name);
+}
+
+int
+mu_filter_get_list (mu_list_t *plist)
+{
+ if (plist == NULL)
+ return MU_ERR_OUT_PTR_NULL;
+ mu_monitor_wrlock (&filter_monitor);
+ if (filter_list == NULL)
+ {
+ int status = mu_list_create (&filter_list);
+ if (status != 0)
+ return status;
+ mu_list_set_comparator (filter_list, filter_name_cmp);
+ /* Default filters. */
+ mu_list_append (filter_list, mu_base64_filter);
+ mu_list_append (filter_list, mu_qp_filter);
+ mu_list_append (filter_list, mu_binary_filter);
+ mu_list_append (filter_list, mu_bit8_filter);
+ mu_list_append (filter_list, mu_bit7_filter);
+ 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);
+ /* FIXME: add the default encodings? */
+ }
+ *plist = filter_list;
+ mu_monitor_unlock (&filter_monitor);
+ 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 (mu_stream_t *pstream, mu_stream_t stream, const char *name,
+ int mode, int flags)
+{
+ int status;
+ mu_filter_record_t frec;
+ mu_list_t list;
+ void *xdata = NULL;
+
+ if ((flags & MU_STREAM_RDWR) == MU_STREAM_RDWR)
+ return EINVAL;
+
+ mu_filter_get_list (&list);
+ status = mu_list_locate (list, (void*)name, (void**)&frec);
+ if (status)
+ return status;
+
+ if (frec->newdata)
+ {
+ status = frec->newdata (&xdata, mode, NULL);
+ if (status)
+ return status;
+ }
+
+ status = ((flags & MU_STREAM_WRITE) ? filter_create_wr : filter_create_rd)
+ (pstream, stream,
+ frec->max_line_length,
+ mode,
+ mode == MU_FILTER_ENCODE ? frec->encoder : frec->decoder,
+ xdata,
+ flags);
+ if (status)
+ free (xdata);
+ return status;
+}

Return to:

Send suggestions and report system problems to the System administrator.