summaryrefslogtreecommitdiffabout
authorSergey Poznyakoff <gray@gnu.org>2019-02-02 07:04:42 (GMT)
committer Sergey Poznyakoff <gray@gnu.org>2019-02-03 09:54:13 (GMT)
commit18e23d6e98bc5942269e385dbb9ea9f0886909ef (patch) (side-by-side diff)
tree9f0a9bb42901c46976eaf23c275ce65d0d03ac41
parent8360e84e5a673211488ee31c93922c987c057007 (diff)
downloadmailutils-18e23d6e98bc5942269e385dbb9ea9f0886909ef.tar.gz
mailutils-18e23d6e98bc5942269e385dbb9ea9f0886909ef.tar.bz2
Rewrite the mailcap support
* configure.ac: Build libmailutils/mailcap/Makefile * include/mailutils/mailcap.h: Rewrite * include/mailutils/sys/Makefile.am: Add mailcap.h * include/mailutils/sys/mailcap.h: New file. * include/mailutils/util.h: Add missing include. * lib/mailcap.c: Rewrite using new API. * libmailutils/Makefile.am: Build in mailcap * libmailutils/base/Makefile.am: Remove mailcap.c * libmailutils/base/mailcap.c: Remove. * libmailutils/mailcap/Makefile.am: New file. * libmailutils/mailcap/ctmatch.c: New file. * libmailutils/mailcap/deferrclos.c: New file. * libmailutils/mailcap/mcp_creat.c: New file. * libmailutils/mailcap/mcp_destr.c: New file. * libmailutils/mailcap/mcp_err.c: New file. * libmailutils/mailcap/mcp_flags.c: New file. * libmailutils/mailcap/mcp_get.c: New file. * libmailutils/mailcap/mcp_sel.c: New file. * libmailutils/mailcap/mcp_count.c: New file. * libmailutils/mailcap/mcp_find.c: New file. * libmailutils/mailcap/ent_cmd.c: New file. * libmailutils/mailcap/ent_creat.c: New file. * libmailutils/mailcap/ent_destr.c: New file. * libmailutils/mailcap/ent_locus.c: New file. * libmailutils/mailcap/ent_type.c: New file. * libmailutils/mailcap/fieldacc.c: New file. * libmailutils/mailcap/fields.c: New file. * libmailutils/mailcap/finder.c: New file. * libmailutils/mailcap/parse.c: New file. * libmailutils/mailcap/parsefile.c: New file. * libmailutils/tests/mailcap.c: Rewrite using new API. Improve cli * libmailutils/tests/mcf.c: New file. * libmailutils/tests/ctm.c: New file. * libmailutils/tests/ctm.at: New file. * libmu_cpp/mailcap.cc: Rewrite using new API. * python/2/libmu_py/mailcap.c: Rewrite using new API. * python/3/libmu_py/mailcap.c: Rewrite using new API. * examples/python/2/mailcap.py: Minor change. This example is broken with the new API. Should be fixed. * include/mailutils/cpp/mailcap.h: Update * include/mailutils/cpp/pop3.h: Update
Diffstat (more/less context) (ignore whitespace changes)
-rw-r--r--configure.ac1
-rw-r--r--examples/python/2/mailcap.py3
-rw-r--r--include/mailutils/cpp/mailcap.h12
-rw-r--r--include/mailutils/cpp/pop3.h2
-rw-r--r--include/mailutils/mailcap.h202
-rw-r--r--include/mailutils/sys/Makefile.am1
-rw-r--r--include/mailutils/sys/mailcap.h58
-rw-r--r--include/mailutils/util.h1
-rw-r--r--lib/mailcap.c426
-rw-r--r--libmailutils/Makefile.am32
-rw-r--r--libmailutils/base/Makefile.am1
-rw-r--r--libmailutils/base/mailcap.c738
-rw-r--r--libmailutils/mailcap/Makefile.am42
-rw-r--r--libmailutils/mailcap/ctmatch.c166
-rw-r--r--libmailutils/mailcap/deferrclos.c32
-rw-r--r--libmailutils/mailcap/ent_cmd.c66
-rw-r--r--libmailutils/mailcap/ent_creat.c51
-rw-r--r--libmailutils/mailcap/ent_destr.c47
-rw-r--r--libmailutils/mailcap/ent_locus.c33
-rw-r--r--libmailutils/mailcap/ent_type.c66
-rw-r--r--libmailutils/mailcap/fieldacc.c108
-rw-r--r--libmailutils/mailcap/fields.c163
-rw-r--r--libmailutils/mailcap/finder.c131
-rw-r--r--libmailutils/mailcap/mcp_count.c51
-rw-r--r--libmailutils/mailcap/mcp_creat.c56
-rw-r--r--libmailutils/mailcap/mcp_destr.c36
-rw-r--r--libmailutils/mailcap/mcp_err.c44
-rw-r--r--libmailutils/mailcap/mcp_find.c32
-rw-r--r--libmailutils/mailcap/mcp_flags.c39
-rw-r--r--libmailutils/mailcap/mcp_get.c31
-rw-r--r--libmailutils/mailcap/mcp_sel.c44
-rw-r--r--libmailutils/mailcap/parse.c239
-rw-r--r--libmailutils/mailcap/parsefile.c41
-rw-r--r--libmailutils/tests/.gitignore2
-rw-r--r--libmailutils/tests/Makefile.am3
-rw-r--r--libmailutils/tests/ctm.at95
-rw-r--r--libmailutils/tests/ctm.c106
-rw-r--r--libmailutils/tests/mailcap.at262
-rw-r--r--libmailutils/tests/mailcap.c221
-rw-r--r--libmailutils/tests/mcf.c148
-rw-r--r--libmailutils/tests/testsuite.at23
-rw-r--r--libmu_cpp/mailcap.cc38
-rw-r--r--python/2/libmu_py/mailcap.c61
-rw-r--r--python/3/libmu_py/mailcap.c63
44 files changed, 2789 insertions, 1228 deletions
diff --git a/configure.ac b/configure.ac
index 4efd441..be5ee11 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1550,6 +1550,7 @@ AC_CONFIG_FILES([
libmailutils/list/Makefile
libmailutils/locus/Makefile
libmailutils/mailbox/Makefile
+ libmailutils/mailcap/Makefile
libmailutils/mailer/Makefile
libmailutils/mime/Makefile
libmailutils/msgset/Makefile
diff --git a/examples/python/2/mailcap.py b/examples/python/2/mailcap.py
index 24e86e8..d88bf90 100644
--- a/examples/python/2/mailcap.py
+++ b/examples/python/2/mailcap.py
@@ -15,8 +15,9 @@
# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
from mailutils import stream, mailcap
+from os import environ
-stm = stream.FileStream ("/etc/mailcap")
+stm = stream.FileStream (environ['MAILCAP'] if 'MAILCAP' in environ else "/etc/mailcap")
mc = mailcap.Mailcap (stm)
for i, entry in enumerate (mc):
diff --git a/include/mailutils/cpp/mailcap.h b/include/mailutils/cpp/mailcap.h
index 2b25923..d584779 100644
--- a/include/mailutils/cpp/mailcap.h
+++ b/include/mailutils/cpp/mailcap.h
@@ -40,10 +40,10 @@ class MailcapEntry
size_t fields_count ();
std::string get_typefield ();
std::string get_viewcommand ();
- std::string get_field (size_t i);
+ std::string get_field (const std::string& name);
- inline std::string operator [] (size_t i) {
- return this->get_field (i);
+ inline std::string operator [] (const std::string& name) {
+ return this->get_field (name);
}
};
@@ -58,10 +58,10 @@ class Mailcap
~Mailcap ();
size_t entries_count ();
- MailcapEntry& get_entry (size_t i);
+ MailcapEntry& find_entry (const std::string& name);
- inline MailcapEntry& operator [] (size_t i) {
- return this->get_entry (i);
+ inline MailcapEntry& operator [] (const std::string& name) {
+ return this->find_entry (name);
}
};
diff --git a/include/mailutils/cpp/pop3.h b/include/mailutils/cpp/pop3.h
index abf8d35..192ec6f 100644
--- a/include/mailutils/cpp/pop3.h
+++ b/include/mailutils/cpp/pop3.h
@@ -56,7 +56,7 @@ class Pop3
void quit ();
Stream& retr (unsigned int msgno);
void rset ();
- void stat (unsigned int* count, mu_off_t* octets);
+ void stat (size_t* count, mu_off_t* octets);
Stream& top (unsigned int msgno, unsigned int lines);
std::string uidl (unsigned int msgno);
Iterator& uidl_all ();
diff --git a/include/mailutils/mailcap.h b/include/mailutils/mailcap.h
index 85abf57..8cb7372 100644
--- a/include/mailutils/mailcap.h
+++ b/include/mailutils/mailcap.h
@@ -20,101 +20,133 @@
#include <mailutils/types.h>
#include <mailutils/errno.h>
+#include <mailutils/locus.h>
+#include <mailutils/util.h>
/* See RFC1524 (A User Agent Configuration Mechanism). */
#ifdef __cplusplus
extern "C" {
#endif
+#if 0
+}
+#endif
-/* Create a mailcap from stream. */
-int mu_mailcap_create (mu_mailcap_t * mailcap, mu_stream_t stream);
-
-/* Destroy mailcap object. */
-void mu_mailcap_destroy (mu_mailcap_t * mailcap);
-
-/* Return the number of entries in the mailcap file. */
-int mu_mailcap_entries_count (mu_mailcap_t mailcap, size_t *pno);
-
-/* Return the mailcap record number, no, of the mailcap file . */
-int mu_mailcap_get_entry (mu_mailcap_t mailcap, size_t no,
+struct mu_mailcap_selector_closure
+{
+ int (*selector) (mu_mailcap_entry_t, void *);
+ void *data;
+ void (*data_free) (void *);
+};
+
+struct mu_mailcap_error_closure
+{
+ void (*error) (void *, struct mu_locus_range const *, char const *);
+ void *data;
+ void (*data_free) (void *);
+};
+
+extern struct mu_mailcap_error_closure mu_mailcap_default_error_closure;
+
+#define MU_MAILCAP_FLAG_DEFAULT 0
+#define MU_MAILCAP_FLAG_LOCUS 0x1
+
+int mu_mailcap_create (mu_mailcap_t *pmailcap);
+void mu_mailcap_destroy (mu_mailcap_t *pmailcap);
+
+int mu_mailcap_set_flags (mu_mailcap_t mailcap, int flags);
+int mu_mailcap_get_flags (mu_mailcap_t mailcap, int *flags);
+
+int mu_mailcap_set_error (mu_mailcap_t mailcap,
+ struct mu_mailcap_error_closure const *err);
+int mu_mailcap_get_error (mu_mailcap_t mailcap,
+ struct mu_mailcap_error_closure *err);
+int mu_mailcap_set_selector (mu_mailcap_t mailcap,
+ struct mu_mailcap_selector_closure const *sel);
+int mu_mailcap_get_selector (mu_mailcap_t mailcap,
+ struct mu_mailcap_selector_closure *sel);
+
+int mu_mailcap_get_count (mu_mailcap_t mailcap, size_t *pcount);
+int mu_mailcap_get_iterator (mu_mailcap_t mailcap, mu_iterator_t *pitr);
+int mu_mailcap_foreach (mu_mailcap_t mailcap,
+ int (*action) (mu_mailcap_entry_t, void *),
+ void *data);
+int mu_mailcap_get_entry (mu_mailcap_t mailcap, size_t n,
mu_mailcap_entry_t *entry);
-
-/* Return the number of fields in a mailcap entry */
-int mu_mailcap_entry_fields_count (mu_mailcap_entry_t entry,
- size_t *pcount);
-
-/* Save in buffer[] the content-type of the record. */
-int mu_mailcap_entry_get_typefield (mu_mailcap_entry_t entry,
- char *buffer, size_t buflen,
- size_t *pn);
-
-/* Save in buffer[] the view command of the record. */
-int mu_mailcap_entry_get_viewcommand (mu_mailcap_entry_t entry,
- char *buffer, size_t buflen,
- size_t *pn);
-
-/* Save in buffer[] the field number no the record . */
-int mu_mailcap_entry_get_field (mu_mailcap_entry_t entry, size_t no,
- char *buffer, size_t buflen, size_t *pn);
-
-/* Save in buffer the value of a key:
- * mu_mailcap_entry_get_value (entry, "compose", buffer, buflen, pn);
- * i.e compose="lynx %s" --> "lynx %s" will be saved in the buffer without
- * the quotes. */
-int mu_mailcap_entry_get_value (mu_mailcap_entry_t entry, const char *key,
- char *buffer, size_t buflen, size_t *pn);
-
-/* Helper function saving in buffer, the argument of "compose" field. */
-int mu_mailcap_entry_get_compose (mu_mailcap_entry_t entry, char *buffer,
- size_t buflen, size_t *pn);
-
-/* Helper function saving in buffer, the argument of "composetyped" field. */
-int mu_mailcap_entry_get_composetyped (mu_mailcap_entry_t entry,
- char *buffer, size_t buflen,
- size_t *pn);
-
-/* Helper function saving in buffer, the argument of "edit" field. */
-int mu_mailcap_entry_get_edit (mu_mailcap_entry_t entry, char *buffer,
- size_t buflen, size_t *pn);
-
-/* Helper function saving in buffer, the argument of "textualnewlines" field. */
-int mu_mailcap_entry_get_textualnewlines (mu_mailcap_entry_t entry,
- char *buffer, size_t buflen,
- size_t *pn);
-
-/* Helper function saving in buffer, the argument of "test" field. */
-int mu_mailcap_entry_get_test (mu_mailcap_entry_t entry,
- char *buffer, size_t buflen, size_t *pn);
-
-/* Helper function saving in buffer, the argument of "x11-bitmap" field. */
-int mu_mailcap_entry_get_x11bitmap (mu_mailcap_entry_t entry,
- char *buffer, size_t buflen, size_t *pn);
-
-/* Helper function saving in buffer, the argument of "description" field. */
-int mu_mailcap_entry_get_description (mu_mailcap_entry_t entry,
- char *buffer, size_t buflen,
- size_t *pn);
-
-/* Helper function saving in buffer, the argument of "nametemplate" field. */
-int mu_mailcap_entry_get_nametemplate (mu_mailcap_entry_t entry,
- char *buffer, size_t buflen,
- size_t *pn);
-
-/* Helper function saving in buffer, the argument of "notes" field. */
-int mu_mailcap_entry_get_notes (mu_mailcap_entry_t entry, char *buffer,
- size_t buflen, size_t *pn);
-
-/* Helper function. Returns *on != 0 if the flag "needsterminal" is in the
- record. */
-int mu_mailcap_entry_needsterminal (mu_mailcap_entry_t entry, int *on);
-
-/* Helper function. Returns *on != 0 if the flag "copiousoutput" is in the
- record. */
-int mu_mailcap_entry_copiousoutput (mu_mailcap_entry_t entry, int *on);
+int mu_mailcap_find_entry (mu_mailcap_t mailcap, char const *type,
+ mu_mailcap_entry_t *entry);
+
+int mu_mailcap_parse (mu_mailcap_t mailcap, mu_stream_t input,
+ struct mu_locus_point const *pt);
+int mu_mailcap_parse_file (mu_mailcap_t mailcap, char const *file_name);
+
+int mu_mailcap_entry_create (mu_mailcap_entry_t *ret_entry,
+ char *type, char *command);
+void mu_mailcap_entry_destroy (mu_mailcap_entry_t *pent);
+void mu_mailcap_entry_destroy_item (void *ptr);
+
+int mu_mailcap_entry_sget_type (mu_mailcap_entry_t ent, char const **ptype);
+int mu_mailcap_entry_aget_type (mu_mailcap_entry_t ent, char **ptype);
+int mu_mailcap_entry_get_type (mu_mailcap_entry_t ent,
+ char *buffer, size_t buflen,
+ size_t *pn);
+
+int mu_mailcap_entry_sget_command (mu_mailcap_entry_t ent, char const **pcommand);
+int mu_mailcap_entry_aget_command (mu_mailcap_entry_t ent, char **pcommand);
+int mu_mailcap_entry_get_command (mu_mailcap_entry_t ent,
+ char *buffer, size_t buflen,
+ size_t *pn);
+
+int mu_mailcap_entry_get_locus (mu_mailcap_entry_t ent,
+ struct mu_locus_range *loc);
+
+void mu_mailcap_entry_field_deallocate (void *ptr);
+int mu_mailcap_entry_set_bool (mu_mailcap_entry_t ent, char const *name);
+int mu_mailcap_entry_set_string (mu_mailcap_entry_t ent, char const *name,
+ char const *value);
+int mu_mailcap_entry_field_unset (mu_mailcap_entry_t ent, char const *name);
+int mu_mailcap_entry_fields_count (mu_mailcap_entry_t ent, size_t *pcount);
+int mu_mailcap_entry_fields_foreach (mu_mailcap_entry_t ent,
+ int (*action) (char const *, char const *, void *),
+ void *data);
+int mu_mailcap_entry_fields_get_iterator (mu_mailcap_entry_t ent,
+ mu_iterator_t *pitr);
+
+int mu_mailcap_entry_sget_field (mu_mailcap_entry_t ent, char const *name,
+ char const **pval);
+int mu_mailcap_entry_aget_field (mu_mailcap_entry_t ent, char const *name,
+ char **pval);
+int mu_mailcap_entry_get_field (mu_mailcap_entry_t ent,
+ char const *name,
+ char *buffer, size_t buflen,
+ size_t *pn);
+
+#define MU_MAILCAP_NEEDSTERMINAL "needsterminal"
+#define MU_MAILCAP_COPIOUSOUTPUT "copiousoutput"
+#define MU_MAILCAP_COMPOSE "compose"
+#define MU_MAILCAP_COMPOSETYPED "composetyped"
+#define MU_MAILCAP_PRINT "print"
+#define MU_MAILCAP_EDIT "edit"
+#define MU_MAILCAP_TEST "test"
+#define MU_MAILCAP_X11_BITMAP "x11-bitmap"
+#define MU_MAILCAP_TEXTUALNEWLINES "textualnewlines"
+#define MU_MAILCAP_DESCRIPTION "description"
+
+int mu_mailcap_string_match (char const *pattern, int delim, char const *type);
+int mu_mailcap_content_type_match (const char *pattern, int delim,
+ mu_content_type_t ct);
+
+typedef struct _mu_mailcap_finder *mu_mailcap_finder_t;
+
+int mu_mailcap_finder_create (mu_mailcap_finder_t *, int,
+ struct mu_mailcap_selector_closure *,
+ struct mu_mailcap_error_closure *,
+ char **file_names);
+int mu_mailcap_finder_next_match (mu_mailcap_finder_t, mu_mailcap_entry_t *);
+void mu_mailcap_finder_destroy (mu_mailcap_finder_t *);
#ifdef __cplusplus
}
#endif
-
+
#endif
diff --git a/include/mailutils/sys/Makefile.am b/include/mailutils/sys/Makefile.am
index 11cf643..08d8756 100644
--- a/include/mailutils/sys/Makefile.am
+++ b/include/mailutils/sys/Makefile.am
@@ -36,6 +36,7 @@ sysinclude_HEADERS = \
list.h\
logstream.h\
mailbox.h\
+ mailcap.h\
mailer.h\
mapfile_stream.h\
memory_stream.h\
diff --git a/include/mailutils/sys/mailcap.h b/include/mailutils/sys/mailcap.h
new file mode 100644
index 0000000..bc8140f
--- a/dev/null
+++ b/include/mailutils/sys/mailcap.h
@@ -0,0 +1,58 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#ifndef _MAILUTILS_SYS_MAILCAP_H
+# define _MAILUTILS_SYS_MAILCAP_H
+# include <mailutils/mailcap.h>
+# include <mailutils/locus.h>
+
+struct _mu_mailcap_entry
+{
+ char *type;
+ char *command;
+ mu_assoc_t fields;
+ struct mu_locus_range *lrp;
+};
+
+enum fld_type
+ {
+ fld_bool,
+ fld_string
+ };
+
+struct mailcap_field
+{
+ enum fld_type type;
+ char *strval;
+};
+
+struct _mu_mailcap
+{
+ int flags;
+ mu_list_t elist;
+ struct mu_mailcap_selector_closure selector;
+ struct mu_mailcap_error_closure error;
+ struct mu_locus_range locus;
+};
+
+struct _mu_mailcap_finder
+{
+ struct _mu_mailcap *mcp;
+ mu_iterator_t itr;
+};
+
+#endif
diff --git a/include/mailutils/util.h b/include/mailutils/util.h
index ec902d2..26c9bb3 100644
--- a/include/mailutils/util.h
+++ b/include/mailutils/util.h
@@ -23,6 +23,7 @@
#include <mailutils/list.h>
#include <mailutils/types.h>
#include <mailutils/cidr.h>
+#include <mailutils/filter.h>
#ifdef __cplusplus
extern "C" {
diff --git a/lib/mailcap.c b/lib/mailcap.c
index dd84e08..ba819ae 100644
--- a/lib/mailcap.c
+++ b/lib/mailcap.c
@@ -18,15 +18,7 @@
# include <config.h>
#endif
#include <mailutils/mailutils.h>
-#include <fnmatch.h>
#include <sys/wait.h>
-#include <ctype.h>
-
-/* FNM_CASEFOLD is a GNU extension. Provide a replacement for systems
- lacking it. */
-#ifndef FNM_CASEFOLD
-# define FNM_CASEFOLD 0
-#endif
/* Default mailcap path, the $HOME/.mailcap: entry is prepended to it */
#define DEFAULT_MAILCAP \
@@ -41,15 +33,14 @@
struct mime_context
{
- mu_stream_t input;
+ mu_stream_t input;
mu_header_t hdr;
- char *content_type_buffer;
- char *content_type;
- mu_list_t values;
+ mu_content_type_t content_type;
+
char *temp_file;
int unlink_temp_file;
- mu_list_t no_ask_types;
+ char *no_ask_types;
int dh;
int flags;
};
@@ -59,29 +50,22 @@ mime_context_fill (struct mime_context *ctx, const char *file,
mu_stream_t input, mu_header_t hdr, const char *no_ask,
int interactive, int dry_run, mu_debug_handle_t dh)
{
- struct mu_wordsplit ws;
- size_t i;
-
+ int rc;
+ char *buffer;
+
memset (ctx, 0, sizeof *ctx);
ctx->input = input;
ctx->hdr = hdr;
- if (mu_header_aget_value (hdr, MU_HEADER_CONTENT_TYPE,
- &ctx->content_type_buffer))
+
+ rc = mu_header_aget_value_unfold (hdr, MU_HEADER_CONTENT_TYPE, &buffer);
+ if (rc)
+ return 1;
+ rc = mu_content_type_parse (buffer, NULL, &ctx->content_type);
+ free (buffer);
+ if (rc)
return 1;
- ws.ws_delim = ";";
- if (mu_wordsplit (ctx->content_type_buffer, &ws,
- MU_WRDSF_DELIM|MU_WRDSF_SQUEEZE_DELIMS|MU_WRDSF_WS|
- MU_WRDSF_NOVAR|MU_WRDSF_NOCMD))
- {
- mu_error (_("cannot split line `%s': %s"),
- ctx->content_type_buffer,
- mu_wordsplit_strerror (&ws));
- return 1;
- }
- ctx->content_type = ws.ws_wordv[0];
- ws.ws_wordv[0] = NULL;
- ctx->temp_file = file ? mu_strdup (file) : NULL;
+ ctx->temp_file = file ? mu_strdup (file) : NULL;
ctx->unlink_temp_file = 0;
if (interactive)
@@ -89,56 +73,20 @@ mime_context_fill (struct mime_context *ctx, const char *file,
if (dry_run)
ctx->flags |= FLAGS_DRY_RUN;
ctx->dh = dh;
-
- mu_list_create (&ctx->values);
- for (i = 1; i < ws.ws_wordc; i++)
- {
- mu_list_append (ctx->values, ws.ws_wordv[i]);
- ws.ws_wordv[i] = NULL;
- }
- mu_wordsplit_free (&ws);
-
- if (no_ask)
- {
- mu_list_create (&ctx->no_ask_types);
- mu_list_set_destroy_item (ctx->no_ask_types, mu_list_free_item);
- if (mu_string_split (no_ask, ",", ctx->no_ask_types))
- return 1;
- }
+ ctx->no_ask_types = no_ask ? mu_strdup (no_ask) : NULL;
+
return 0;
}
static void
mime_context_release (struct mime_context *ctx)
{
- free (ctx->content_type_buffer);
+ mu_content_type_destroy (&ctx->content_type);
if (ctx->unlink_temp_file)
unlink (ctx->temp_file);
free (ctx->temp_file);
- mu_list_destroy (&ctx->values);
- mu_list_destroy (&ctx->no_ask_types);
-}
-
-static int
-mime_context_do_not_ask (struct mime_context *ctx)
-{
- int rc = 0;
-
- if (ctx->no_ask_types)
- {
- mu_iterator_t itr;
- mu_list_get_iterator (ctx->no_ask_types, &itr);
- for (mu_iterator_first (itr); !rc && !mu_iterator_is_done (itr);
- mu_iterator_next (itr))
- {
- char *p;
- mu_iterator_current (itr, (void**)&p);
- rc = fnmatch (p, ctx->content_type, FNM_CASEFOLD) == 0;
- }
- mu_iterator_destroy (&itr);
- }
- return rc;
+ free (ctx->no_ask_types);
}
static int
@@ -154,50 +102,11 @@ interactive_p (struct mime_context *ctx)
}
static void
-mime_context_get_content_type (struct mime_context *ctx, char **ptr)
-{
- *ptr = ctx->content_type;
-}
-
-static void
mime_context_get_input (struct mime_context *ctx, mu_stream_t *pinput)
{
*pinput = ctx->input;
}
-static int
-mime_context_get_content_type_value (struct mime_context *ctx,
- char *name, size_t len,
- char **ptr, size_t *plen)
-{
- mu_iterator_t itr = NULL;
- int rc = 1;
-
- mu_list_get_iterator (ctx->values, &itr);
- for (mu_iterator_first (itr);
- !mu_iterator_is_done (itr); mu_iterator_next (itr))
- {
- char *item, *p;
-
- mu_iterator_current (itr, (void**) &item);
- p = strchr (item, '=');
- if (p - item == len && strncasecmp (item, name, len) == 0)
- {
- rc = 0;
- *ptr = ++p;
- *plen = strlen (*ptr);
- if (**ptr == '"')
- {
- ++*ptr;
- *plen -= 2;
- }
- break;
- }
- }
- mu_iterator_destroy (&itr);
- return rc;
-}
-
/* FIXME: Rewrite via mu_stream_copy */
static void
mime_context_write_input (struct mime_context *ctx, int fd)
@@ -206,7 +115,7 @@ mime_context_write_input (struct mime_context *ctx, int fd)
char buf[512];
size_t n;
int status;
-
+
mime_context_get_input (ctx, &input);
status = mu_stream_seek (input, 0, SEEK_SET, NULL);
if (status && status != ENOSYS)
@@ -239,12 +148,13 @@ mime_context_get_temp_file (struct mime_context *ctx, char **ptr)
static mu_opool_t expand_pool;
static int
-expand_string (struct mime_context *ct, char **pstr)
+expand_string (struct mime_context *ct, char const *input, char **pstr)
{
- char *p, *s;
+ char const *p;
+ char *s;
int rc = 0;
-
- for (p = *pstr; *p; )
+
+ for (p = input; *p; )
{
switch (p[0])
{
@@ -257,26 +167,34 @@ expand_string (struct mime_context *ct, char **pstr)
rc = 1;
p += 2;
break;
-
+
case 't':
- mime_context_get_content_type (ct, &s);
- mu_opool_appendz (expand_pool, s);
+ mu_opool_appendz (expand_pool, ct->content_type->type);
+ mu_opool_append_char (expand_pool, '/');
+ mu_opool_appendz (expand_pool, ct->content_type->subtype);
p += 2;
break;
-
+
case '{':
{
size_t n;
- char *q;
-
+ char const *q;
+ char *namebuf;
+ struct mu_mime_param *param;
+
p += 2;
q = p;
while (*p && *p != '}')
p++;
- if (mime_context_get_content_type_value (ct,
- q, p-q,
- &s, &n) == 0)
- mu_opool_append (expand_pool, s, n);
+ n = p - q;
+ namebuf = mu_alloc (n + 1);
+ memcpy (namebuf, q, n);
+ namebuf[n] = 0;
+ param = mu_assoc_get (ct->content_type->param, namebuf);
+ if (param)
+ /* FIXME: cset? */
+ mu_opool_appendz (expand_pool, param->value);
+ free (namebuf);
if (*p)
p++;
break;
@@ -286,7 +204,7 @@ expand_string (struct mime_context *ct, char **pstr)
case 'n':
p++;
break;
-
+
default:
mu_opool_append_char (expand_pool, p[0]);
}
@@ -333,12 +251,12 @@ confirm_action (struct mime_context *ctx, const char *str)
{
char repl[128], *p;
int len;
- char *type;
- mime_context_get_content_type (ctx, &type);
- if (!interactive_p (ctx) || mime_context_do_not_ask (ctx))
+ if (!interactive_p (ctx)
+ || mu_mailcap_content_type_match (ctx->no_ask_types, ',',
+ ctx->content_type) == 0)
return 1;
-
+
printf (_("Run `%s'?"), str);
fflush (stdout);
@@ -348,40 +266,44 @@ confirm_action (struct mime_context *ctx, const char *str)
len = strlen (p);
if (len > 0 && p[len-1] == '\n')
p[len--] = 0;
-
+
return mu_true_answer_p (p);
}
+struct list_closure
+{
+ unsigned long n;
+};
+
+static int
+list_field (char const *name, char const *value, void *data)
+{
+ struct list_closure *fc = data;
+ printf ("\tfields[%lu]: ", fc->n++);
+ if (value)
+ printf ("%s=%s", name, value);
+ else
+ printf ("%s", name);
+ printf ("\n");
+ return 0;
+}
+
static void
dump_mailcap_entry (mu_mailcap_entry_t entry)
{
- char buffer[256];
- size_t i, count;
-
- mu_mailcap_entry_get_typefield (entry, buffer,
- sizeof (buffer), NULL);
- printf ("typefield: %s\n", buffer);
-
+ char const *value;
+ struct list_closure lc;
+
+ mu_mailcap_entry_sget_type (entry, &value);
+ printf ("typefield: %s\n", value);
+
/* view-command. */
- mu_mailcap_entry_get_viewcommand (entry, buffer,
- sizeof (buffer), NULL);
- printf ("view-command: %s\n", buffer);
+ mu_mailcap_entry_sget_command (entry, &value);
+ printf ("view-command: %s\n", value);
/* fields. */
- mu_mailcap_entry_fields_count (entry, &count);
- for (i = 1; i <= count; i++)
- {
- int status = mu_mailcap_entry_get_field (entry, i, buffer,
- sizeof (buffer), NULL);
- if (status)
- {
- mu_error (_("cannot retrieve field %lu: %s"),
- (unsigned long) i,
- mu_strerror (status));
- break;
- }
- printf ("fields[%u]: %s\n", (unsigned) i, buffer);
- }
+ lc.n = 1;
+ mu_mailcap_entry_fields_foreach (entry, list_field, &lc);
printf ("\n");
}
@@ -403,7 +325,7 @@ create_filter (char *cmd, int outfd, int *infd)
if (infd)
pipe (lp);
-
+
pid = fork ();
if (pid == -1)
{
@@ -421,7 +343,7 @@ create_filter (char *cmd, int outfd, int *infd)
/* Child process */
struct mu_wordsplit ws;
char **argv;
-
+
if (need_shell_p (cmd))
{
char *x_argv[4];
@@ -440,7 +362,7 @@ create_filter (char *cmd, int outfd, int *infd)
_exit (127);
}
argv = ws.ws_wordv;
- }
+ }
/* Create input channel: */
if (infd)
{
@@ -448,11 +370,11 @@ create_filter (char *cmd, int outfd, int *infd)
dup2 (lp[0], 0);
close (lp[1]);
}
-
+
/* Create output channel */
if (outfd != -1 && outfd != 1)
dup2 (outfd, 1);
-
+
execvp (argv[0], argv);
mu_error (_("cannot execute `%s': %s"), cmd, mu_strerror (errno));
_exit (127);
@@ -470,9 +392,9 @@ create_filter (char *cmd, int outfd, int *infd)
static void
print_exit_status (int status)
{
- if (WIFEXITED (status))
+ if (WIFEXITED (status))
printf (_("Command exited with status %d\n"), WEXITSTATUS(status));
- else if (WIFSIGNALED (status))
+ else if (WIFSIGNALED (status))
printf(_("Command terminated on signal %d\n"), WTERMSIG(status));
else
printf (_("Command terminated\n"));
@@ -498,29 +420,17 @@ get_pager ()
static int
run_test (mu_mailcap_entry_t entry, struct mime_context *ctx)
{
- size_t size;
int status = 0;
-
- if (mu_mailcap_entry_get_test (entry, NULL, 0, &size) == 0)
+ char const *value;
+
+ if (mu_mailcap_entry_sget_field (entry, MU_MAILCAP_TEST, &value) == 0)
{
- struct mu_wordsplit ws;
char *str;
-
- mu_opool_alloc (expand_pool, size + 1);
- str = mu_opool_finish (expand_pool, NULL);
- mu_mailcap_entry_get_test (entry, str, size + 1, NULL);
-
- expand_string (ctx, &str);
- if (mu_wordsplit (str, &ws, MU_WRDSF_DEFFLAGS))
- {
- mu_error (_("%s failed: %s"), "mu_wordsplit",
- mu_wordsplit_strerror (&ws));
- return 1;
- }
-
- if (mu_spawnvp (ws.ws_wordv[0], ws.ws_wordv, &status))
+ char *argv[] = { "/bin/sh", "-c", NULL, NULL };
+ expand_string (ctx, value, &str);
+ argv[2] = str;
+ if (mu_spawnvp (argv[0], argv, &status))
status = 1;
- mu_wordsplit_free (&ws);
}
return status;
}
@@ -528,59 +438,52 @@ run_test (mu_mailcap_entry_t entry, struct mime_context *ctx)
static int
run_mailcap (mu_mailcap_entry_t entry, struct mime_context *ctx)
{
- char *view_command;
- size_t size;
- int flag;
- int status;
- int fd;
- int *pfd = NULL;
- int outfd = -1;
+ char const *view_command;
+ char *command;
+ int status;
+ int fd;
+ int *pfd = NULL;
+ int outfd = -1;
pid_t pid;
-
- if (mu_debug_level_p (ctx->dh, MU_DEBUG_TRACE3))
+ struct mu_locus_range lr = MU_LOCUS_RANGE_INITIALIZER;
+
+ if (mu_mailcap_entry_get_locus (entry, &lr) == 0)
+ {
+ mu_stream_lprintf (mu_strout, &lr, "trying entry\n");
+ mu_locus_range_deinit (&lr);
+ }
+ if (mu_debug_level_p (ctx->dh, MU_DEBUG_TRACE2))
dump_mailcap_entry (entry);
if (run_test (entry, ctx))
return -1;
if (interactive_p (ctx))
- {
- if (mu_mailcap_entry_get_viewcommand (entry, NULL, 0, &size))
- return 1;
- size++;
- mu_opool_alloc (expand_pool, size);
- view_command = mu_opool_finish (expand_pool, NULL);
- mu_mailcap_entry_get_viewcommand (entry, view_command, size, NULL);
- }
+ status = mu_mailcap_entry_sget_command (entry, &view_command);
else
- {
- if (mu_mailcap_entry_get_value (entry, "print", NULL, 0, &size))
- return 1;
- size++;
- mu_opool_alloc (expand_pool, size);
- view_command = mu_opool_finish (expand_pool, NULL);
- mu_mailcap_entry_get_value (entry, "print", view_command, size, NULL);
- }
+ status = mu_mailcap_entry_sget_field (entry, MU_MAILCAP_PRINT, &view_command);
+
+ if (status)
+ return 1;
/* NOTE: We don't create temporary file for %s, we just use
mimeview_file instead */
- if (expand_string (ctx, &view_command))
+ if (expand_string (ctx, view_command, &command))
pfd = NULL;
else
pfd = &fd;
- mu_debug (ctx->dh, MU_DEBUG_TRACE0, (_("executing %s...\n"), view_command));
+ mu_debug (ctx->dh, MU_DEBUG_TRACE0, (_("executing %s...\n"), command));
- if (!confirm_action (ctx, view_command))
+ if (!confirm_action (ctx, command))
return 1;
if (dry_run_p (ctx))
return 0;
-
- flag = 0;
+
if (interactive_p (ctx)
- && mu_mailcap_entry_copiousoutput (entry, &flag) == 0 && flag)
+ && mu_mailcap_entry_sget_field (entry, MU_MAILCAP_COPIOUSOUTPUT, NULL) == 0)
create_filter (get_pager (), -1, &outfd);
-
- pid = create_filter (view_command, outfd, pfd);
+
+ pid = create_filter (command, outfd, pfd);
if (pid > 0)
{
if (pfd)
@@ -588,7 +491,7 @@ run_mailcap (mu_mailcap_entry_t entry, struct mime_context *ctx)
mime_context_write_input (ctx, fd);
close (fd);
}
-
+
while (waitpid (pid, &status, 0) < 0)
if (errno != EINTR)
{
@@ -602,62 +505,14 @@ run_mailcap (mu_mailcap_entry_t entry, struct mime_context *ctx)
}
static int
-find_entry (const char *file, struct mime_context *ctx)
+entry_selector (mu_mailcap_entry_t entry, void *data)
{
- mu_mailcap_t mailcap;
- int status;
- mu_stream_t stream;
- int rc = 1;
-
- mu_debug (ctx->dh, MU_DEBUG_TRACE1, (_("trying %s...\n"), file));
- status = mu_file_stream_create (&stream, file, MU_STREAM_READ);
- if (status)
- {
- if (status != ENOENT)
- mu_error ("cannot open input stream %s: %s",
- file, mu_strerror (status));
- return -1;
- }
+ struct mime_context *ctx = data;
+ char const *pattern;
- status = mu_mailcap_create (&mailcap, stream);
- if (status == 0)
- {
- size_t i, count = 0;
- char *type;
-
- mime_context_get_content_type (ctx, &type);
-
- mu_mailcap_entries_count (mailcap, &count);
- for (i = 1; i <= count; i++)
- {
- mu_mailcap_entry_t entry;
- char buffer[256];
-
- if (mu_mailcap_get_entry (mailcap, i, &entry))
- continue;
-
- /* typefield. */
- mu_mailcap_entry_get_typefield (entry,
- buffer, sizeof (buffer), NULL);
-
- if (fnmatch (buffer, type, FNM_CASEFOLD) == 0)
- {
- mu_debug (ctx->dh, MU_DEBUG_TRACE1, (_("found in %s\n"), file));
- if (run_mailcap (entry, ctx) == 0)
- {
- rc = 0;
- break;
- }
- }
- }
- mu_mailcap_destroy (&mailcap);
- }
- else
- {
- mu_error ("cannot create mailcap for %s: %s",
- file, mu_strerror (status));
- }
- return rc;
+ if (mu_mailcap_entry_sget_type (entry, &pattern))
+ return 1;
+ return mu_mailcap_content_type_match (pattern, 0, ctx->content_type);
}
int
@@ -669,7 +524,7 @@ display_stream_mailcap (const char *ident, mu_stream_t stream, mu_header_t hdr,
struct mu_wordsplit ws;
struct mime_context ctx;
int rc = 1;
-
+
if (mime_context_fill (&ctx, ident, stream, hdr,
no_ask, interactive, dry_run, dh))
return 1;
@@ -681,10 +536,10 @@ display_stream_mailcap (const char *ident, mu_stream_t stream, mu_header_t hdr,
DEFAULT_MAILCAP);
free (home);
if (!mailcap_path_tmp)
- return 1;
+ return 1;
mailcap_path = mailcap_path_tmp;
}
-
+
mu_opool_create (&expand_pool, MU_OPOOL_ENOMEMABRT);
ws.ws_delim = ":";
@@ -697,14 +552,33 @@ display_stream_mailcap (const char *ident, mu_stream_t stream, mu_header_t hdr,
}
else
{
- size_t i;
+ mu_mailcap_finder_t finder;
+ int flags = MU_MAILCAP_FLAG_DEFAULT;
+ struct mu_mailcap_error_closure *errcp = NULL;
+ struct mu_mailcap_selector_closure selcl;
+ mu_mailcap_entry_t entry;
+ int rc;
+
+ if (mu_debug_level_p (ctx.dh, MU_DEBUG_TRACE1)
+ || mu_debug_level_p (ctx.dh, MU_DEBUG_TRACE2))
+ flags |= MU_MAILCAP_FLAG_LOCUS;
+ if (mu_debug_level_p (ctx.dh, MU_DEBUG_ERROR))
+ errcp = &mu_mailcap_default_error_closure;
+
+ memset (&selcl, 0, sizeof (selcl));
+ selcl.selector = entry_selector;
+ selcl.data = &ctx;
+
+ rc = mu_mailcap_finder_create (&finder, flags,
+ &selcl, errcp, ws.ws_wordv);
+ mu_wordsplit_free (&ws);
- for (i = 0; i < ws.ws_wordc; i++)
+ while ((rc = mu_mailcap_finder_next_match (finder, &entry)) == 0)
{
- if ((rc = find_entry (ws.ws_wordv[i], &ctx)) == 0)
+ if (run_mailcap (entry, &ctx) == 0)
break;
}
- mu_wordsplit_free (&ws);
+ mu_mailcap_finder_destroy (&finder);
}
mu_opool_destroy (&expand_pool);
free (mailcap_path_tmp);
diff --git a/libmailutils/Makefile.am b/libmailutils/Makefile.am
index 55b6238..422d2c1 100644
--- a/libmailutils/Makefile.am
+++ b/libmailutils/Makefile.am
@@ -16,9 +16,34 @@
# <http://www.gnu.org/licenses/>.
SUBDIRS = \
- auth base address list sockaddr cidr cfg cli diag\
- filter locus mailbox mailer mime msgset opt server string stream stdstream\
- property url imapio datetime wicket . tests
+ auth\
+ base\
+ address\
+ list\
+ sockaddr\
+ cidr\
+ cfg\
+ cli\
+ diag\
+ filter\
+ locus\
+ mailbox\
+ mailcap\
+ mailer\
+ mime\
+ msgset\
+ opt\
+ server\
+ string\
+ stream\
+ stdstream\
+ property\
+ url\
+ imapio\
+ datetime\
+ wicket\
+ .\
+ tests
lib_LTLIBRARIES = libmailutils.la
@@ -40,6 +65,7 @@ libmailutils_la_LIBADD = \
list/liblist.la\
locus/liblocus.la\
mailbox/libmailbox.la\
+ mailcap/libmailcap.la\
mailer/libmailer.la\
mime/libmime.la\
msgset/libmsgset.la\
diff --git a/libmailutils/base/Makefile.am b/libmailutils/base/Makefile.am
index e4ff1da..e641f1d 100644
--- a/libmailutils/base/Makefile.am
+++ b/libmailutils/base/Makefile.am
@@ -43,7 +43,6 @@ libbase_la_SOURCES = \
lcall.c\
locale.c\
locker.c\
- mailcap.c\
md5.c\
monitor.c\
msgid.c\
diff --git a/libmailutils/base/mailcap.c b/libmailutils/base/mailcap.c
deleted file mode 100644
index 4a4ba01..0000000
--- a/libmailutils/base/mailcap.c
+++ b/dev/null
@@ -1,738 +0,0 @@
-/* GNU Mailutils -- a suite of utilities for electronic mail
- Copyright (C) 1999-2019 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 <stdlib.h>
-#include <string.h>
-#include <errno.h>
-
-#include <mailutils/cctype.h>
-#include <mailutils/mailcap.h>
-#include <mailutils/stream.h>
-#include <mailutils/util.h>
-#include <mailutils/cstr.h>
-
-/* Definition of the structure, this should be in mailutils/sys/mailcap.h. */
-struct _mu_mailcap_entry
-{
- char * typefield;
- char * viewcommand;
- char ** fields;
- size_t fields_count;
-};
-
-/* Definition of the structure, this should be in mailutils/sys/mailcap.h. */
-struct _mu_mailcap
-{
- mu_mailcap_entry_t *entries;
- size_t entries_count;
-};
-
-
-static int mu_mailcap_parse (mu_mailcap_t mailcap, mu_stream_t stream);
-static int mu_mailcap_parse_entry (mu_mailcap_entry_t entry, char *buffer);
-static char * tokenize (char *s, char **save_ptr);
-
-int
-mu_mailcap_create (mu_mailcap_t * pmailcap, mu_stream_t stream)
-{
- mu_mailcap_t mailcap;
- int status = 0;
-
- if (stream == NULL)
- return EINVAL;
- if (pmailcap == NULL)
- return MU_ERR_OUT_PTR_NULL;
-
- mailcap = calloc (1, sizeof (*mailcap));
- if (mailcap != NULL)
- {
- status = mu_mailcap_parse (mailcap, stream);
- if (status != 0)
- {
- mu_mailcap_destroy (&mailcap);
- }
- else
- {
- *pmailcap = mailcap;
- }
- }
- else
- {
- status = ENOMEM;
- }
- return status;
-}
-
-void
-mu_mailcap_destroy (mu_mailcap_t * pmailcap)
-{
- if (pmailcap != NULL && *pmailcap != NULL)
- {
- int i;
- mu_mailcap_t mailcap = *pmailcap;
-
- for (i = 0; i < mailcap->entries_count; i++)
- {
- int j;
- mu_mailcap_entry_t entry = mailcap->entries[i];
- free (entry->typefield);
- free (entry->viewcommand);
- for (j = 0; j < entry->fields_count; j++)
- {
- free (entry->fields[j]);
- }
- }
- }
-}
-
-int
-mu_mailcap_entries_count (mu_mailcap_t mailcap, size_t *pcount)
-{
- int status = 0;
-
- if (mailcap == NULL)
- status = EINVAL;
- if (pcount != NULL)
- {
- *pcount = mailcap->entries_count;
- }
- return status;
-}
-
-int
-mu_mailcap_get_entry (mu_mailcap_t mailcap, size_t no,
- mu_mailcap_entry_t *pentry)
-{
- int status = 0;
- if (mailcap == NULL)
- status = EINVAL;
- else if (pentry == NULL)
- status = MU_ERR_OUT_PTR_NULL;
- else if (no == 0 || no > mailcap->entries_count)
- {
- status = MU_ERR_NOENT;
- }
- else
- {
- *pentry = mailcap->entries[no - 1];
- }
- return status;
-}
-
-int
-mu_mailcap_entry_get_typefield (mu_mailcap_entry_t entry, char *buffer,
- size_t buflen, size_t *pn)
-{
- int status = 0;
- int len = 0;
-
- if (entry == NULL)
- {
- status = EINVAL;
- }
- else
- {
- len = strlen(entry->typefield);
- if (buffer != NULL && buflen > 0)
- {
- buflen--;
- len = (len < buflen) ? len : buflen;
- memcpy (buffer, entry->typefield, len);
- buffer[len] = '\0';
- }
- }
- if (pn)
- {
- *pn = len;
- }
- return status;
-}
-
-int
-mu_mailcap_entry_get_viewcommand (mu_mailcap_entry_t entry, char *buffer,
- size_t buflen, size_t *pn)
-{
- int status = 0;
- int len = 0;
-
- if (entry == NULL)
- {
- status = EINVAL;
- }
- else
- {
- len = strlen(entry->viewcommand);
- if (buffer != NULL && buflen > 0)
- {
- buflen--;
- len = (len < buflen) ? len : buflen;
- memcpy (buffer, entry->viewcommand, len);
- buffer[len] = '\0';
- }
- }
- if (pn)
- {
- *pn = len;
- }
- return status;
-}
-
-int
-mu_mailcap_entry_fields_count (mu_mailcap_entry_t entry, size_t *pcount)
-{
- int status = 0;
- if (entry == NULL)
- {
- status = EINVAL;
- }
- if (pcount != NULL)
- {
- *pcount = entry->fields_count;
- }
- return status;
-}
-
-int
-mu_mailcap_entry_get_field (mu_mailcap_entry_t entry, size_t no,
- char *buffer, size_t buflen, size_t *pn)
-{
- int status = 0;
- int len = 0;
-
- if (entry == NULL)
- {
- status = EINVAL;
- }
- else if ( no == 0 || no > entry->fields_count)
- {
- status = MU_ERR_NOENT;
- }
- else
- {
- len = strlen(entry->fields[no - 1]);
- if (buffer != NULL && buflen > 0)
- {
- buflen--;
- len = (len < buflen) ? len : buflen;
- memcpy (buffer, entry->fields[no - 1], len);
- buffer[len] = '\0';
- }
- }
- if (pn)
- {
- *pn = len;
- }
- return status;
-}
-
-int
-mu_mailcap_entry_get_compose (mu_mailcap_entry_t entry,
- char *buffer, size_t buflen, size_t *pn)
-{
- return mu_mailcap_entry_get_value (entry, "compose", buffer, buflen, pn);
-}
-
-int
-mu_mailcap_entry_get_composetyped (mu_mailcap_entry_t entry, char *buffer,
- size_t buflen, size_t *pn)
-{
- return mu_mailcap_entry_get_value (entry, "composetyped", buffer, buflen, pn);
-}
-
-int
-mu_mailcap_entry_get_edit (mu_mailcap_entry_t entry, char *buffer,
- size_t buflen, size_t *pn)
-{
- return mu_mailcap_entry_get_value (entry, "edit", buffer, buflen, pn);
-}
-
-int
-mu_mailcap_entry_get_test (mu_mailcap_entry_t entry,
- char *buffer, size_t buflen, size_t *pn)
-{
- return mu_mailcap_entry_get_value (entry, "test", buffer, buflen, pn);
-}
-
-int
-mu_mailcap_entry_get_x11bitmap (mu_mailcap_entry_t entry,
- char *buffer, size_t buflen, size_t *pn)
-{
- return mu_mailcap_entry_get_value (entry, "x11-bitmap", buffer, buflen, pn);
-}
-
-int
-mu_mailcap_entry_get_description (mu_mailcap_entry_t entry,
- char *buffer, size_t buflen, size_t *pn)
-{
- return mu_mailcap_entry_get_value (entry, "description", buffer, buflen, pn);
-}
-
-int
-mu_mailcap_entry_needsterminal (mu_mailcap_entry_t entry, int *on)
-{
- int status = 0;
- int found = 0;
- if (entry == NULL)
- {
- status = EINVAL;
- }
- else
- {
- int i;
- for (i = 0; i < entry->fields_count; i++)
- {
- int n = mu_c_strcasecmp (entry->fields[i], "needsterminal");
- if (n == 0)
- {
- found = 1;
- break;
- }
- }
- }
- if (on)
- *on = found;
- return status;
-}
-
-int
-mu_mailcap_entry_copiousoutput (mu_mailcap_entry_t entry, int *on)
-{
- int status = 0;
- int found = 0;
- if (entry == NULL)
- {
- status = EINVAL;
- }
- else
- {
- int i;
- for (i = 0; i < entry->fields_count; i++)
- {
- int n = mu_c_strcasecmp (entry->fields[i], "copiousoutput");
- if (n == 0)
- {
- found = 1;
- break;
- }
- }
- }
- if (on)
- *on = found;
- return status;
-}
-
-int
-mu_mailcap_entry_get_value (mu_mailcap_entry_t entry, const char *key,
- char *buffer, size_t buflen, size_t *pn)
-{
- int len = 0;
- int status = ENOENT;
-
- if (!entry)
- status = EINVAL;
- else
- {
- int i;
- int key_len = strlen (key);
- for (i = 0; i < entry->fields_count; i++)
- {
- int n = mu_c_strncasecmp (entry->fields[i], key, key_len);
- if (n == 0)
- {
- int field_len = strlen(entry->fields[i]);
- status = 0;
- if (field_len > key_len)
- {
- int c = entry->fields[i][key_len];
- if (mu_isspace (c) || c == '=')
- {
- char *value = strchr (entry->fields[i], '=');
- if (value != NULL)
- {
- value++; /* Pass the equal. */
- /* Remove leading space. */
- for (; mu_isspace (*value); value++)
- ;
- len = strlen (value);
- /* Strip surrounding double quotes */
- if (len > 1 && value[0] == '"' && value[len - 1] == '"')
- {
- value++;
- len -= 2;
- }
- if (buffer != NULL && buflen > 0)
- {
- buflen--;
- len = (len < buflen) ? len : buflen;
- memcpy (buffer, value, len);
- buffer[len] = '\0';
- }
- break;
- }
- }
- }
- }
- }
- }
- if (pn)
- *pn = len;
- return status;
-}
-
-/*
- * break the line on ';'. Same as strtok() but
- * check for escaped "\;"
- */
-static char *
-tokenize (char *s, char **save_ptr)
-{
- int c;
- char *token;
-
- if (s == NULL)
- {
- s = *save_ptr;
- }
-
- if (*s == '\0')
- {
- *save_ptr = s;
- return NULL;
- }
-
- for (token = s, c = 0; *s; s++)
- {
- if (*s == ';' && c != '\\')
- {
- break;
- }
- c = *s;
- }
-
- if (*s == '\0')
- {
- *save_ptr = s;
- }
- else
- {
- *s = '\0';
- *save_ptr = s + 1;
- }
- return token;
-}
-
-/**
- * parse the mailcap line, fields are separated by ';'
- */
-static int
-mu_mailcap_parse_entry (mu_mailcap_entry_t entry, char *buffer)
-{
- char *token = NULL;
- char *s = NULL;
- int i;
- for (i = 0, token = tokenize (buffer, &s);
- token != NULL; token = tokenize (NULL, &s), i++)
- {
- switch (i)
- {
- /* The first entry in a mailcap line is the typefield. */
- case 0:
- entry->typefield = strdup (mu_str_stripws (token));
- break;
-
- /* The second entry in a mailcap line is the view-command. */
- case 1:
- entry->viewcommand = strdup (mu_str_stripws (token));
- break;
-
- /* The rest are the optional fields. */
- default:
- {
- char **fields = realloc (entry->fields,
- (entry->fields_count + 1) *
- sizeof (*fields));
- if (fields != NULL)
- {
- entry->fields = fields;
- entry->fields[entry->fields_count] =
- strdup (mu_str_stripws (token));
- entry->fields_count++;
- }
- }
- }
- }
- /* Make sure typefield and viewcommand are not null. */
- if (entry->typefield == NULL)
- {
- entry->typefield = strdup ("");
- }
- if (entry->viewcommand == NULL)
- {
- entry->viewcommand = strdup ("");
- }
- return 0;
-}
-
-/*
- * parse a mailcap file or stream,
- * - ignore empty line.
- * - ignore line starting with '#'
- * - multiline is done with the '\' as continuation
- * example:
-# comment
-application/pgp; gpg < %s | metamail; needsterminal; \
- test=test %{encapsulation}=entity ; copiousoutput
- */
-static int
-mu_mailcap_parse (mu_mailcap_t mailcap, mu_stream_t stream)
-{
- int status;
- size_t n;
- char *previous;
- char *buffer;
- size_t buflen = 512;
-
- buffer = malloc (buflen);
- if (buffer == NULL)
- {
- return ENOMEM;
- }
-
- /*
- * We are doing this a little more complex then expected, because we do not
- * want to seek() back in the stream:
- * - we have to take care of continuation line i.e. line ending with '\'
- * - we have to take to account that the line may be bigger then the buffer
- * and reallocate
- * - check the return of malloc/realloc
- * The old continuation line is saved in the "previous" pointer and
- * prepended to the buffer.
- */
- status = mu_stream_seek (stream, 0, MU_SEEK_SET, NULL);
- if (status)
- return status;
- previous = NULL;
- while ((status = mu_stream_readline (stream, buffer, buflen, &n)) == 0
- && n > 0)
- {
- int len;
-
- /* If there is no trailing newline, that means the buffer was too small,
- * make room for the buffer and continue reading */
- if (buffer[n - 1] != '\n')
- {
- char *b = realloc (buffer, buflen * sizeof (*buffer));
- buflen *= 2;
- if (b == NULL)
- {
- status = ENOMEM;
- break;
- }
- buffer = b;
- /*
- * Fake this as a continuation line, for simplicity.
- */
- strcat (buffer, "\\");
- }
- else
- {
- /* Nuke the trailing newline. */
- buffer[n - 1] = '\0';
- }
-
- /* recalculate the len. */
- len = strlen (buffer);
-
- /* Ending with a '\' means continuation line. */
- if (len && buffer[len - 1] == '\\')
- {
- buffer[len - 1] = '\0';
- /*
- * Check for any previous line:
- * - if yes append the buffer to the previous line.
- * - if not set the buffer as the previous line and continue.
- */
- if (previous == NULL)
- {
- previous = strdup (buffer);
- if (previous == NULL)
- {
- status = ENOMEM;
- break;
- }
- }
- else
- {
- char *b = realloc (previous, strlen (previous) + len + 1);
- if (b == NULL)
- {
- status = ENOMEM;
- break;
- }
- previous = b;
- strcat(previous, buffer);
- }
- }
- else
- {
- /* Did we have a previous incomplete line?
- * if yes make one line from the previous and the buffer.
- */
- if (previous != NULL)
- {
- int prev_len = strlen (previous);
- int total = prev_len + len + 1;
- if (total > buflen)
- {
- char *b = realloc (buffer, total * sizeof (*buffer));
- if (b == NULL)
- {
- status = ENOMEM;
- break;
- }
- buffer = b;
- buflen = total;
- }
- memmove (buffer + prev_len, buffer, len + 1);
- memcpy (buffer, previous, prev_len);
- free (previous);
- previous = NULL;
- }
- }
-
- /* Parse the well-form mailcap line entry. */
- if (previous == NULL) {
- /* Nuke the trailing/prepend spaces. */
- char *line = mu_str_stripws (buffer);
- /* Ignore comments or empty lines */
- if (*line != '#' && *line != '\0')
- {
- mu_mailcap_entry_t *entries;
- entries = realloc (mailcap->entries,
- (mailcap->entries_count + 1) *
- sizeof (*entries));
- if (entries != NULL)
- {
- mailcap->entries = entries;
- mailcap->entries[mailcap->entries_count] = calloc (1,
- sizeof(**entries));
- if (mailcap->entries[mailcap->entries_count] != NULL)
- {
- mu_mailcap_parse_entry (mailcap->entries[mailcap->entries_count], line);
- }
- mailcap->entries_count++;
- }
- else
- {
- status = ENOMEM;
- break;
- }
- }
- }
- }
-
- if (buffer != NULL)
- {
- free (buffer);
- }
- if (previous != NULL)
- {
- free (previous);
- }
- return status;
-}
-
-#ifdef STANDALONE_TEST
-int main()
-{
- mu_stream_t stream = NULL;
- int status = 0;
-
- status = mu_file_stream_create (&stream, "/home/alain/mailcap",
- MU_STREAM_READ);
- if (status == 0)
- {
- mu_mailcap_t mailcap;
- status = mu_mailcap_create (&mailcap, stream);
- if (status == 0)
- {
- int i, n;
- size_t count = 0;
- char buffer[256];
-
- mu_mailcap_entries_count (mailcap, &count);
- for (i = 1; i <= count; i++)
- {
- int j;
- mu_mailcap_entry_t entry = NULL;
- int fields_count = 0;
-
- printf ("entry[%d]\n", i);
-#if 1
-
- mu_mailcap_get_entry (mailcap, i, &entry);
- /* Print typefield. */
- mu_mailcap_entry_get_typefield (entry, buffer,
- sizeof (buffer), NULL);
- printf ("\ttypefield: %s\n", buffer);
-
- /* Print view-command. */
- mu_mailcap_entry_get_viewcommand (entry, buffer,
- sizeof (buffer), NULL);
- printf ("\tview-command: %s\n", buffer);
-
- /* Print fields. */
- mu_mailcap_entry_fields_count (entry, &fields_count);
- for (j = 1; j <= fields_count; j++)
- {
- mu_mailcap_entry_get_field (entry, j, buffer,
- sizeof (buffer), NULL);
- printf("\tfields[%d]: %s\n", j, buffer);
- }
- n = 0;
- mu_mailcap_entry_get_compose (entry, buffer,
- sizeof (buffer), &n);
- if (n > 0)
- {
- printf("\tcompose[%s]\n", buffer);
- }
- printf("\n");
- }
-#else
- for (i = 0; i < mailcap->entries_count; i++)
- {
- int j;
- mu_mailcap_entry_t entry = mailcap->entries[i];
- printf("[%s];[%s]", entry->typefield, entry->viewcommand);
- for (j = 0; j < entry->fields_count; j++)
- {
- printf(";[%s]", entry->fields[j]);
- }
- printf("\n");
- }
-#endif
- mu_mailcap_destroy (&mailcap);
- }
- }
- return 0;
-}
-
-#endif
diff --git a/libmailutils/mailcap/Makefile.am b/libmailutils/mailcap/Makefile.am
new file mode 100644
index 0000000..20e8668
--- a/dev/null
+++ b/libmailutils/mailcap/Makefile.am
@@ -0,0 +1,42 @@
+# GNU Mailutils -- a suite of utilities for electronic mail
+# Copyright (C) 2019 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/>.
+
+noinst_LTLIBRARIES = libmailcap.la
+
+libmailcap_la_SOURCES = \
+ ctmatch.c\
+ deferrclos.c\
+ mcp_creat.c\
+ mcp_destr.c\
+ mcp_get.c\
+ mcp_err.c\
+ mcp_find.c\
+ mcp_flags.c\
+ mcp_sel.c\
+ mcp_count.c\
+ ent_cmd.c\
+ ent_creat.c\
+ ent_destr.c\
+ ent_locus.c\
+ ent_type.c\
+ fields.c\
+ fieldacc.c\
+ finder.c\
+ parse.c\
+ parsefile.c
+
+AM_CPPFLAGS = @MU_LIB_COMMON_INCLUDES@ -I/libmailutils
diff --git a/libmailutils/mailcap/ctmatch.c b/libmailutils/mailcap/ctmatch.c
new file mode 100644
index 0000000..180ff59
--- a/dev/null
+++ b/libmailutils/mailcap/ctmatch.c
@@ -0,0 +1,166 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <mailutils/cctype.h>
+#include <mailutils/util.h>
+
+enum
+ {
+ MATCH = 0,
+ NO_MATCH = 1
+ };
+
+/* Return MATCH (0) if content-type string TYPESTR matches one of
+ patterns from PATLIST, a list of patterns delimited with DELIM.
+ Whitespace is allowed at either side of patterns in PATLIST.
+ Empty patterns are ignored.
+
+ A "pattern" is a type/subtype specification. Matching is case-insensitive.
+ If the subtype is '*', it matches any subtype from TYPESTR.
+*/
+int
+mu_mailcap_string_match (char const *patlist, int delim, char const *typestr)
+{
+ char const *type;
+
+ if (!patlist)
+ return NO_MATCH;
+
+ while (*patlist)
+ {
+ type = typestr;
+
+ /* Skip whitespace and delimiters */
+ while (*patlist && (*patlist == delim || mu_isspace (*patlist)))
+ patlist++;
+
+ /* Match type */
+ do
+ {
+ if (!*patlist || !*type
+ || mu_tolower (*patlist++) != mu_tolower (*type++))
+ goto retry;
+ if (*patlist == delim)
+ goto retry;
+ }
+ while (*patlist != '/');
+
+ if (*type != '/')
+ goto retry;
+ patlist++;
+ type++;
+
+ if (*patlist == '*')
+ return MATCH;
+
+ /* Match subtype */
+ while (*patlist && *patlist != delim && *type
+ && mu_tolower (*patlist) == mu_tolower (*type))
+ {
+ patlist++;
+ type++;
+ }
+
+ /* Skip optional whitespace */
+ while (*patlist && mu_isspace (*patlist))
+ patlist++;
+
+ if (*patlist == 0 || *patlist == delim)
+ {
+ if (*type == 0)
+ return MATCH;
+ }
+ retry:
+ /* Skip to the next pattern */
+ do
+ {
+ if (*patlist == 0)
+ return NO_MATCH;
+ patlist++;
+ }
+ while (*patlist != delim);
+ }
+ return NO_MATCH;
+}
+
+/* Return 0 if parsed content-type CT matches PATTERN. */
+int
+mu_mailcap_content_type_match (char const *patlist, int delim,
+ mu_content_type_t ct)
+{
+ char const *type;
+
+ if (!patlist)
+ return NO_MATCH;
+
+ while (*patlist)
+ {
+ type = ct->type;
+
+ /* Skip whitespace and delimiters */
+ while (*patlist && (*patlist == delim || mu_isspace (*patlist)))
+ patlist++;
+
+ /* Match type */
+ do
+ {
+ if (!*patlist || !*type
+ || mu_tolower (*patlist++) != mu_tolower (*type++))
+ goto retry;
+ if (*patlist == delim)
+ goto retry;
+ }
+ while (*patlist != '/');
+
+ if (*type != 0)
+ goto retry;
+ patlist++;
+
+ if (*patlist == '*')
+ return MATCH;
+
+ /* Match subtype */
+ type = ct->subtype;
+ while (*patlist && *patlist != delim && *type
+ && mu_tolower (*patlist) == mu_tolower (*type))
+ {
+ patlist++;
+ type++;
+ }
+
+ /* Skip optional whitespace */
+ while (*patlist && mu_isspace (*patlist))
+ patlist++;
+
+ if (*patlist == 0 || *patlist == delim)
+ {
+ if (*type == 0)
+ return MATCH;
+ }
+ retry:
+ /* Skip to next pattern */
+ do
+ {
+ if (*patlist == 0)
+ return NO_MATCH;
+ patlist++;
+ }
+ while (*patlist != delim);
+ }
+ return NO_MATCH;
+}
diff --git a/libmailutils/mailcap/deferrclos.c b/libmailutils/mailcap/deferrclos.c
new file mode 100644
index 0000000..db260c6
--- a/dev/null
+++ b/libmailutils/mailcap/deferrclos.c
@@ -0,0 +1,32 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <mailutils/mailcap.h>
+#include <mailutils/diag.h>
+
+static void
+mailcap_error (void *closure, struct mu_locus_range const *loc, char const *msg)
+{
+ mu_diag_at_locus_range (MU_DIAG_ERR, loc, "%s", msg);
+}
+
+struct mu_mailcap_error_closure mu_mailcap_default_error_closure = {
+ mailcap_error,
+ NULL,
+ NULL
+};
diff --git a/libmailutils/mailcap/ent_cmd.c b/libmailutils/mailcap/ent_cmd.c
new file mode 100644
index 0000000..ad74173
--- a/dev/null
+++ b/libmailutils/mailcap/ent_cmd.c
@@ -0,0 +1,66 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <stdlib.h>
+#include <mailutils/sys/mailcap.h>
+
+int
+mu_mailcap_entry_sget_command (mu_mailcap_entry_t ent, char const **pcommand)
+{
+ if (!ent)
+ return EINVAL;
+ if (!pcommand)
+ return MU_ERR_OUT_PTR_NULL;
+ *pcommand = ent->command;
+ return 0;
+}
+
+int
+mu_mailcap_entry_aget_command (mu_mailcap_entry_t ent, char **pcommand)
+{
+ if (!ent)
+ return EINVAL;
+ if (!pcommand)
+ return MU_ERR_OUT_PTR_NULL;
+ if (!(*pcommand = strdup (ent->command)))
+ return ENOMEM;
+ return 0;
+}
+
+int
+mu_mailcap_entry_get_command (mu_mailcap_entry_t ent,
+ char *buffer, size_t buflen,
+ size_t *pn)
+{
+ size_t len;
+
+ if (!ent)
+ return EINVAL;
+ len = strlen (ent->command);
+
+ if (buffer)
+ {
+ if (len > buflen)
+ len = buflen;
+ memcpy (buffer, ent->command, len);
+ buffer[len] = 0;
+ }
+ if (pn)
+ *pn = len;
+ return 0;
+}
diff --git a/libmailutils/mailcap/ent_creat.c b/libmailutils/mailcap/ent_creat.c
new file mode 100644
index 0000000..30a1395
--- a/dev/null
+++ b/libmailutils/mailcap/ent_creat.c
@@ -0,0 +1,51 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <stdlib.h>
+#include <mailutils/assoc.h>
+#include <mailutils/sys/mailcap.h>
+
+int
+mu_mailcap_entry_create (mu_mailcap_entry_t *ret_ent,
+ char *type, char *command)
+{
+ int rc;
+ mu_mailcap_entry_t ent = calloc (1, sizeof (*ent));
+
+ if (!ent)
+ return ENOMEM;
+ if (!ret_ent)
+ return MU_ERR_OUT_PTR_NULL;
+
+ ent->type = strdup (type);
+ ent->command = strdup (command);
+ if (!ent->type || !ent->command)
+ {
+ mu_mailcap_entry_destroy (&ent);
+ return ENOMEM;
+ }
+ rc = mu_assoc_create (&ent->fields, MU_ASSOC_ICASE);
+ if (rc)
+ mu_mailcap_entry_destroy (&ent);
+ else
+ {
+ mu_assoc_set_destroy_item (ent->fields, mu_mailcap_entry_field_deallocate);
+ *ret_ent = ent;
+ }
+ return rc;
+}
diff --git a/libmailutils/mailcap/ent_destr.c b/libmailutils/mailcap/ent_destr.c
new file mode 100644
index 0000000..1fa0769
--- a/dev/null
+++ b/libmailutils/mailcap/ent_destr.c
@@ -0,0 +1,47 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <stdlib.h>
+#include <mailutils/assoc.h>
+#include <mailutils/sys/mailcap.h>
+
+void
+mu_mailcap_entry_destroy (mu_mailcap_entry_t *pent)
+{
+ if (pent && *pent)
+ {
+ mu_mailcap_entry_t ent = *pent;
+ free (ent->type);
+ free (ent->command);
+ mu_assoc_destroy (&ent->fields);
+ if (ent->lrp)
+ {
+ mu_locus_range_deinit (ent->lrp);
+ free (ent->lrp);
+ }
+ free (ent);
+ *pent = NULL;
+ }
+}
+
+void
+mu_mailcap_entry_destroy_item (void *ptr)
+{
+ mu_mailcap_entry_t ent = ptr;
+ mu_mailcap_entry_destroy (&ent);
+}
diff --git a/libmailutils/mailcap/ent_locus.c b/libmailutils/mailcap/ent_locus.c
new file mode 100644
index 0000000..9d460d9
--- a/dev/null
+++ b/libmailutils/mailcap/ent_locus.c
@@ -0,0 +1,33 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <stdlib.h>
+#include <mailutils/sys/mailcap.h>
+#include <mailutils/errno.h>
+
+int
+mu_mailcap_entry_get_locus (mu_mailcap_entry_t ent, struct mu_locus_range *lrp)
+{
+ if (!ent)
+ return EINVAL;
+ if (!lrp)
+ return MU_ERR_OUT_PTR_NULL;
+ if (!ent->lrp)
+ return MU_ERR_NOENT;
+ return mu_locus_range_copy (lrp, ent->lrp);
+}
diff --git a/libmailutils/mailcap/ent_type.c b/libmailutils/mailcap/ent_type.c
new file mode 100644
index 0000000..5854639
--- a/dev/null
+++ b/libmailutils/mailcap/ent_type.c
@@ -0,0 +1,66 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <stdlib.h>
+#include <mailutils/sys/mailcap.h>
+
+int
+mu_mailcap_entry_sget_type (mu_mailcap_entry_t ent, char const **ptype)
+{
+ if (!ent)
+ return EINVAL;
+ if (!ptype)
+ return MU_ERR_OUT_PTR_NULL;
+ *ptype = ent->type;
+ return 0;
+}
+
+int
+mu_mailcap_entry_aget_type (mu_mailcap_entry_t ent, char **ptype)
+{
+ if (!ent)
+ return EINVAL;
+ if (!ptype)
+ return MU_ERR_OUT_PTR_NULL;
+ if (!(*ptype = strdup (ent->type)))
+ return ENOMEM;
+ return 0;
+}
+
+int
+mu_mailcap_entry_get_type (mu_mailcap_entry_t ent,
+ char *buffer, size_t buflen,
+ size_t *pn)
+{
+ size_t len;
+
+ if (!ent)
+ return EINVAL;
+ len = strlen (ent->type);
+
+ if (buffer)
+ {
+ if (len > buflen)
+ len = buflen;
+ memcpy (buffer, ent->type, len);
+ buffer[len] = 0;
+ }
+ if (pn)
+ *pn = len;
+ return 0;
+}
diff --git a/libmailutils/mailcap/fieldacc.c b/libmailutils/mailcap/fieldacc.c
new file mode 100644
index 0000000..259aad3
--- a/dev/null
+++ b/libmailutils/mailcap/fieldacc.c
@@ -0,0 +1,108 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <stdlib.h>
+#include <mailutils/assoc.h>
+#include <mailutils/sys/mailcap.h>
+
+int
+mu_mailcap_entry_sget_field (mu_mailcap_entry_t ent, char const *name,
+ char const **pval)
+{
+ struct mailcap_field *fp;
+
+ if (!ent || !name)
+ return EINVAL;
+ if (!pval)
+ return MU_ERR_OUT_PTR_NULL;
+ fp = mu_assoc_get (ent->fields, name);
+ if (!fp)
+ return MU_ERR_NOENT;
+ if (pval)
+ {
+ if (fp->type == fld_string)
+ *pval = fp->strval;
+ else
+ *pval = NULL;
+ }
+ return 0;
+}
+
+int
+mu_mailcap_entry_aget_field (mu_mailcap_entry_t ent, char const *name,
+ char **pval)
+{
+ int rc;
+ char const *val;
+
+ rc = mu_mailcap_entry_sget_field (ent, name, &val);
+ if (rc == 0)
+ {
+ if (val)
+ {
+ char *copy = strdup (val);
+ if (!copy)
+ return ENOMEM;
+ *pval = copy;
+ }
+ else
+ *pval = NULL;
+ }
+ return rc;
+}
+
+int
+mu_mailcap_entry_get_field (mu_mailcap_entry_t ent,
+ char const *name,
+ char *buffer, size_t buflen,
+ size_t *pn)
+{
+ int rc;
+ char const *val;
+ size_t len;
+
+ if (!ent)
+ return EINVAL;
+
+ rc = mu_mailcap_entry_sget_field (ent, name, &val);
+ if (rc)
+ return rc;
+
+ if (val)
+ {
+ len = strlen (val);
+
+ if (buffer)
+ {
+ if (len > buflen)
+ len = buflen;
+ memcpy (buffer, val, len);
+ buffer[len] = 0;
+ }
+ }
+ else
+ {
+ len = 0;
+ if (buffer)
+ buffer[0] = 0;
+ }
+
+ if (pn)
+ *pn = len;
+ return 0;
+}
diff --git a/libmailutils/mailcap/fields.c b/libmailutils/mailcap/fields.c
new file mode 100644
index 0000000..d73efcc
--- a/dev/null
+++ b/libmailutils/mailcap/fields.c
@@ -0,0 +1,163 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <stdlib.h>
+#include <mailutils/assoc.h>
+#include <mailutils/sys/mailcap.h>
+
+void
+mu_mailcap_entry_field_deallocate (void *ptr)
+{
+ struct mailcap_field *flg = ptr;
+ if (flg->type == fld_string)
+ free (flg->strval);
+ free (flg);
+}
+
+int
+mu_mailcap_entry_set_bool (mu_mailcap_entry_t ent, char const *name)
+{
+ struct mailcap_field *fp, **fpp;
+ int rc;
+
+ if (!ent || !name)
+ return EINVAL;
+
+ rc = mu_assoc_install_ref (ent->fields, name, (void *)&fpp);
+ switch (rc)
+ {
+ case 0:
+ fp = malloc (sizeof (*fp));
+ if (!fp)
+ return ENOMEM;
+ fp->type = fld_bool;
+ *fpp = fp;
+ break;
+
+ case MU_ERR_EXISTS:
+ fp = *fpp;
+ if (fp->type == fld_string)
+ {
+ free (fp->strval);
+ fp->strval = NULL;
+ fp->type = fld_bool;
+ }
+ break;
+ }
+
+ return rc;
+}
+
+int
+mu_mailcap_entry_set_string (mu_mailcap_entry_t ent, char const *name,
+ char const *value)
+{
+ struct mailcap_field *fp, **fpp;
+ int rc;
+ char *copy;
+
+ if (!ent || !name || !value)
+ return EINVAL;
+
+ rc = mu_assoc_install_ref (ent->fields, name, (void *)&fpp);
+ switch (rc)
+ {
+ case 0:
+ fp = malloc (sizeof (*fp));
+ if (!fp)
+ return ENOMEM;
+ fp->strval = strdup (value);
+ if (!fp->strval)
+ {
+ free (fp);
+ return ENOMEM;
+ }
+ fp->type = fld_string;
+ *fpp = fp;
+ break;
+
+ case MU_ERR_EXISTS:
+ copy = strdup (value);
+ if (!copy)
+ return ENOMEM;
+
+ fp = *fpp;
+ if (fp->type == fld_string)
+ free (fp->strval);
+ else
+ fp->type = fld_string;
+ fp->strval = copy;
+ break;
+ }
+
+ return rc;
+}
+
+int
+mu_mailcap_entry_field_unset (mu_mailcap_entry_t ent, char const *name)
+{
+ if (!ent || !name)
+ return EINVAL;
+ return mu_assoc_remove (ent->fields, name);
+}
+
+int
+mu_mailcap_entry_fields_count (mu_mailcap_entry_t ent, size_t *pcount)
+{
+ if (!ent)
+ return EINVAL;
+ return mu_assoc_count (ent->fields, pcount);
+}
+
+struct fields_iter_closure
+{
+ int (*action) (char const *, char const *, void *);
+ void *data;
+};
+
+static int
+fields_iter_action (char const *name, void *item, void *data)
+{
+ struct mailcap_field *flg = item;
+ struct fields_iter_closure *clos = data;
+ return clos->action (name, flg->type == fld_string ? flg->strval : NULL,
+ clos->data);
+}
+
+int
+mu_mailcap_entry_fields_foreach (mu_mailcap_entry_t ent,
+ int (*action) (char const *, char const *, void *),
+ void *data)
+{
+ struct fields_iter_closure clos;
+ if (!ent || !action)
+ return EINVAL;
+ clos.action = action;
+ clos.data = data;
+ return mu_assoc_foreach (ent->fields, fields_iter_action, &clos);
+}
+
+int
+mu_mailcap_entry_fields_get_iterator (mu_mailcap_entry_t ent, mu_iterator_t *pitr)
+{
+ if (!ent)
+ return EINVAL;
+ if (!pitr)
+ return MU_ERR_OUT_PTR_NULL;
+ return mu_assoc_get_iterator (ent->fields, pitr);
+}
diff --git a/libmailutils/mailcap/finder.c b/libmailutils/mailcap/finder.c
new file mode 100644
index 0000000..714412e
--- a/dev/null
+++ b/libmailutils/mailcap/finder.c
@@ -0,0 +1,131 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <mailutils/sys/mailcap.h>
+#include <mailutils/iterator.h>
+
+static int
+finder_init (mu_mailcap_finder_t finder,
+ int flags,
+ struct mu_mailcap_selector_closure *sc,
+ struct mu_mailcap_error_closure *ec,
+ char **file_names);
+
+int
+mu_mailcap_finder_create (mu_mailcap_finder_t *pfinder, int flags,
+ struct mu_mailcap_selector_closure *sc,
+ struct mu_mailcap_error_closure *ec,
+ char **file_names)
+{
+ int rc;
+ mu_mailcap_finder_t finder;
+
+ if (!pfinder)
+ return MU_ERR_OUT_PTR_NULL;
+ if (!file_names)
+ return EINVAL;
+ finder = calloc (1, sizeof *finder);
+ if (!finder)
+ return ENOMEM;
+ rc = finder_init (finder, flags, sc, ec, file_names);
+ if (rc)
+ mu_mailcap_finder_destroy (&finder);
+ else
+ *pfinder = finder;
+ return rc;
+}
+
+static int
+finder_init (mu_mailcap_finder_t finder,
+ int flags,
+ struct mu_mailcap_selector_closure *sc,
+ struct mu_mailcap_error_closure *ec,
+ char **file_names)
+{
+ int rc;
+ size_t i;
+
+ rc = mu_mailcap_create (&finder->mcp);
+ if (rc)
+ return rc;
+ mu_mailcap_set_flags (finder->mcp, flags);
+ if (sc)
+ {
+ rc = mu_mailcap_set_selector (finder->mcp, sc);
+ if (rc)
+ return rc;
+ }
+ if (ec)
+ {
+ rc = mu_mailcap_set_error (finder->mcp, ec);
+ if (rc)
+ return rc;
+ }
+
+ for (i = 0; file_names[i]; i++)
+ {
+ if (access (file_names[i], F_OK))
+ continue;
+ mu_mailcap_parse_file (finder->mcp, file_names[i]);
+ }
+
+ return 0;
+}
+
+void
+mu_mailcap_finder_destroy (mu_mailcap_finder_t *pfinder)
+{
+ if (pfinder && *pfinder)
+ {
+ mu_mailcap_finder_t finder = *pfinder;
+ mu_iterator_destroy (&finder->itr);
+ mu_mailcap_destroy (&finder->mcp);
+ free (finder);
+ *pfinder = NULL;
+ }
+}
+
+int
+mu_mailcap_finder_next_match (mu_mailcap_finder_t finder,
+ mu_mailcap_entry_t *ret_entry)
+{
+ int rc;
+
+ if (!finder)
+ return EINVAL;
+ if (!ret_entry)
+ return MU_ERR_OUT_PTR_NULL;
+ if (!finder->itr)
+ {
+ rc = mu_mailcap_get_iterator (finder->mcp, &finder->itr);
+ if (rc == 0)
+ rc = mu_iterator_first (finder->itr);
+ }
+ else
+ rc = mu_iterator_next (finder->itr);
+
+ if (rc)
+ return rc;
+
+ if (mu_iterator_is_done (finder->itr))
+ return MU_ERR_NOENT;
+
+ return mu_iterator_current (finder->itr, (void**) ret_entry);
+}
diff --git a/libmailutils/mailcap/mcp_count.c b/libmailutils/mailcap/mcp_count.c
new file mode 100644
index 0000000..d1540bc
--- a/dev/null
+++ b/libmailutils/mailcap/mcp_count.c
@@ -0,0 +1,51 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <mailutils/list.h>
+#include <mailutils/iterator.h>
+#include <mailutils/sys/mailcap.h>
+
+int
+mu_mailcap_get_count (mu_mailcap_t mailcap, size_t *pcount)
+{
+ if (!mailcap)
+ return EINVAL;
+ if (!pcount)
+ return MU_ERR_OUT_PTR_NULL;
+ return mu_list_count (mailcap->elist, pcount);
+}
+
+int
+mu_mailcap_get_iterator (mu_mailcap_t mailcap, mu_iterator_t *pitr)
+{
+ if (!mailcap)
+ return EINVAL;
+ if (!pitr)
+ return MU_ERR_OUT_PTR_NULL;
+ return mu_list_get_iterator (mailcap->elist, pitr);
+}
+
+int
+mu_mailcap_foreach (mu_mailcap_t mailcap,
+ int (*action) (mu_mailcap_entry_t, void *),
+ void *data)
+{
+ if (!mailcap || !action)
+ return EINVAL;
+ return mu_list_foreach (mailcap->elist, (mu_list_action_t) action, data);
+}
diff --git a/libmailutils/mailcap/mcp_creat.c b/libmailutils/mailcap/mcp_creat.c
new file mode 100644
index 0000000..1481c09
--- a/dev/null
+++ b/libmailutils/mailcap/mcp_creat.c
@@ -0,0 +1,56 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <stdlib.h>
+#include <mailutils/list.h>
+#include <mailutils/sys/mailcap.h>
+#include <mailutils/cctype.h>
+
+static int
+type_comp (const void *item, const void *data)
+{
+ struct _mu_mailcap_entry const *ent = item;
+ return mu_mailcap_string_match (ent->type, 0, data);
+}
+
+int
+mu_mailcap_create (mu_mailcap_t *pmailcap)
+{
+ mu_mailcap_t mailcap;
+ int rc;
+
+ if (pmailcap == NULL)
+ return MU_ERR_OUT_PTR_NULL;
+
+ mailcap = calloc (1, sizeof (*mailcap));
+ if (!mailcap)
+ return ENOMEM;
+
+ mailcap->flags = MU_MAILCAP_FLAG_DEFAULT;
+ rc = mu_list_create (&mailcap->elist);
+ if (rc)
+ {
+ free (mailcap);
+ return rc;
+ }
+ mu_list_set_destroy_item (mailcap->elist, mu_mailcap_entry_destroy_item);
+ mu_list_set_comparator (mailcap->elist, type_comp);
+
+ *pmailcap = mailcap;
+ return 0;
+}
diff --git a/libmailutils/mailcap/mcp_destr.c b/libmailutils/mailcap/mcp_destr.c
new file mode 100644
index 0000000..a3a62a4
--- a/dev/null
+++ b/libmailutils/mailcap/mcp_destr.c
@@ -0,0 +1,36 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <stdlib.h>
+#include <mailutils/list.h>
+#include <mailutils/sys/mailcap.h>
+
+void
+mu_mailcap_destroy (mu_mailcap_t *pmailcap)
+{
+ if (pmailcap && *pmailcap)
+ {
+ mu_mailcap_t mailcap = *pmailcap;
+ mu_list_destroy (&mailcap->elist);
+ if (mailcap->selector.data && mailcap->selector.data_free)
+ mailcap->selector.data_free (mailcap->selector.data);
+ if (mailcap->error.data && mailcap->error.data_free)
+ mailcap->error.data_free (mailcap->error.data);
+ free (mailcap);
+ }
+}
diff --git a/libmailutils/mailcap/mcp_err.c b/libmailutils/mailcap/mcp_err.c
new file mode 100644
index 0000000..4ec091d
--- a/dev/null
+++ b/libmailutils/mailcap/mcp_err.c
@@ -0,0 +1,44 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <mailutils/sys/mailcap.h>
+
+int
+mu_mailcap_set_error (mu_mailcap_t mailcap,
+ struct mu_mailcap_error_closure const *err)
+{
+ if (!mailcap)
+ return EINVAL;
+ if (err)
+ mailcap->error = *err;
+ else
+ memset (&mailcap->error, 0, sizeof (mailcap->error));
+ return 0;
+}
+
+int
+mu_mailcap_get_error (mu_mailcap_t mailcap,
+ struct mu_mailcap_error_closure *err)
+{
+ if (!mailcap)
+ return EINVAL;
+ if (!err)
+ return MU_ERR_OUT_PTR_NULL;
+ *err = mailcap->error;
+ return 0;
+}
diff --git a/libmailutils/mailcap/mcp_find.c b/libmailutils/mailcap/mcp_find.c
new file mode 100644
index 0000000..f02f599
--- a/dev/null
+++ b/libmailutils/mailcap/mcp_find.c
@@ -0,0 +1,32 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <stdlib.h>
+#include <mailutils/list.h>
+#include <mailutils/sys/mailcap.h>
+
+int
+mu_mailcap_find_entry (mu_mailcap_t mailcap, char const *type,
+ mu_mailcap_entry_t *entry)
+{
+ if (!mailcap || !type)
+ return EINVAL;
+ if (!entry)
+ return MU_ERR_OUT_PTR_NULL;
+ return mu_list_locate (mailcap->elist, (void *) type, (void **) entry);
+}
diff --git a/libmailutils/mailcap/mcp_flags.c b/libmailutils/mailcap/mcp_flags.c
new file mode 100644
index 0000000..93c2e06
--- a/dev/null
+++ b/libmailutils/mailcap/mcp_flags.c
@@ -0,0 +1,39 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <mailutils/sys/mailcap.h>
+
+int
+mu_mailcap_set_flags (mu_mailcap_t mailcap, int flags)
+{
+ if (!mailcap)
+ return EINVAL;
+ mailcap->flags = flags;
+ return 0;
+}
+
+int
+mu_mailcap_get_flags (mu_mailcap_t mailcap, int *flags)
+{
+ if (!mailcap)
+ return EINVAL;
+ if (!flags)
+ return MU_ERR_OUT_PTR_NULL;
+ *flags = mailcap->flags;
+ return 0;
+}
diff --git a/libmailutils/mailcap/mcp_get.c b/libmailutils/mailcap/mcp_get.c
new file mode 100644
index 0000000..7dc7ad5
--- a/dev/null
+++ b/libmailutils/mailcap/mcp_get.c
@@ -0,0 +1,31 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <stdlib.h>
+#include <mailutils/list.h>
+#include <mailutils/sys/mailcap.h>
+
+int
+mu_mailcap_get_entry (mu_mailcap_t mailcap, size_t n, mu_mailcap_entry_t *entry)
+{
+ if (!mailcap)
+ return EINVAL;
+ if (!entry)
+ return MU_ERR_OUT_PTR_NULL;
+ return mu_list_get (mailcap->elist, n, (void **)entry);
+}
diff --git a/libmailutils/mailcap/mcp_sel.c b/libmailutils/mailcap/mcp_sel.c
new file mode 100644
index 0000000..c511071
--- a/dev/null
+++ b/libmailutils/mailcap/mcp_sel.c
@@ -0,0 +1,44 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <mailutils/sys/mailcap.h>
+
+int
+mu_mailcap_set_selector (mu_mailcap_t mailcap,
+ struct mu_mailcap_selector_closure const *sel)
+{
+ if (!mailcap)
+ return EINVAL;
+ if (sel)
+ mailcap->selector = *sel;
+ else
+ memset (&mailcap->selector, 0, sizeof (mailcap->selector));
+ return 0;
+}
+
+int
+mu_mailcap_get_selector (mu_mailcap_t mailcap,
+ struct mu_mailcap_selector_closure *sel)
+{
+ if (!mailcap)
+ return EINVAL;
+ if (!sel)
+ return MU_ERR_OUT_PTR_NULL;
+ *sel = mailcap->selector;
+ return 0;
+}
diff --git a/libmailutils/mailcap/parse.c b/libmailutils/mailcap/parse.c
new file mode 100644
index 0000000..3d64060
--- a/dev/null
+++ b/libmailutils/mailcap/parse.c
@@ -0,0 +1,239 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <stdlib.h>
+#include <mailutils/sys/mailcap.h>
+#include <mailutils/wordsplit.h>
+#include <mailutils/locus.h>
+#include <mailutils/nls.h>
+#include <mailutils/filter.h>
+#include <mailutils/list.h>
+#include <mailutils/stream.h>
+#include <mailutils/opool.h>
+#include <mailutils/cctype.h>
+
+static int
+create_entry (mu_mailcap_t mp, char *input, mu_mailcap_entry_t *pent)
+{
+ mu_mailcap_entry_t ent;
+ struct mu_wordsplit ws;
+ int rc;
+ size_t i;
+
+ ws.ws_delim = ";";
+ ws.ws_escape[0] = ";\\";
+ ws.ws_escape[1] = "";
+ if (mu_wordsplit (input, &ws,
+ MU_WRDSF_DELIM
+ | MU_WRDSF_NOCMD
+ | MU_WRDSF_NOVAR
+ | MU_WRDSF_WS
+ | MU_WRDSF_ESCAPE))
+ {
+ if (mp->error.error)
+ mp->error.error (mp->error.data, &mp->locus,
+ mu_wordsplit_strerror (&ws));
+ return MU_ERR_FAILURE;
+ }
+ if (ws.ws_wordc < 2)
+ {
+ if (mp->error.error)
+ mp->error.error (mp->error.data, &mp->locus, _("not enough fields"));
+ mu_wordsplit_free (&ws);
+ return MU_ERR_PARSE;
+ }
+ rc = mu_mailcap_entry_create (&ent, ws.ws_wordv[0], ws.ws_wordv[1]);
+ if (rc == 0)
+ {
+ for (i = 2; i < ws.ws_wordc; i++)
+ {
+ char *p = strchr (ws.ws_wordv[i], '=');
+ if (p)
+ {
+ *p++ = 0;
+ rc = mu_mailcap_entry_set_string (ent, ws.ws_wordv[i], p);
+ }
+ else
+ rc = mu_mailcap_entry_set_bool (ent, ws.ws_wordv[i]);
+ if (rc)
+ break;
+ }
+ }
+
+ mu_wordsplit_free (&ws);
+
+ if (rc == 0)
+ {
+ if (mp->flags & MU_MAILCAP_FLAG_LOCUS)
+ {
+ ent->lrp = calloc (1, sizeof ent->lrp[0]);
+ if (ent->lrp)
+ {
+ mu_locus_range_init (ent->lrp);
+ rc = mu_locus_range_copy (ent->lrp, &mp->locus);
+ }
+ else
+ rc = errno;
+ }
+ }
+
+ if (rc)
+ {
+ if (mp->error.error)
+ mp->error.error (mp->error.data, &mp->locus, mu_strerror (rc));
+ mu_mailcap_entry_destroy (&ent);
+ }
+ else
+ *pent = ent;
+
+ return rc;
+}
+
+int
+mu_mailcap_parse (mu_mailcap_t mailcap, mu_stream_t input,
+ struct mu_locus_point const *pt)
+{
+ int rc;
+ char *buffer = NULL;
+ size_t bufsize = 0;
+ size_t nread;
+ mu_opool_t acc = NULL;
+ mu_stream_t flt;
+ const char *argv[] = { "inline-comment", "#", "-i", "#", NULL };
+ int err = 0;
+
+ rc = mu_filter_create_args (&flt, input,
+ argv[0],
+ MU_ARRAY_SIZE (argv) - 1, argv,
+ MU_FILTER_DECODE, MU_STREAM_READ);
+ if (rc)
+ return rc;
+
+ mu_locus_range_init (&mailcap->locus);
+ if (pt)
+ {
+ mu_locus_point_copy (&mailcap->locus.beg, pt);
+ mu_locus_point_copy (&mailcap->locus.end, pt);
+ }
+
+ while ((rc = mu_stream_getline (flt, &buffer, &bufsize, &nread)) == 0)
+ {
+ mu_mailcap_entry_t entry;
+ int cont = acc && mu_opool_size (acc) > 0;
+
+ if (nread > 0)
+ {
+ buffer[--nread] = 0;
+
+ if (buffer[0] == '#')
+ {
+ unsigned long n;
+ char *p;
+
+ errno = 0;
+ n = strtoul (buffer + 2, &p, 10);
+ if (errno == 0 && (*p == 0 || mu_isspace (*p)))
+ mailcap->locus.beg.mu_line = mailcap->locus.end.mu_line = n;
+ continue;
+ }
+ else if (nread && buffer[nread-1] == '\\')
+ {
+ if (--nread > 0)
+ {
+ if (!acc)
+ {
+ rc = mu_opool_create (&acc, MU_OPOOL_DEFAULT);
+ if (rc)
+ break;
+ }
+ rc = mu_opool_append (acc, buffer, nread);
+ if (rc)
+ break;
+ }
+
+ mailcap->locus.end.mu_line++;
+ continue;
+ }
+ else if (cont)
+ {
+ char *p;
+
+ rc = mu_opool_append (acc, buffer, nread);
+ if (rc)
+ break;
+ rc = mu_opool_append_char (acc, 0);
+ if (rc)
+ break;
+ p = mu_opool_finish (acc, NULL);
+ rc = create_entry (mailcap, p, &entry);
+ mu_opool_clear (acc);
+
+ mailcap->locus.beg.mu_line = ++mailcap->locus.end.mu_line;
+ }
+ else if (nread == 0)
+ {
+ mailcap->locus.beg.mu_line = ++mailcap->locus.end.mu_line;
+ continue;
+ }
+ else
+ {
+ rc = create_entry (mailcap, buffer, &entry);
+ mailcap->locus.beg.mu_line = ++mailcap->locus.end.mu_line;
+ }
+ }
+ else if (cont)
+ {
+ /* Missing trailing newline */
+ char *p;
+
+ rc = mu_opool_append_char (acc, 0);
+ if (rc)
+ break;
+ p = mu_opool_finish (acc, NULL);
+ rc = create_entry (mailcap, p, &entry);
+ mu_opool_clear (acc);
+ }
+ else
+ break;
+
+ if (rc == 0)
+ {
+ if (mailcap->selector.selector
+ && mailcap->selector.selector (entry, mailcap->selector.data) != 0)
+ {
+ mu_mailcap_entry_destroy (&entry);
+ }
+ else
+ {
+ mu_list_append (mailcap->elist, entry);
+ }
+ }
+ else if (rc == MU_ERR_PARSE)
+ err = 1;
+ else
+ break;
+ }
+ mu_stream_destroy (&flt);
+ mu_locus_range_deinit (&mailcap->locus);
+ mu_opool_destroy (&acc);
+
+ if (rc && err)
+ rc = MU_ERR_PARSE;
+
+ return rc;
+}
diff --git a/libmailutils/mailcap/parsefile.c b/libmailutils/mailcap/parsefile.c
new file mode 100644
index 0000000..ff04075
--- a/dev/null
+++ b/libmailutils/mailcap/parsefile.c
@@ -0,0 +1,41 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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/>. */
+
+#include <config.h>
+#include <stdlib.h>
+#include <mailutils/sys/mailcap.h>
+#include <mailutils/stream.h>
+#include <mailutils/locus.h>
+
+int
+mu_mailcap_parse_file (mu_mailcap_t mailcap, char const *file_name)
+{
+ int rc;
+ mu_stream_t str;
+ struct mu_locus_point point;
+
+ rc = mu_file_stream_create (&str, file_name, MU_STREAM_READ);
+ if (rc)
+ return rc;
+ mu_locus_point_init (&point);
+ mu_locus_point_set_file (&point, file_name);
+ point.mu_line = 1;
+ rc = mu_mailcap_parse (mailcap, str, &point);
+ mu_locus_point_deinit (&point);
+ mu_stream_destroy (&str);
+ return rc;
+}
diff --git a/libmailutils/tests/.gitignore b/libmailutils/tests/.gitignore
index 74cee5f..b93c70a 100644
--- a/libmailutils/tests/.gitignore
+++ b/libmailutils/tests/.gitignore
@@ -2,6 +2,7 @@ atconfig
atlocal
cidr
conttype
+ctm
package.m4
testsuite
testsuite.dir
@@ -23,6 +24,7 @@ listop
linetrack
logstr
mailcap
+mcf
mimehdr
modmesg
modtofsaf
diff --git a/libmailutils/tests/Makefile.am b/libmailutils/tests/Makefile.am
index 59a10da..b264bef 100644
--- a/libmailutils/tests/Makefile.am
+++ b/libmailutils/tests/Makefile.am
@@ -43,6 +43,7 @@ noinst_PROGRAMS = \
addr\
cidr\
conttype\
+ ctm\
debugspec\
decode2047\
dump\
@@ -58,6 +59,7 @@ noinst_PROGRAMS = \
linetrack\
logstr\
mailcap\
+ mcf\
mimehdr\
modtofsaf\
msgset\
@@ -96,6 +98,7 @@ TESTSUITE_AT = \
decode2047.at\
crlf.at\
crlfdot.at\
+ ctm.at\
encode2047.at\
exp.at\
fromflt.at\
diff --git a/libmailutils/tests/ctm.at b/libmailutils/tests/ctm.at
new file mode 100644
index 0000000..6b360ec
--- a/dev/null
+++ b/libmailutils/tests/ctm.at
@@ -0,0 +1,95 @@
+# This file is part of GNU Mailutils. -*- Autotest -*-
+# Copyright (C) 2019 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.
+#
+# GNU Mailutils 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/>.
+
+AT_SETUP([Content-type matcher])
+AT_KEYWORDS([mailcap ctm])
+AT_CHECK(
+[echo "# single string match"
+ctm -n 'text/plain' text/plain text/html tEXt/PLAIN
+
+echo "# single pattern match"
+ctm -n 'text/*' text/plain text/html image/jpeg
+
+echo "# single string match (mu_mailcap_content_type_match)"
+ctm -nc 'text/plain' text/plain text/html
+
+echo "# single pattern match (mu_mailcap_content_type_match)"
+ctm -nc 'text/*' text/plain text/html image/jpeg
+
+echo "# pattern list match"
+ctm 'text/*,application/x-tar, image/jpeg, image/tiff ,,message/rfc822,,multipart/mixed' \
+ text/plain\
+ TEXT/HTML\
+ application/x-tar\
+ IMAGE/Jpeg\
+ image/tiff\
+ message/rfc822\
+ multipart/mixed\
+ multipart/alternative\
+ image/png
+
+echo "# pattern list match (mu_mailcap_content_type_match)"
+ctm -c \
+ 'text/*,application/x-tar, image/jpeg, image/tiff ,,message/rfc822,,multipart/mixed' \
+ text/plain\
+ TEXT/HTML\
+ application/x-tar\
+ IMAGE/Jpeg\
+ image/tiff\
+ message/rfc822\
+ multipart/mixed\
+ multipart/alternative\
+ image/png
+],
+[0],
+[# single string match
+text/plain: 0
+text/html: 1
+tEXt/PLAIN: 0
+# single pattern match
+text/plain: 0
+text/html: 0
+image/jpeg: 1
+# single string match (mu_mailcap_content_type_match)
+text/plain: 0
+text/html: 1
+# single pattern match (mu_mailcap_content_type_match)
+text/plain: 0
+text/html: 0
+image/jpeg: 1
+# pattern list match
+text/plain: 0
+TEXT/HTML: 0
+application/x-tar: 0
+IMAGE/Jpeg: 0
+image/tiff: 0
+message/rfc822: 0
+multipart/mixed: 0
+multipart/alternative: 1
+image/png: 1
+# pattern list match (mu_mailcap_content_type_match)
+text/plain: 0
+TEXT/HTML: 0
+application/x-tar: 0
+IMAGE/Jpeg: 0
+image/tiff: 0
+message/rfc822: 0
+multipart/mixed: 0
+multipart/alternative: 1
+image/png: 1
+])
+
+AT_CLEANUP
diff --git a/libmailutils/tests/ctm.c b/libmailutils/tests/ctm.c
new file mode 100644
index 0000000..acfc522
--- a/dev/null
+++ b/libmailutils/tests/ctm.c
@@ -0,0 +1,106 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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.
+
+ GNU Mailutils 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/>. */
+
+#include "config.h"
+#include "mailutils/mailutils.h"
+
+void
+usage (void)
+{
+ mu_stream_printf (mu_strerr, "ctm [-c] [-n] PATLIST TYPE [TYPE...]\n");
+ mu_stream_printf (mu_strerr, "checks content-type matchers\n");
+ mu_stream_printf (mu_strerr, "Options:\n");
+ mu_stream_printf (mu_strerr, " -c test mu_mailcap_content_type_match\n");
+ mu_stream_printf (mu_strerr, " -n set delim=0\n");
+}
+
+int
+main (int argc, char **argv)
+{
+ int delim = ',';
+ int ctflag = 0;
+ char *arg;
+ char *pattern;
+
+ mu_stdstream_setup (MU_STDSTREAM_RESET_NONE);
+ while (--argc && (arg = *++argv)[0] == '-')
+ {
+ if (strcmp (arg, "--") == 0)
+ {
+ argc--;
+ argv++;
+ break;
+ }
+ else
+ {
+ while (*++arg)
+ {
+ switch (*arg)
+ {
+ case 'c':
+ ctflag = 1;
+ break;
+
+ case 'n':
+ delim = 0;
+ break;
+
+ default:
+ mu_error ("unrecognized option: -%c", *arg);
+ usage ();
+ return 1;
+ }
+ }
+ }
+ }
+
+ if (argc < 2)
+ {
+ usage ();
+ return 1;
+ }
+
+ argc--;
+ pattern = *argv++;
+ while (argc--)
+ {
+ int rc;
+
+ arg = *argv++;
+ if (ctflag)
+ {
+ struct mu_content_type ct;
+ char *p;
+
+ memset (&ct, 0, sizeof (ct));
+ ct.type = arg;
+ p = strchr (arg, '/');
+ if (!p)
+ {
+ mu_error ("%s: malformed argument\n", arg);
+ continue;
+ }
+ *p = 0;
+ ct.subtype = p + 1;
+ rc = mu_mailcap_content_type_match (pattern, delim, &ct);
+ *p = '/';
+ }
+ else
+ rc = mu_mailcap_string_match (pattern, delim, arg);
+ mu_printf ("%s: %d\n", arg, rc);
+ }
+ return 0;
+}
diff --git a/libmailutils/tests/mailcap.at b/libmailutils/tests/mailcap.at
index 954b629e..b333d69 100644
--- a/libmailutils/tests/mailcap.at
+++ b/libmailutils/tests/mailcap.at
@@ -14,17 +14,17 @@
# You should have received a copy of the GNU General Public License
# along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>.
-AT_BANNER(Mailcap)
-
dnl ------------------------------------------------------------
dnl MAILCAP([NAME], [KW = `'], [INPUT], [STDOUT = `'],
dnl [STDERR = `'], [RUN-IF-FAIL], [RUN-IF-PASS])
dnl
+m4_pushdef([MAILCAP_OPTIONS])
+
m4_pushdef([MAILCAP],[
m4_pushdef([MU_TEST_GROUP],[Mailcap])
m4_pushdef([MU_TEST_KEYWORDS],[mailcap])
-m4_pushdef([MU_TEST_COMMAND],[mailcap])
+m4_pushdef([MU_TEST_COMMAND],[mailcap MAILCAP_OPTIONS])
MU_GENERIC_TEST([$1],[$2],[$3],[],[$4],[$5])
m4_popdef([MU_TEST_COMMAND])
m4_popdef([MU_TEST_KEYWORDS])
@@ -280,4 +280,260 @@ nametemplate=%s.au],
]])
+m4_pushdef([MAILCAP_OPTIONS],[-l])
+MAILCAP([Locations],[mailcap_loc],
+[# Sample mailcap file
+# For testing location tracing
+application/pgp;\
+ pgp -m %s;\
+ needsterminal
+
+
+image/jpeg;\
+ xv -8 -geometry +0 '%s';\
+ description=JPEG Image;\
+ test=test "$DISPLAY"
+
+# Comment 1
+
+# Comment 2
+
+image/*;\
+ xv -8 -geometry +0 '%s';\
+ description=%t Image;\
+ test=test "$DISPLAY";\
+ nametemplate=%s.IMAGE
+message/rfc822;\
+ formail > '%s.mbox' < '%s' \&\& mutt -m mbox -f '%s.mbox' \&\& rm -f '%s.mbox';\
+ description=Mail Text;\
+ needsterminal
+text/html;\
+ lynx -force_html '%s';\
+ description=HTML Text;\
+ needsterminal;\
+ nametemplate=%s.html
+# Final entry
+# Provides default for all
+# other text types
+text/*;\
+ ${PAGER:-"more"} '%s';\
+ edit=${EDITOR:-"vi"} '%s';\
+ compose=${EDITOR:-"vi"} '%s';\
+ print=a2ps '%s';\
+ needsterminal
+],
+[[<stdin>:3-5: entry[1]
+ typefield: application/pgp
+ view-command: pgp -m %s
+ fields[1]: needsterminal
+
+<stdin>:8-11: entry[2]
+ typefield: image/jpeg
+ view-command: xv -8 -geometry +0 '%s'
+ fields[1]: description=JPEG Image
+ fields[2]: test=test "$DISPLAY"
+
+<stdin>:17-21: entry[3]
+ typefield: image/*
+ view-command: xv -8 -geometry +0 '%s'
+ fields[1]: description=%t Image
+ fields[2]: test=test "$DISPLAY"
+ fields[3]: nametemplate=%s.IMAGE
+
+<stdin>:22-25: entry[4]
+ typefield: message/rfc822
+ view-command: formail > '%s.mbox' < '%s' \&\& mutt -m mbox -f '%s.mbox' \&\& rm -f '%s.mbox'
+ fields[1]: description=Mail Text
+ fields[2]: needsterminal
+
+<stdin>:26-30: entry[5]
+ typefield: text/html
+ view-command: lynx -force_html '%s'
+ fields[1]: description=HTML Text
+ fields[2]: needsterminal
+ fields[3]: nametemplate=%s.html
+
+<stdin>:34-39: entry[6]
+ typefield: text/*
+ view-command: ${PAGER:-"more"} '%s'
+ fields[1]: edit=${EDITOR:-"vi"} '%s'
+ fields[2]: compose=${EDITOR:-"vi"} '%s'
+ fields[3]: print=a2ps '%s'
+ fields[4]: needsterminal
+
+]])
+
+m4_pushdef([MU_TEST_PASS_FILE],[-f $1])
+MAILCAP([mu_mailcap_parse_file],[mu_mailcap_parse_file],
+[# Sample mailcap file
+# For testing location tracing
+application/pgp;\
+ pgp -m %s;\
+ needsterminal
+
+
+image/jpeg;\
+ xv -8 -geometry +0 '%s';\
+ description=JPEG Image;\
+ test=test "$DISPLAY"
+
+# Comment 1
+
+# Comment 2
+
+image/*;\
+ xv -8 -geometry +0 '%s';\
+ description=%t Image;\
+ test=test "$DISPLAY";\
+ nametemplate=%s.IMAGE
+message/rfc822;\
+ formail > '%s.mbox' < '%s' \&\& mutt -m mbox -f '%s.mbox' \&\& rm -f '%s.mbox';\
+ description=Mail Text;\
+ needsterminal
+text/html;\
+ lynx -force_html '%s';\
+ description=HTML Text;\
+ needsterminal;\
+ nametemplate=%s.html
+# Final entry
+# Provides default for all
+# other text types
+text/*;\
+ ${PAGER:-"more"} '%s';\
+ edit=${EDITOR:-"vi"} '%s';\
+ compose=${EDITOR:-"vi"} '%s';\
+ print=a2ps '%s';\
+ needsterminal
+],
+[[input:3-5: entry[1]
+ typefield: application/pgp
+ view-command: pgp -m %s
+ fields[1]: needsterminal
+
+input:8-11: entry[2]
+ typefield: image/jpeg
+ view-command: xv -8 -geometry +0 '%s'
+ fields[1]: description=JPEG Image
+ fields[2]: test=test "$DISPLAY"
+
+input:17-21: entry[3]
+ typefield: image/*
+ view-command: xv -8 -geometry +0 '%s'
+ fields[1]: description=%t Image
+ fields[2]: test=test "$DISPLAY"
+ fields[3]: nametemplate=%s.IMAGE
+
+input:22-25: entry[4]
+ typefield: message/rfc822
+ view-command: formail > '%s.mbox' < '%s' \&\& mutt -m mbox -f '%s.mbox' \&\& rm -f '%s.mbox'
+ fields[1]: description=Mail Text
+ fields[2]: needsterminal
+
+input:26-30: entry[5]
+ typefield: text/html
+ view-command: lynx -force_html '%s'
+ fields[1]: description=HTML Text
+ fields[2]: needsterminal
+ fields[3]: nametemplate=%s.html
+
+input:34-39: entry[6]
+ typefield: text/*
+ view-command: ${PAGER:-"more"} '%s'
+ fields[1]: edit=${EDITOR:-"vi"} '%s'
+ fields[2]: compose=${EDITOR:-"vi"} '%s'
+ fields[3]: print=a2ps '%s'
+ fields[4]: needsterminal
+
+]])
+m4_popdef([MU_TEST_PASS_FILE])
+
+m4_popdef([MAILCAP_OPTIONS])
+
m4_popdef([MAILCAP])
+m4_popdef([MAILCAP_OPTIONS])
+
+AT_SETUP([mailcap_finder])
+AT_KEYWORDS([mailcap mailcap_finder])
+AT_CHECK([
+AT_DATA([1.mc],
+[application/pgp;\
+ pgp -m %s;\
+ needsterminal
+
+image/jpeg;\
+ xv -8 -geometry +0 '%s';\
+ description=JPEG Image;\
+ test=test "$DISPLAY"
+
+message/rfc822;\
+ formail > '%s.mbox' < '%s' \&\& mutt -m mbox -f '%s.mbox' \&\& rm -f '%s.mbox';\
+ description=Mail Text;\
+ needsterminal
+text/html;\
+ lynx -force_html '%s';\
+ description=HTML Text;\
+ needsterminal;\
+ nametemplate=%s.html
+])
+AT_DATA([2.mc],
+[# Final entries for various
+# content types
+
+image/*;\
+ xv -8 -geometry +0 '%s';\
+ description=%t Image;\
+ test=test "$DISPLAY";\
+ nametemplate=%s.IMAGE
+
+text/*;\
+ ${PAGER:-"more"} '%s';\
+ edit=${EDITOR:-"vi"} '%s';\
+ compose=${EDITOR:-"vi"} '%s';\
+ print=a2ps '%s';\
+ needsterminal
+])
+
+mcf -l text/plain 1.mc 2.mc
+mcf -l text/html 1.mc 2.mc
+mcf -l message/rfc822 1.mc 2.mc
+mcf -l application/octet-stream 1.mc 2.mc
+],
+[0],
+[[text/plain
+2.mc:10-15: entry[1]
+ typefield: text/*
+ view-command: ${PAGER:-"more"} '%s'
+ fields[1]: edit=${EDITOR:-"vi"} '%s'
+ fields[2]: compose=${EDITOR:-"vi"} '%s'
+ fields[3]: print=a2ps '%s'
+ fields[4]: needsterminal
+
+text/html
+1.mc:14-18: entry[1]
+ typefield: text/html
+ view-command: lynx -force_html '%s'
+ fields[1]: description=HTML Text
+ fields[2]: needsterminal
+ fields[3]: nametemplate=%s.html
+
+2.mc:10-15: entry[2]
+ typefield: text/*
+ view-command: ${PAGER:-"more"} '%s'
+ fields[1]: edit=${EDITOR:-"vi"} '%s'
+ fields[2]: compose=${EDITOR:-"vi"} '%s'
+ fields[3]: print=a2ps '%s'
+ fields[4]: needsterminal
+
+message/rfc822
+1.mc:10-13: entry[1]
+ typefield: message/rfc822
+ view-command: formail > '%s.mbox' < '%s' \&\& mutt -m mbox -f '%s.mbox' \&\& rm -f '%s.mbox'
+ fields[1]: description=Mail Text
+ fields[2]: needsterminal
+
+application/octet-stream
+]])
+AT_CLEANUP
+
+
+
diff --git a/libmailutils/tests/mailcap.c b/libmailutils/tests/mailcap.c
index cb21352..b4069ad 100644
--- a/libmailutils/tests/mailcap.c
+++ b/libmailutils/tests/mailcap.c
@@ -19,73 +19,184 @@
#endif
#include <stdlib.h>
#include <stdio.h>
-#include <mailutils/mailcap.h>
-#include <mailutils/stream.h>
-#include <mailutils/error.h>
+#include <mailutils/mailutils.h>
+struct list_closure
+{
+ unsigned long n;
+};
+
+static void list_all (mu_mailcap_t mailcap);
+static void list_single_entry (mu_mailcap_entry_t ent);
+static int list_field (char const *name, char const *value, void *data);
+static int list_entry (mu_mailcap_entry_t ent, void *closure);
+
+/* usage:
+ mailcap [-f FILE]
+ List entries
+ mailcap [-f FILE] TYPE
+ List first entry matching TYPE
+ mailcap [-f FILE] TYPE FIELD
+ List FIELD from the first entry matching TYPE
+ */
int
main (int argc, char **argv)
{
- mu_stream_t stream = NULL;
int status = 0;
- mu_mailcap_t mailcap = NULL;
+ int flags = MU_MAILCAP_FLAG_DEFAULT;
+ mu_mailcap_t mailcap;
+ char *file = NULL;
+ char *arg;
- status = mu_stdio_stream_create (&stream, MU_STDIN_FD,
- MU_STREAM_READ|MU_STREAM_SEEK);
- if (status)
- {
- mu_error ("cannot create input stream: %s",
- mu_strerror (status));
- exit (1);
- }
+ mu_stdstream_setup (MU_STDSTREAM_RESET_NONE);
- status = mu_mailcap_create (&mailcap, stream);
- if (status == 0)
+ while (--argc && (arg = *++argv)[0] == '-')
{
- int i;
- size_t count = 0;
- char buffer[256];
-
- mu_mailcap_entries_count (mailcap, &count);
- for (i = 1; i <= count; i++)
+ if (strcmp (arg, "--") == 0)
{
- size_t j;
- mu_mailcap_entry_t entry = NULL;
- size_t fields_count = 0;
-
- printf ("entry[%d]\n", i);
-
- mu_mailcap_get_entry (mailcap, i, &entry);
-
- /* typefield. */
- mu_mailcap_entry_get_typefield (entry, buffer,
- sizeof (buffer), NULL);
- printf ("\ttypefield: %s\n", buffer);
-
- /* view-command. */
- mu_mailcap_entry_get_viewcommand (entry, buffer,
- sizeof (buffer), NULL);
- printf ("\tview-command: %s\n", buffer);
-
- /* fields. */
- mu_mailcap_entry_fields_count (entry, &fields_count);
- for (j = 1; j <= fields_count; j++)
+ argc--;
+ argv++;
+ break;
+ }
+ else if (strncmp (arg, "-f", 2) == 0)
+ {
+ if (arg[2])
+ file = arg + 2;
+ else if (--argc)
+ file = *++argv;
+ else
{
- int status = mu_mailcap_entry_get_field (entry, j, buffer,
- sizeof (buffer), NULL);
- if (status)
- {
- mu_error ("cannot retrieve field %lu: %s",
- (unsigned long) j,
- mu_strerror (status));
- break;
- }
- printf ("\tfields[%lu]: %s\n", (unsigned long) j, buffer);
+ mu_error ("-f requires arguments");
+ return 1;
}
- printf ("\n");
}
- mu_mailcap_destroy (&mailcap);
+ else if (strcmp (arg, "-l") == 0)
+ flags |= MU_MAILCAP_FLAG_LOCUS;
+ else
+ {
+ mu_error ("unrecognized option: %s", arg);
+ return 1;
+ }
+ }
+
+ MU_ASSERT (mu_mailcap_create (&mailcap));
+ mu_mailcap_set_error (mailcap, &mu_mailcap_default_error_closure);
+ if (flags != MU_MAILCAP_FLAG_DEFAULT)
+ MU_ASSERT (mu_mailcap_set_flags (mailcap, flags));
+
+ if (file)
+ status = mu_mailcap_parse_file (mailcap, file);
+ else
+ {
+ struct mu_locus_point point = MU_LOCUS_POINT_INITIALIZER;
+
+ mu_locus_point_set_file (&point, "<stdin>");
+ point.mu_line = 1;
+ status = mu_mailcap_parse (mailcap, mu_strin, &point);
+ mu_locus_point_deinit (&point);
+ }
+
+ if (status && status != MU_ERR_PARSE)
+ {
+ mu_error ("%s", mu_strerror (status));
+ return 1;
+ }
+
+ switch (argc)
+ {
+ case 0:
+ list_all (mailcap);
+ break;
+
+ case 1:
+ {
+ mu_mailcap_entry_t entry;
+
+ MU_ASSERT (mu_mailcap_find_entry (mailcap, argv[0], &entry));
+ list_single_entry (entry);
+ }
+ break;
+
+ case 2:
+ {
+ mu_mailcap_entry_t entry;
+ char const *value;
+
+ MU_ASSERT (mu_mailcap_find_entry (mailcap, argv[0], &entry));
+ status = mu_mailcap_entry_sget_field (entry, argv[1], &value);
+ if (status == 0)
+ {
+ if (value)
+ mu_printf ("%s=%s\n", argv[1], value);
+ else
+ mu_printf ("%s is set\n", argv[1]);
+ }
+ else if (status == MU_ERR_NOENT)
+ mu_printf ("%s is not set\n", argv[1]);
+ else
+ mu_error ("%s", mu_strerror (status));
+ }
+ break;
+
+ default:
+ mu_error ("too many arguments");
+ return 1;
}
-
+
+ mu_mailcap_destroy (&mailcap);
+ return 0;
+}
+
+static void
+list_all (mu_mailcap_t mailcap)
+{
+ struct list_closure lc;
+ lc.n = 1;
+ mu_mailcap_foreach (mailcap, list_entry, &lc);
+}
+
+int
+list_entry (mu_mailcap_entry_t ent, void *closure)
+{
+ struct list_closure *lc = closure;
+ struct mu_locus_range lr = MU_LOCUS_RANGE_INITIALIZER;
+
+ if (mu_mailcap_entry_get_locus (ent, &lr) == 0)
+ {
+ mu_stream_lprintf (mu_strout, &lr, "entry[%lu]\n", lc->n);
+ mu_locus_range_deinit (&lr);
+ }
+ else
+ mu_printf ("entry[%lu]\n", lc->n);
+ list_single_entry (ent);
+ lc->n++;
+ return 0;
+}
+
+static void
+list_single_entry (mu_mailcap_entry_t ent)
+{
+ struct list_closure fc;
+ char const *val;
+
+ MU_ASSERT (mu_mailcap_entry_sget_type (ent, &val));
+ mu_printf ("\ttypefield: %s\n", val);
+ MU_ASSERT (mu_mailcap_entry_sget_command (ent, &val));
+ mu_printf ("\tview-command: %s\n", val);
+ fc.n = 1;
+ mu_mailcap_entry_fields_foreach (ent, list_field, &fc);
+ mu_printf ("\n");
+}
+
+static int
+list_field (char const *name, char const *value, void *data)
+{
+ struct list_closure *fc = data;
+ mu_printf ("\tfields[%lu]: ", fc->n++);
+ if (value)
+ mu_printf ("%s=%s", name, value);
+ else
+ mu_printf ("%s", name);
+ mu_printf ("\n");
return 0;
}
diff --git a/libmailutils/tests/mcf.c b/libmailutils/tests/mcf.c
new file mode 100644
index 0000000..ba240d7
--- a/dev/null
+++ b/libmailutils/tests/mcf.c
@@ -0,0 +1,148 @@
+/* GNU Mailutils -- a suite of utilities for electronic mail
+ Copyright (C) 1999-2019 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.
+
+ GNU Mailutils 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/>. */
+
+#ifdef HAVE_CONFIG_H
+# include <config.h>
+#endif
+#include <stdlib.h>
+#include <stdio.h>
+#include <mailutils/mailutils.h>
+
+void
+usage (mu_stream_t str)
+{
+ mu_stream_printf (str, "usage: mcf [-l] TYPE/SUBTYPE FILE [FILE...]\n");
+}
+
+int
+selector (mu_mailcap_entry_t entry, void *data)
+{
+ char const *type = data;
+ char const *pattern;
+
+ MU_ASSERT (mu_mailcap_entry_sget_type (entry, &pattern));
+ return mu_mailcap_string_match (pattern, 0, type);
+}
+
+static void list_entry (mu_mailcap_entry_t ent, unsigned long n);
+
+int
+main (int argc, char **argv)
+{
+ struct mu_mailcap_selector_closure selcl;
+ char *type;
+ int rc;
+ mu_mailcap_finder_t finder;
+ mu_mailcap_entry_t entry;
+ size_t n;
+ int flags = MU_MAILCAP_FLAG_DEFAULT;
+ char *arg;
+
+ mu_stdstream_setup (MU_STDSTREAM_RESET_NONE);
+
+ while (--argc && (arg = *++argv)[0] == '-')
+ {
+ if (strcmp (arg, "--") == 0)
+ {
+ argc--;
+ argv++;
+ break;
+ }
+ else if (strcmp (arg, "-l") == 0)
+ flags |= MU_MAILCAP_FLAG_LOCUS;
+ else
+ {
+ mu_error ("unrecognized option: %s", arg);
+ usage (mu_strerr);
+ return 1;
+ }
+ }
+
+ if (argc < 2)
+ {
+ usage (mu_strerr);
+ return 1;
+ }
+ type = argv[0];
+ mu_printf ("%s\n", type);
+
+ memset (&selcl, 0, sizeof (selcl));
+ selcl.selector = selector;
+ selcl.data = type;
+
+ MU_ASSERT (mu_mailcap_finder_create (&finder, flags,
+ &selcl,
+ &mu_mailcap_default_error_closure,
+ argv + 1));
+
+ n = 1;
+ while ((rc = mu_mailcap_finder_next_match (finder, &entry)) == 0)
+ {
+ list_entry (entry, n++);
+ }
+ mu_mailcap_finder_destroy (&finder);
+
+ if (rc != MU_ERR_NOENT)
+ {
+ mu_diag_funcall (MU_DIAG_ERR,
+ "mu_mailcap_finder_next_match",
+ NULL,
+ rc);
+ }
+
+ return 0;
+}
+
+struct list_closure
+{
+ unsigned long n;
+};
+
+static int
+list_field (char const *name, char const *value, void *data)
+{
+ struct list_closure *fc = data;
+ mu_printf ("\tfields[%lu]: ", fc->n++);
+ if (value)
+ mu_printf ("%s=%s", name, value);
+ else
+ mu_printf ("%s", name);
+ mu_printf ("\n");
+ return 0;
+}
+
+static void
+list_entry (mu_mailcap_entry_t ent, unsigned long n)
+{
+ struct mu_locus_range lr = MU_LOCUS_RANGE_INITIALIZER;
+ char const *val;
+ struct list_closure fc;
+
+ if (mu_mailcap_entry_get_locus (ent, &lr) == 0)
+ {
+ mu_stream_lprintf (mu_strout, &lr, "entry[%lu]\n", n);
+ mu_locus_range_deinit (&lr);
+ }
+ else
+ mu_printf ("entry[%lu]\n", n);
+ MU_ASSERT (mu_mailcap_entry_sget_type (ent, &val));
+ mu_printf ("\ttypefield: %s\n", val);
+ MU_ASSERT (mu_mailcap_entry_sget_command (ent, &val));
+ mu_printf ("\tview-command: %s\n", val);
+ fc.n = 1;
+ mu_mailcap_entry_fields_foreach (ent, list_field, &fc);
+ mu_printf ("\n");
+}
diff --git a/libmailutils/tests/testsuite.at b/libmailutils/tests/testsuite.at
index d4ce2ec..e641c78 100644
--- a/libmailutils/tests/testsuite.at
+++ b/libmailutils/tests/testsuite.at
@@ -17,11 +17,13 @@
m4_include([testsuite.inc])
dnl ------------------------------------------------------------
-m4_define([MU_TEST_GROUP],[generic])
+m4_pushdef([MU_TEST_GROUP],[generic])
dnl ------------------------------------------------------------
-m4_define([MU_TEST_KEYWORDS])
+m4_pushdef([MU_TEST_KEYWORDS])
dnl ------------------------------------------------------------
-m4_define([MU_TEST_COMMAND])
+m4_pushdef([MU_TEST_COMMAND])
+dnl ------------------------------------------------------------
+m4_pushdef([MU_TEST_PASS_FILE],[< $1])
m4_define([mu_trimstr],[m4_if([$2],-1,[$1],[m4_substr([$1],0,$2)...])])
m4_define([mu_firstline],[mu_trimstr([$1],m4_index([$1],[
@@ -41,13 +43,13 @@ dnl STDERR $6
dnl RUN-IF-FAIL $7
dnl RUN-IF-PASS $8
dnl
-m4_define([MU_GENERIC_TEST],[
+m4_pushdef([MU_GENERIC_TEST],[
AT_SETUP([m4_if(MU_TEST_GROUP,[],,MU_TEST_GROUP: )m4_if([$1],[],[mu_firstline([$3])],[$1])])
AT_KEYWORDS([MU_TEST_KEYWORDS $2])
AT_CHECK([
AT_DATA([input],[$3
])
-MU_TEST_COMMAND < input],[$4],[$5],[$6],[$7],[$8])
+MU_TEST_COMMAND MU_TEST_PASS_FILE(input)],[$4],[$5],[$6],[$7],[$8])
AT_CLEANUP
])
@@ -184,7 +186,11 @@ m4_include([wordsplit.at])
m4_include([exp.at])
m4_include([url.at])
m4_include([url-comp.at])
+
+AT_BANNER(Mailcap)
+m4_include([ctm.at])
m4_include([mailcap.at])
+
m4_include([wicket.at])
m4_include([prop.at])
@@ -237,3 +243,10 @@ m4_include([msgset.at])
m4_include([globtest.at])
m4_include([linetrack.at])
+
+
+m4_popdef([MU_TEST_GROUP])
+m4_popdef([MU_TEST_KEYWORDS])
+m4_popdef([MU_TEST_COMMAND])
+m4_popdef([MU_TEST_PASS_FILE])
+m4_popdef([MU_GENERIC_TEST])
diff --git a/libmu_cpp/mailcap.cc b/libmu_cpp/mailcap.cc
index ef53f28..d76f501 100644
--- a/libmu_cpp/mailcap.cc
+++ b/libmu_cpp/mailcap.cc
@@ -25,7 +25,15 @@ using namespace mailutils;
Mailcap :: Mailcap (const Stream& stm)
{
- int status = mu_mailcap_create (&mailcap, stm.stm);
+ int status;
+
+ status = mu_mailcap_create (&mailcap);
+ if (status == 0)
+ {
+ status = mu_mailcap_parse (mailcap, stm.stm, NULL);
+ if (status == MU_ERR_PARSE)
+ status = 0; /* FIXME */
+ }
if (status)
throw Exception ("Mailcap::Mailcap", status);
}
@@ -47,20 +55,20 @@ size_t
Mailcap :: entries_count ()
{
size_t count = 0;
- int status = mu_mailcap_entries_count (mailcap, &count);
+ int status = mu_mailcap_get_count (mailcap, &count);
if (status)
throw Exception ("Mailcap::entries_count", status);
return count;
}
MailcapEntry&
-Mailcap :: get_entry (size_t i)
+Mailcap :: find_entry (const std::string& name)
{
mu_mailcap_entry_t c_entry;
- int status = mu_mailcap_get_entry (mailcap, i, &c_entry);
+ int status = mu_mailcap_find_entry (mailcap, name.c_str (), &c_entry);
if (status)
- throw Exception ("Mailcap::get_entry", status);
+ throw Exception ("Mailcap::find_entry", status);
MailcapEntry* entry = new MailcapEntry (c_entry);
return *entry;
@@ -89,32 +97,32 @@ MailcapEntry :: fields_count ()
}
std::string
-MailcapEntry :: get_field (size_t i)
+MailcapEntry :: get_field (const std::string& name)
{
- int status = mu_mailcap_entry_get_field (entry, i, buf,
- sizeof (buf), NULL);
+ char const *value;
+ int status = mu_mailcap_entry_sget_field (entry, name.c_str (), &value);
if (status)
throw Exception ("MailcapEntry::get_field", status);
- return std::string (buf);
+ return std::string (value ? value : "");
}
std::string
MailcapEntry :: get_typefield ()
{
- int status = mu_mailcap_entry_get_typefield (entry, buf,
- sizeof (buf), NULL);
+ char const *value;
+ int status = mu_mailcap_entry_sget_type (entry, &value);
if (status)
throw Exception ("MailcapEntry::get_typefield", status);
- return std::string (buf);
+ return std::string (value);
}
std::string
MailcapEntry :: get_viewcommand ()
{
- int status = mu_mailcap_entry_get_viewcommand (entry, buf,
- sizeof (buf), NULL);
+ char const *value;
+ int status = mu_mailcap_entry_sget_command (entry, &value);
if (status)
throw Exception ("MailcapEntry::get_viewcommand", status);
- return std::string (buf);
+ return std::string (value);
}
diff --git a/python/2/libmu_py/mailcap.c b/python/2/libmu_py/mailcap.c
index 24243ca..615b5fd 100644
--- a/python/2/libmu_py/mailcap.c
+++ b/python/2/libmu_py/mailcap.c
@@ -12,7 +12,7 @@
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
+ Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#include "libmu_py.h"
@@ -151,7 +151,12 @@ api_mailcap_create (PyObject *self, PyObject *args)
return NULL;
}
- status = mu_mailcap_create (&py_mc->mc, py_stm->stm);
+ status = mu_mailcap_create (&py_mc->mc);
+ if (status)
+ return _ro (PyInt_FromLong (status));
+ status = mu_mailcap_parse (py_mc->mc, py_stm->stm, NULL);
+ if (status == MU_ERR_PARSE)
+ status = 0; /* FIXME */
return _ro (PyInt_FromLong (status));
}
@@ -177,7 +182,7 @@ api_mailcap_entries_count (PyObject *self, PyObject *args)
if (!PyArg_ParseTuple (args, "O!", &PyMailcapType, &py_mc))
return NULL;
- status = mu_mailcap_entries_count (py_mc->mc, &count);
+ status = mu_mailcap_get_count (py_mc->mc, &count);
return status_object (status, PyInt_FromSize_t (count));
}
@@ -188,7 +193,6 @@ api_mailcap_get_entry (PyObject *self, PyObject *args)
Py_ssize_t i;
PyMailcap *py_mc;
PyMailcapEntry *py_entry = PyMailcapEntry_NEW ();
-
if (!PyArg_ParseTuple (args, "O!n", &PyMailcapType, &py_mc, &i))
return NULL;
ASSERT_INDEX_RANGE (i, "mailcap");
@@ -199,6 +203,22 @@ api_mailcap_get_entry (PyObject *self, PyObject *args)
}
static PyObject *
+api_mailcap_find_entry (PyObject *self, PyObject *args)
+{
+ int status;
+ PyMailcap *py_mc;
+ PyMailcapEntry *py_entry = PyMailcapEntry_NEW ();
+ char *name;
+
+ if (!PyArg_ParseTuple (args, "O!s", &PyMailcapType, &py_mc, &name))
+ return NULL;
+ status = mu_mailcap_find_entry (py_mc->mc, name, &py_entry->entry);
+
+ Py_INCREF (py_entry);
+ return status_object (status, (PyObject *)py_entry);
+}
+
+static PyObject *
api_mailcap_entry_fields_count (PyObject *self, PyObject *args)
{
int status;
@@ -216,46 +236,46 @@ static PyObject *
api_mailcap_entry_get_field (PyObject *self, PyObject *args)
{
int status;
- Py_ssize_t i;
- char buf[256];
+ char *name;
+ char const *value;
PyMailcapEntry *py_entry;
- if (!PyArg_ParseTuple (args, "O!n", &PyMailcapEntryType, &py_entry, &i))
+ if (!PyArg_ParseTuple (args, "O!s", &PyMailcapEntryType, &py_entry, &name))
return NULL;
- ASSERT_INDEX_RANGE (i, "mailcap");
- status = mu_mailcap_entry_get_field (py_entry->entry, i, buf,
- sizeof (buf), NULL);
- return status_object (status, PyString_FromString (buf));
+ status = mu_mailcap_entry_sget_field (py_entry->entry, name, &value);
+ return status_object (status,
+ status == 0
+ ? (value ? PyString_FromString (value)
+ : PyBool_FromLong (1))
+ : PyBool_FromLong (0));
}
static PyObject *
api_mailcap_entry_get_typefield (PyObject *self, PyObject *args)
{
int status;
- char buf[256];
+ char const *value;
PyMailcapEntry *py_entry;
if (!PyArg_ParseTuple (args, "O!", &PyMailcapEntryType, &py_entry))
return NULL;
- status = mu_mailcap_entry_get_typefield (py_entry->entry, buf,
- sizeof (buf), NULL);
- return status_object (status, PyString_FromString (buf));
+ status = mu_mailcap_entry_sget_type (py_entry->entry, &value);
+ return status_object (status, PyString_FromString (status == 0 ? value : ""));
}
static PyObject *
api_mailcap_entry_get_viewcommand (PyObject *self, PyObject *args)
{
int status;
- char buf[256];
+ char const *value;
PyMailcapEntry *py_entry;
if (!PyArg_ParseTuple (args, "O!", &PyMailcapEntryType, &py_entry))
return NULL;
- status = mu_mailcap_entry_get_viewcommand (py_entry->entry, buf,
- sizeof (buf), NULL);
- return status_object (status, PyString_FromString (buf));
+ status = mu_mailcap_entry_sget_command (py_entry->entry, &value);
+ return status_object (status, PyString_FromString (status == 0 ? value : ""));
}
static PyMethodDef methods[] = {
@@ -271,6 +291,9 @@ static PyMethodDef methods[] = {
{ "get_entry", (PyCFunction) api_mailcap_get_entry, METH_VARARGS,
"Return in 'entry' the mailcap entry of 'no'." },
+ { "find_entry", (PyCFunction) api_mailcap_find_entry, METH_VARARGS,
+ "Return in 'entry' the mailcap entry for given content-type." },
+
{ "entry_fields_count", (PyCFunction) api_mailcap_entry_fields_count,
METH_VARARGS,
"Return the number of fields found in the entry." },
diff --git a/python/3/libmu_py/mailcap.c b/python/3/libmu_py/mailcap.c
index 81eb6d9..6db1770 100644
--- a/python/3/libmu_py/mailcap.c
+++ b/python/3/libmu_py/mailcap.c
@@ -12,7 +12,7 @@
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
+ Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#include "libmu_py.h"
@@ -89,8 +89,13 @@ api_mailcap_create (PyObject *self, PyObject *args)
return NULL;
}
- status = mu_mailcap_create (&py_mc->mc, py_stm->stm);
- return _ro (PyLong_FromLong (status));
+ status = mu_mailcap_create (&py_mc->mc);
+ if (status)
+ return _ro (PyInt_FromLong (status));
+ status = mu_mailcap_parse (py_mc->mc, py_stm->stm, NULL);
+ if (status == MU_ERR_PARSE)
+ status = 0; /* FIXME */
+ return _ro (PyInt_FromLong (status));
}
static PyObject *
@@ -115,7 +120,7 @@ api_mailcap_entries_count (PyObject *self, PyObject *args)
if (!PyArg_ParseTuple (args, "O!", &PyMailcapType, &py_mc))
return NULL;
- status = mu_mailcap_entries_count (py_mc->mc, &count);
+ status = mu_mailcap_get_count (py_mc->mc, &count);
return status_object (status, PyLong_FromSize_t (count));
}
@@ -126,7 +131,6 @@ api_mailcap_get_entry (PyObject *self, PyObject *args)
Py_ssize_t i;
PyMailcap *py_mc;
PyMailcapEntry *py_entry = PyMailcapEntry_NEW ();
-
if (!PyArg_ParseTuple (args, "O!n", &PyMailcapType, &py_mc, &i))
return NULL;
ASSERT_INDEX_RANGE (i, "mailcap");
@@ -137,6 +141,22 @@ api_mailcap_get_entry (PyObject *self, PyObject *args)
}
static PyObject *
+api_mailcap_find_entry (PyObject *self, PyObject *args)
+{
+ int status;
+ PyMailcap *py_mc;
+ PyMailcapEntry *py_entry = PyMailcapEntry_NEW ();
+ char *name;
+
+ if (!PyArg_ParseTuple (args, "O!s", &PyMailcapType, &py_mc, &name))
+ return NULL;
+ status = mu_mailcap_find_entry (py_mc->mc, name, &py_entry->entry);
+
+ Py_INCREF (py_entry);
+ return status_object (status, (PyObject *)py_entry);
+}
+
+static PyObject *
api_mailcap_entry_fields_count (PyObject *self, PyObject *args)
{
int status;
@@ -154,46 +174,46 @@ static PyObject *
api_mailcap_entry_get_field (PyObject *self, PyObject *args)
{
int status;
- Py_ssize_t i;
- char buf[256];
+ char *name;
+ char const *value;
PyMailcapEntry *py_entry;
- if (!PyArg_ParseTuple (args, "O!n", &PyMailcapEntryType, &py_entry, &i))
+ if (!PyArg_ParseTuple (args, "O!s", &PyMailcapEntryType, &py_entry, &name))
return NULL;
- ASSERT_INDEX_RANGE (i, "mailcap");
- status = mu_mailcap_entry_get_field (py_entry->entry, i, buf,
- sizeof (buf), NULL);
- return status_object (status, PyUnicode_FromString (buf));
+ status = mu_mailcap_entry_sget_field (py_entry->entry, name, &value);
+ return status_object (status,
+ status == 0
+ ? (value ? PyString_FromString (value)
+ : PyBool_FromLong (1))
+ : PyBool_FromLong (0));
}
static PyObject *
api_mailcap_entry_get_typefield (PyObject *self, PyObject *args)
{
int status;
- char buf[256];
+ char const *value;
PyMailcapEntry *py_entry;
if (!PyArg_ParseTuple (args, "O!", &PyMailcapEntryType, &py_entry))
return NULL;
- status = mu_mailcap_entry_get_typefield (py_entry->entry, buf,
- sizeof (buf), NULL);
- return status_object (status, PyUnicode_FromString (buf));
+ status = mu_mailcap_entry_sget_type (py_entry->entry, &value);
+ return status_object (status, PyString_FromString (status == 0 ? value : ""));
}
static PyObject *
api_mailcap_entry_get_viewcommand (PyObject *self, PyObject *args)
{
int status;
- char buf[256];
+ char const *value;
PyMailcapEntry *py_entry;
if (!PyArg_ParseTuple (args, "O!", &PyMailcapEntryType, &py_entry))
return NULL;
- status = mu_mailcap_entry_get_viewcommand (py_entry->entry, buf,
- sizeof (buf), NULL);
- return status_object (status, PyUnicode_FromString (buf));
+ status = mu_mailcap_entry_sget_command (py_entry->entry, &value);
+ return status_object (status, PyString_FromString (status == 0 ? value : ""));
}
static PyMethodDef methods[] = {
@@ -209,6 +229,9 @@ static PyMethodDef methods[] = {
{ "get_entry", (PyCFunction) api_mailcap_get_entry, METH_VARARGS,
"Return in 'entry' the mailcap entry of 'no'." },
+ { "find_entry", (PyCFunction) api_mailcap_find_entry, METH_VARARGS,
+ "Return in 'entry' the mailcap entry for given content-type." },
+
{ "entry_fields_count", (PyCFunction) api_mailcap_entry_fields_count,
METH_VARARGS,
"Return the number of fields found in the entry." },

Return to:

Send suggestions and report system problems to the System administrator.