aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.moddir_rules2
-rw-r--r--configs/http.conf.sample13
-rwxr-xr-xconfigure6
-rw-r--r--configure.ac2
-rw-r--r--include/asterisk/autoconfig.h.in6
-rw-r--r--include/asterisk/compat.h8
-rw-r--r--include/asterisk/manager.h16
-rw-r--r--main/Makefile8
-rw-r--r--main/http.c318
-rw-r--r--main/manager.c38
-rw-r--r--main/minimime/.cvsignore4
-rw-r--r--main/minimime/Doxyfile1098
-rw-r--r--main/minimime/Make.conf7
-rw-r--r--main/minimime/Makefile60
-rw-r--r--main/minimime/mimeparser.h67
-rw-r--r--main/minimime/mimeparser.l483
-rw-r--r--main/minimime/mimeparser.tab.c2341
-rw-r--r--main/minimime/mimeparser.tab.h112
-rw-r--r--main/minimime/mimeparser.y750
-rw-r--r--main/minimime/mimeparser.yy.c2622
-rw-r--r--main/minimime/minimime.c245
-rw-r--r--main/minimime/mm-docs/html/bug.html28
-rw-r--r--main/minimime/mm-docs/html/doxygen.css358
-rw-r--r--main/minimime/mm-docs/html/files.html44
-rw-r--r--main/minimime/mm-docs/html/globals.html198
-rw-r--r--main/minimime/mm-docs/html/globals_func.html198
-rw-r--r--main/minimime/mm-docs/html/group__codecs.html243
-rw-r--r--main/minimime/mm-docs/html/group__contenttype.html516
-rw-r--r--main/minimime/mm-docs/html/group__context.html465
-rw-r--r--main/minimime/mm-docs/html/group__envelope.html172
-rw-r--r--main/minimime/mm-docs/html/group__error.html108
-rw-r--r--main/minimime/mm-docs/html/group__mimepart.html705
-rw-r--r--main/minimime/mm-docs/html/group__mimeutil.html22
-rw-r--r--main/minimime/mm-docs/html/group__param.html273
-rw-r--r--main/minimime/mm-docs/html/group__util.html280
-rw-r--r--main/minimime/mm-docs/html/index.html21
-rw-r--r--main/minimime/mm-docs/html/mimeparser_8h-source.html42
-rw-r--r--main/minimime/mm-docs/html/mimeparser_8tab_8h-source.html136
-rw-r--r--main/minimime/mm-docs/html/mm_8h-source.html382
-rw-r--r--main/minimime/mm-docs/html/mm__codecs_8c.html58
-rw-r--r--main/minimime/mm-docs/html/mm__contenttype_8c.html78
-rw-r--r--main/minimime/mm-docs/html/mm__context_8c.html63
-rw-r--r--main/minimime/mm-docs/html/mm__envelope_8c.html44
-rw-r--r--main/minimime/mm-docs/html/mm__error_8c.html49
-rw-r--r--main/minimime/mm-docs/html/mm__header_8c.html131
-rw-r--r--main/minimime/mm-docs/html/mm__internal_8h-source.html82
-rw-r--r--main/minimime/mm-docs/html/mm__internal_8h.html78
-rw-r--r--main/minimime/mm-docs/html/mm__mem_8h-source.html56
-rw-r--r--main/minimime/mm-docs/html/mm__mimepart_8c.html79
-rw-r--r--main/minimime/mm-docs/html/mm__mimeutil_8c.html76
-rw-r--r--main/minimime/mm-docs/html/mm__param_8c.html57
-rw-r--r--main/minimime/mm-docs/html/mm__parse_8c.html198
-rw-r--r--main/minimime/mm-docs/html/mm__queue_8h-source.html532
-rw-r--r--main/minimime/mm-docs/html/mm__util_8c.html58
-rw-r--r--main/minimime/mm-docs/html/mm__util_8h-source.html74
-rw-r--r--main/minimime/mm-docs/html/modules.html30
-rw-r--r--main/minimime/mm-docs/html/pages.html23
-rw-r--r--main/minimime/mm-docs/html/tabs.css102
-rw-r--r--main/minimime/mm-docs/latex/Makefile39
-rw-r--r--main/minimime/mm-docs/latex/bug.tex9
-rw-r--r--main/minimime/mm-docs/latex/doxygen.sty78
-rw-r--r--main/minimime/mm-docs/latex/files.tex21
-rw-r--r--main/minimime/mm-docs/latex/group__codecs.tex119
-rw-r--r--main/minimime/mm-docs/latex/group__contenttype.tex246
-rw-r--r--main/minimime/mm-docs/latex/group__context.tex214
-rw-r--r--main/minimime/mm-docs/latex/group__envelope.tex65
-rw-r--r--main/minimime/mm-docs/latex/group__error.tex43
-rw-r--r--main/minimime/mm-docs/latex/group__mimepart.tex333
-rw-r--r--main/minimime/mm-docs/latex/group__mimeutil.tex2
-rw-r--r--main/minimime/mm-docs/latex/group__param.tex127
-rw-r--r--main/minimime/mm-docs/latex/group__util.tex128
-rw-r--r--main/minimime/mm-docs/latex/mm__codecs_8c.tex41
-rw-r--r--main/minimime/mm-docs/latex/mm__contenttype_8c.tex61
-rw-r--r--main/minimime/mm-docs/latex/mm__context_8c.tex44
-rw-r--r--main/minimime/mm-docs/latex/mm__envelope_8c.tex25
-rw-r--r--main/minimime/mm-docs/latex/mm__error_8c.tex29
-rw-r--r--main/minimime/mm-docs/latex/mm__header_8c.tex63
-rw-r--r--main/minimime/mm-docs/latex/mm__internal_8h.tex45
-rw-r--r--main/minimime/mm-docs/latex/mm__mimepart_8c.tex69
-rw-r--r--main/minimime/mm-docs/latex/mm__mimeutil_8c.tex50
-rw-r--r--main/minimime/mm-docs/latex/mm__param_8c.tex38
-rw-r--r--main/minimime/mm-docs/latex/mm__parse_8c.tex90
-rw-r--r--main/minimime/mm-docs/latex/mm__util_8c.tex38
-rw-r--r--main/minimime/mm-docs/latex/modules.tex12
-rw-r--r--main/minimime/mm-docs/latex/pages.tex5
-rw-r--r--main/minimime/mm-docs/latex/refman.tex62
-rw-r--r--main/minimime/mm-docs/refman.pdfbin0 -> 261943 bytes
-rw-r--r--main/minimime/mm.h368
-rw-r--r--main/minimime/mm_base64.c210
-rw-r--r--main/minimime/mm_codecs.c250
-rw-r--r--main/minimime/mm_contenttype.c757
-rw-r--r--main/minimime/mm_context.c604
-rw-r--r--main/minimime/mm_envelope.c269
-rw-r--r--main/minimime/mm_error.c123
-rw-r--r--main/minimime/mm_header.c213
-rw-r--r--main/minimime/mm_init.c65
-rw-r--r--main/minimime/mm_internal.h65
-rw-r--r--main/minimime/mm_mem.c171
-rw-r--r--main/minimime/mm_mem.h32
-rw-r--r--main/minimime/mm_mimepart.c657
-rw-r--r--main/minimime/mm_mimeutil.c136
-rw-r--r--main/minimime/mm_param.c215
-rw-r--r--main/minimime/mm_parse.c181
-rw-r--r--main/minimime/mm_queue.h508
-rw-r--r--main/minimime/mm_util.c412
-rw-r--r--main/minimime/mm_util.h50
-rw-r--r--main/minimime/mm_warnings.c99
-rw-r--r--main/minimime/mytest_files/ast_postdata38
-rw-r--r--main/minimime/mytest_files/ast_postdata2bin0 -> 1737 bytes
-rw-r--r--main/minimime/mytest_files/ast_postdata3.gzbin0 -> 526318 bytes
-rw-r--r--main/minimime/mytest_files/mytest.c71
-rw-r--r--main/minimime/strlcat.c70
-rw-r--r--main/minimime/strlcpy.c66
-rw-r--r--main/minimime/sys/CVS/Entries2
-rw-r--r--main/minimime/sys/CVS/Repository1
-rw-r--r--main/minimime/sys/CVS/Root1
-rw-r--r--main/minimime/sys/mm_queue.h503
-rwxr-xr-xmain/minimime/test.sh54
-rw-r--r--main/minimime/test/CVS/Entries1
-rw-r--r--main/minimime/test/CVS/Repository1
-rw-r--r--main/minimime/test/CVS/Root1
-rw-r--r--main/minimime/tests/CVS/Entries4
-rw-r--r--main/minimime/tests/CVS/Entries.Log1
-rw-r--r--main/minimime/tests/CVS/Repository1
-rw-r--r--main/minimime/tests/CVS/Root1
-rw-r--r--main/minimime/tests/Makefile18
-rw-r--r--main/minimime/tests/create.c106
-rw-r--r--main/minimime/tests/messages/CVS/Entries8
-rw-r--r--main/minimime/tests/messages/CVS/Repository1
-rw-r--r--main/minimime/tests/messages/CVS/Root1
-rw-r--r--main/minimime/tests/messages/test1.txt50
-rw-r--r--main/minimime/tests/messages/test2.txt50
-rw-r--r--main/minimime/tests/messages/test3.txt12
-rw-r--r--main/minimime/tests/messages/test4.txt168
-rw-r--r--main/minimime/tests/messages/test5.txt44
-rw-r--r--main/minimime/tests/messages/test6.txt12
-rw-r--r--main/minimime/tests/messages/test7.txt64
-rw-r--r--main/minimime/tests/parse.c231
-rw-r--r--main/strcompat.c128
139 files changed, 23447 insertions, 8 deletions
diff --git a/Makefile.moddir_rules b/Makefile.moddir_rules
index d2dafe329..1c78ebd45 100644
--- a/Makefile.moddir_rules
+++ b/Makefile.moddir_rules
@@ -12,7 +12,9 @@
#
ifneq ($(findstring MALLOC_DEBUG,$(MENUSELECT_CFLAGS)),)
+ ifeq ($(findstring astmm.h,$(ASTCFLAGS)),)
ASTCFLAGS+=-include $(ASTTOPDIR)/include/asterisk/astmm.h
+ endif
endif
ifeq ($(findstring LOADABLE_MODULES,$(MENUSELECT_CFLAGS)),)
diff --git a/configs/http.conf.sample b/configs/http.conf.sample
index 19f96ca9a..ebd09e79f 100644
--- a/configs/http.conf.sample
+++ b/configs/http.conf.sample
@@ -48,3 +48,16 @@ bindaddr=127.0.0.1
; To produce a certificate you can e.g. use openssl
; openssl req -new -x509 -days 365 -nodes -out /tmp/foo.pem -keyout /tmp/foo.pem
;
+;prefix=asterisk
+
+; The post_mappings section maps URLs to real paths on the filesystem. If a
+; POST is done from within an authenticated manager session to one of the
+; configured POST mappings, then any files in the POST will be placed in the
+; configured directory.
+;
+;[post_mappings]
+;
+; In this example, if the prefix option is set to "asterisk", then using the
+; POST URL: /asterisk/uploads will put files in /var/lib/asterisk/uploads/.
+;uploads = /var/lib/asterisk/uploads/
+;
diff --git a/configure b/configure
index 00dcbd3a4..108c6e428 100755
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
#! /bin/sh
-# From configure.ac Revision: 58948 .
+# From configure.ac Revision: 59203 .
# Guess values for system-dependent variables and create Makefiles.
# Generated by GNU Autoconf 2.60.
#
@@ -16007,7 +16007,9 @@ done
-for ac_func in asprintf atexit bzero dup2 endpwent floor ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday inet_ntoa isascii localtime_r memchr memmove memset mkdir munmap pow putenv re_comp regcomp rint select setenv socket sqrt strcasecmp strcasestr strchr strcspn strdup strerror strncasecmp strndup strnlen strrchr strsep strspn strstr strtol strtoq unsetenv utime vasprintf
+
+
+for ac_func in asprintf atexit bzero dup2 endpwent floor ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday inet_ntoa isascii localtime_r memchr memmove memset mkdir munmap pow putenv re_comp regcomp rint select setenv socket sqrt strcasecmp strcasestr strchr strcspn strdup strerror strlcat strlcpy strncasecmp strndup strnlen strrchr strsep strspn strstr strtol strtoq unsetenv utime vasprintf
do
as_ac_var=`echo "ac_cv_func_$ac_func" | $as_tr_sh`
{ echo "$as_me:$LINENO: checking for $ac_func" >&5
diff --git a/configure.ac b/configure.ac
index ddc70ed39..fe23adec1 100644
--- a/configure.ac
+++ b/configure.ac
@@ -275,7 +275,7 @@ AC_FUNC_STRNLEN
AC_FUNC_STRTOD
AC_FUNC_UTIME_NULL
AC_FUNC_VPRINTF
-AC_CHECK_FUNCS([asprintf atexit bzero dup2 endpwent floor ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday inet_ntoa isascii localtime_r memchr memmove memset mkdir munmap pow putenv re_comp regcomp rint select setenv socket sqrt strcasecmp strcasestr strchr strcspn strdup strerror strncasecmp strndup strnlen strrchr strsep strspn strstr strtol strtoq unsetenv utime vasprintf])
+AC_CHECK_FUNCS([asprintf atexit bzero dup2 endpwent floor ftruncate getcwd gethostbyname gethostname getloadavg gettimeofday inet_ntoa isascii localtime_r memchr memmove memset mkdir munmap pow putenv re_comp regcomp rint select setenv socket sqrt strcasecmp strcasestr strchr strcspn strdup strerror strlcat strlcpy strncasecmp strndup strnlen strrchr strsep strspn strstr strtol strtoq unsetenv utime vasprintf])
# https support (in main/http.c) uses funopen on BSD systems,
# fopencookie on linux
diff --git a/include/asterisk/autoconfig.h.in b/include/asterisk/autoconfig.h.in
index e450ba93f..ef6a76a49 100644
--- a/include/asterisk/autoconfig.h.in
+++ b/include/asterisk/autoconfig.h.in
@@ -462,6 +462,12 @@
/* Define to 1 if you have the <string.h> header file. */
#undef HAVE_STRING_H
+/* Define to 1 if you have the `strlcat' function. */
+#undef HAVE_STRLCAT
+
+/* Define to 1 if you have the `strlcpy' function. */
+#undef HAVE_STRLCPY
+
/* Define to 1 if you have the `strncasecmp' function. */
#undef HAVE_STRNCASECMP
diff --git a/include/asterisk/compat.h b/include/asterisk/compat.h
index e02d3c7c1..838e24e47 100644
--- a/include/asterisk/compat.h
+++ b/include/asterisk/compat.h
@@ -61,6 +61,14 @@ int unsetenv(const char *name);
int vasprintf(char **strp, const char *fmt, va_list ap);
#endif
+#ifndef HAVE_STRLCAT
+size_t strlcat(char *dst, const char *src, size_t siz);
+#endif
+
+#ifndef HAVE_STRLCPY
+size_t strlcpy(char *dst, const char *src, size_t siz);
+#endif
+
#ifdef SOLARIS
#define __BEGIN_DECLS
#define __END_DECLS
diff --git a/include/asterisk/manager.h b/include/asterisk/manager.h
index 1cf03b5b5..8efcfba18 100644
--- a/include/asterisk/manager.h
+++ b/include/asterisk/manager.h
@@ -134,6 +134,22 @@ int ast_manager_register2(
*/
int ast_manager_unregister( char *action );
+/*!
+ * \brief Verify a session's read permissions against a permission mask.
+ * \param ident session identity
+ * \param perm permission mask to verify
+ * \returns 1 if the session has the permission mask capabilities, otherwise 0
+ */
+int astman_verify_session_readpermissions(unsigned long ident, int perm);
+
+/*!
+ * \brief Verify a session's write permissions against a permission mask.
+ * \param ident session identity
+ * \param perm permission mask to verify
+ * \returns 1 if the session has the permission mask capabilities, otherwise 0
+ */
+int astman_verify_session_writepermissions(unsigned long ident, int perm);
+
/*! External routines may send asterisk manager events this way */
/*! \param category Event category, matches manager authorization
\param event Event name
diff --git a/main/Makefile b/main/Makefile
index 9e0f6f235..f552fabda 100644
--- a/main/Makefile
+++ b/main/Makefile
@@ -133,7 +133,10 @@ else
H323LDLIBS=
endif
-asterisk: $(OBJS) editline/libedit.a db1-ast/libdb1.a $(AST_EMBED_LDSCRIPTS)
+minimime/libmmime.a:
+ @cd minimime && $(MAKE) libmmime.a
+
+asterisk: $(OBJS) editline/libedit.a db1-ast/libdb1.a minimime/libmmime.a $(AST_EMBED_LDSCRIPTS)
@$(CC) -c -o buildinfo.o $(ASTCFLAGS) buildinfo.c
$(ECHO_PREFIX) echo " [LD] $^ -> $@"
$(CMD_PREFIX) $(CXX) $(STATIC_BUILD) -o $@ $(ASTLINK) $(AST_EMBED_LDFLAGS) $(ASTLDFLAGS) $(H323LDFLAGS) $^ buildinfo.o $(AST_LIBS) $(AST_EMBED_LIBS) $(H323LDLIBS)
@@ -145,3 +148,6 @@ clean::
@if [ -f editline/Makefile ]; then $(MAKE) -C editline distclean ; fi
@$(MAKE) -C db1-ast clean
@$(MAKE) -C stdtime clean
+ @$(MAKE) -C minimime clean
+
+.PHONY: minimime/libmmime.a
diff --git a/main/http.c b/main/http.c
index 4fbe9bded..0dee18faa 100644
--- a/main/http.c
+++ b/main/http.c
@@ -21,8 +21,9 @@
* \brief http server for AMI access
*
* \author Mark Spencer <markster@digium.com>
- * This program implements a tiny http server supporting the "get" method
- * only and was inspired by micro-httpd by Jef Poskanzer
+ *
+ * This program implements a tiny http server
+ * and was inspired by micro-httpd by Jef Poskanzer
*
* \ref AstHTTP - AMI over the http protocol
*/
@@ -47,6 +48,8 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include <fcntl.h>
#include <pthread.h>
+#include "minimime/mm.h"
+
#include "asterisk/cli.h"
#include "asterisk/http.h"
#include "asterisk/utils.h"
@@ -55,6 +58,7 @@ ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
#include "asterisk/config.h"
#include "asterisk/stringfields.h"
#include "asterisk/version.h"
+#include "asterisk/manager.h"
#define MAX_PREFIX 80
#define DEFAULT_PREFIX "/asterisk"
@@ -93,6 +97,14 @@ static struct server_args https_desc = {
static AST_RWLIST_HEAD_STATIC(uris, ast_http_uri); /*!< list of supported handlers */
+struct ast_http_post_mapping {
+ AST_RWLIST_ENTRY(ast_http_post_mapping) entry;
+ char *from;
+ char *to;
+};
+
+static AST_RWLIST_HEAD_STATIC(post_mappings, ast_http_post_mapping);
+
/* all valid URIs must be prepended by the string in prefix. */
static char prefix[MAX_PREFIX];
static int enablestatic;
@@ -329,6 +341,225 @@ void ast_http_uri_unlink(struct ast_http_uri *urih)
AST_RWLIST_UNLOCK(&uris);
}
+/*! \note This assumes that the post_mappings list is locked */
+static struct ast_http_post_mapping *find_post_mapping(const char *uri)
+{
+ struct ast_http_post_mapping *post_map;
+
+ if (!ast_strlen_zero(prefix) && strncmp(prefix, uri, strlen(prefix))) {
+ ast_log(LOG_DEBUG, "URI %s does not have prefix %s\n", uri, prefix);
+ return NULL;
+ }
+
+ uri += strlen(prefix);
+ if (*uri == '/')
+ uri++;
+
+ AST_RWLIST_TRAVERSE(&post_mappings, post_map, entry) {
+ if (!strcmp(uri, post_map->from))
+ return post_map;
+ }
+
+ return NULL;
+}
+
+static int get_filename(struct mm_mimepart *part, char *fn, size_t fn_len)
+{
+ const char *filename;
+
+ filename = mm_content_getdispositionparambyname(part->type, "filename");
+
+ if (ast_strlen_zero(filename))
+ return -1;
+
+ ast_copy_string(fn, filename, fn_len);
+
+ return 0;
+}
+
+static void post_raw(struct mm_mimepart *part, const char *post_dir, const char *fn)
+{
+ char filename[PATH_MAX];
+ FILE *f;
+ const char *body;
+ size_t body_len;
+
+ snprintf(filename, sizeof(filename), "%s/%s", post_dir, fn);
+
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Posting raw data to %s\n", filename);
+
+ if (!(f = fopen(filename, "w"))) {
+ ast_log(LOG_WARNING, "Unable to open %s for writing file from a POST!\n", filename);
+ return;
+ }
+
+ if (!(body = mm_mimepart_getbody(part, 0))) {
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Couldn't get the mimepart body\n");
+ fclose(f);
+ return;
+ }
+ body_len = mm_mimepart_getlength(part);
+
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Body length is %ld\n", body_len);
+
+ fwrite(body, 1, body_len, f);
+
+ fclose(f);
+}
+
+static struct ast_str *handle_post(struct server_instance *ser, char *uri,
+ int *status, char **title, int *contentlength, struct ast_variable *headers,
+ struct ast_variable *cookies)
+{
+ char buf;
+ FILE *f;
+ size_t res;
+ struct ast_variable *var;
+ int content_len = 0;
+ MM_CTX *ctx;
+ int mm_res, i;
+ struct ast_http_post_mapping *post_map;
+ const char *post_dir;
+ unsigned long ident = 0;
+
+ for (var = cookies; var; var = var->next) {
+ if (strcasecmp(var->name, "mansession_id"))
+ continue;
+
+ if (sscanf(var->value, "%lx", &ident) != 1) {
+ *status = 400;
+ *title = ast_strdup("Bad Request");
+ return ast_http_error(400, "Bad Request", NULL, "The was an error parsing the request.");
+ }
+
+ if (!astman_verify_session_writepermissions(ident, EVENT_FLAG_CONFIG)) {
+ *status = 401;
+ *title = ast_strdup("Unauthorized");
+ return ast_http_error(401, "Unauthorized", NULL, "You are not authorized to make this request.");
+ }
+
+ break;
+ }
+ if (!var) {
+ *status = 401;
+ *title = ast_strdup("Unauthorized");
+ return ast_http_error(401, "Unauthorized", NULL, "You are not authorized to make this request.");
+ }
+
+ if (!(f = tmpfile()))
+ return NULL;
+
+ for (var = headers; var; var = var->next) {
+ if (!strcasecmp(var->name, "Content-Length")) {
+ if ((sscanf(var->value, "%u", &content_len)) != 1) {
+ ast_log(LOG_ERROR, "Invalid Content-Length in POST request!\n");
+ fclose(f);
+ return NULL;
+ }
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Got a Content-Length of %d\n", content_len);
+ } else if (!strcasecmp(var->name, "Content-Type"))
+ fprintf(f, "Content-Type: %s\r\n\r\n", var->value);
+ }
+
+ while ((res = fread(&buf, 1, 1, ser->f))) {
+ fwrite(&buf, 1, 1, f);
+ content_len--;
+ if (!content_len)
+ break;
+ }
+
+ if (fseek(f, SEEK_SET, 0)) {
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Failed to seek temp file back to beginning.\n");
+ fclose(f);
+ return NULL;
+ }
+
+ AST_RWLIST_RDLOCK(&post_mappings);
+ if (!(post_map = find_post_mapping(uri))) {
+ if (option_debug)
+ ast_log(LOG_DEBUG, "%s is not a valid URI for POST\n", uri);
+ AST_RWLIST_UNLOCK(&post_mappings);
+ fclose(f);
+ *status = 404;
+ *title = ast_strdup("Not Found");
+ return ast_http_error(404, "Not Found", NULL, "The requested URL was not found on this server.");
+ }
+ post_dir = ast_strdupa(post_map->to);
+ post_map = NULL;
+ AST_RWLIST_UNLOCK(&post_mappings);
+
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Going to post files to dir %s\n", post_dir);
+
+ if (!(ctx = mm_context_new())) {
+ fclose(f);
+ return NULL;
+ }
+
+ mm_res = mm_parse_fileptr(ctx, f, MM_PARSE_LOOSE, 0);
+ fclose(f);
+ if (mm_res == -1) {
+ ast_log(LOG_ERROR, "Error parsing MIME data\n");
+ mm_context_free(ctx);
+ *status = 400;
+ *title = ast_strdup("Bad Request");
+ return ast_http_error(400, "Bad Request", NULL, "The was an error parsing the request.");
+ }
+
+ mm_res = mm_context_countparts(ctx);
+ if (!mm_res) {
+ ast_log(LOG_ERROR, "Invalid MIME data, found no parts!\n");
+ mm_context_free(ctx);
+ *status = 400;
+ *title = ast_strdup("Bad Request");
+ return ast_http_error(400, "Bad Request", NULL, "The was an error parsing the request.");
+ }
+
+ if (option_debug) {
+ if (mm_context_iscomposite(ctx))
+ ast_log(LOG_DEBUG, "Found %d MIME parts\n", mm_res - 1);
+ else
+ ast_log(LOG_DEBUG, "We have a flat (not multi-part) message\n");
+ }
+
+ for (i = 1; i < mm_res; i++) {
+ struct mm_mimepart *part;
+ char fn[PATH_MAX];
+
+ if (!(part = mm_context_getpart(ctx, i))) {
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Failed to get mime part num %d\n", i);
+ continue;
+ }
+
+ if (get_filename(part, fn, sizeof(fn))) {
+ if (option_debug)
+ ast_log(LOG_DEBUG, "Failed to retrieve a filename for part num %d\n", i);
+ continue;
+ }
+
+ if (!part->type) {
+ if (option_debug)
+ ast_log(LOG_DEBUG, "This part has no content struct?\n");
+ continue;
+ }
+
+ /* XXX This assumes the MIME part body is not encoded! */
+ post_raw(part, post_dir, fn);
+ }
+
+ mm_context_free(ctx);
+
+ *status = 200;
+ *title = ast_strdup("OK");
+ return ast_http_error(200, "OK", NULL, "File successfully uploaded.");
+}
+
static struct ast_str *handle_uri(struct sockaddr_in *sin, char *uri, int *status, char **title, int *contentlength, struct ast_variable **cookies)
{
char *c;
@@ -520,7 +751,7 @@ static void *httpd_helper_thread(void *data)
char buf[4096];
char cookie[4096];
struct server_instance *ser = data;
- struct ast_variable *var, *prev=NULL, *vars=NULL;
+ struct ast_variable *var, *prev=NULL, *vars=NULL, *headers = NULL;
char *uri, *title=NULL;
int status = 200, contentlength = 0;
struct ast_str *out = NULL;
@@ -549,8 +780,23 @@ static void *httpd_helper_thread(void *data)
ast_trim_blanks(cookie);
if (ast_strlen_zero(cookie))
break;
- if (strncasecmp(cookie, "Cookie: ", 8))
+ if (strncasecmp(cookie, "Cookie: ", 8)) {
+ char *name, *value;
+
+ value = ast_strdupa(cookie);
+ name = strsep(&value, ":");
+ if (!value)
+ continue;
+ value = ast_skip_blanks(value);
+ if (ast_strlen_zero(value))
+ continue;
+ var = ast_variable_new(name, value);
+ if (!var)
+ continue;
+ var->next = headers;
+ headers = var;
continue;
+ }
/* TODO - The cookie parsing code below seems to work
in IE6 and FireFox 1.5. However, it is not entirely
@@ -596,6 +842,8 @@ static void *httpd_helper_thread(void *data)
if (!*uri)
out = ast_http_error(400, "Bad Request", NULL, "Invalid Request");
+ else if (!strcasecmp(buf, "post"))
+ out = handle_post(ser, uri, &status, &title, &contentlength, headers, vars);
else if (strcasecmp(buf, "get"))
out = ast_http_error(501, "Not Implemented", NULL,
"Attempt to use unimplemented / unsupported method");
@@ -851,6 +1099,47 @@ static void add_redirect(const char *value)
AST_RWLIST_UNLOCK(&uri_redirects);
}
+static void destroy_post_mapping(struct ast_http_post_mapping *post_map)
+{
+ if (post_map->from)
+ free(post_map->from);
+ if (post_map->to)
+ free(post_map->to);
+ free(post_map);
+}
+
+static void destroy_post_mappings(void)
+{
+ struct ast_http_post_mapping *post_map;
+
+ AST_RWLIST_WRLOCK(&post_mappings);
+ while ((post_map = AST_RWLIST_REMOVE_HEAD(&post_mappings, entry)))
+ destroy_post_mapping(post_map);
+ AST_RWLIST_UNLOCK(&post_mappings);
+}
+
+static void add_post_mapping(const char *from, const char *to)
+{
+ struct ast_http_post_mapping *post_map;
+
+ if (!(post_map = ast_calloc(1, sizeof(*post_map))))
+ return;
+
+ if (!(post_map->from = ast_strdup(from))) {
+ destroy_post_mapping(post_map);
+ return;
+ }
+
+ if (!(post_map->to = ast_strdup(to))) {
+ destroy_post_mapping(post_map);
+ return;
+ }
+
+ AST_RWLIST_WRLOCK(&post_mappings);
+ AST_RWLIST_INSERT_TAIL(&post_mappings, post_map, entry);
+ AST_RWLIST_UNLOCK(&post_mappings);
+}
+
static int __ast_http_load(int reload)
{
struct ast_config *cfg;
@@ -869,6 +1158,7 @@ static int __ast_http_load(int reload)
memset(&https_desc.sin, 0, sizeof(https_desc.sin));
https_desc.sin.sin_port = htons(8089);
+
strcpy(newprefix, DEFAULT_PREFIX);
http_tls_cfg.enabled = 0;
@@ -884,6 +1174,8 @@ static int __ast_http_load(int reload)
free(redirect);
AST_RWLIST_UNLOCK(&uri_redirects);
+ destroy_post_mappings();
+
cfg = ast_config_load("http.conf");
if (cfg) {
v = ast_variable_browse(cfg, "general");
@@ -931,6 +1223,10 @@ static int __ast_http_load(int reload)
ast_log(LOG_WARNING, "Ignoring unknown option '%s' in http.conf\n", v->name);
}
}
+
+ for (v = ast_variable_browse(cfg, "post_mappings"); v; v = v->next)
+ add_post_mapping(v->name, v->value);
+
ast_config_destroy(cfg);
}
if (!have_sslbindaddr)
@@ -943,6 +1239,7 @@ static int __ast_http_load(int reload)
server_start(&http_desc);
if (ssl_setup(https_desc.tls_cfg))
server_start(&https_desc);
+
return 0;
}
@@ -950,6 +1247,7 @@ static int handle_show_http(int fd, int argc, char *argv[])
{
struct ast_http_uri *urih;
struct http_uri_redirect *redirect;
+ struct ast_http_post_mapping *post_map;
if (argc != 3)
return RESULT_SHOWUSAGE;
@@ -986,6 +1284,14 @@ static int handle_show_http(int fd, int argc, char *argv[])
ast_cli(fd, " None.\n");
AST_RWLIST_UNLOCK(&uri_redirects);
+
+ ast_cli(fd, "\nPOST mappings:\n");
+ AST_RWLIST_RDLOCK(&post_mappings);
+ AST_LIST_TRAVERSE(&post_mappings, post_map, entry)
+ ast_cli(fd, "%s/%s => %s\n", prefix, post_map->from, post_map->to);
+ ast_cli(fd, "%s\n", AST_LIST_EMPTY(&post_mappings) ? "None.\n" : "");
+ AST_RWLIST_UNLOCK(&post_mappings);
+
return RESULT_SUCCESS;
}
@@ -1006,8 +1312,12 @@ static struct ast_cli_entry cli_http[] = {
int ast_http_init(void)
{
+ mm_library_init();
+ mm_codec_registerdefaultcodecs();
+
ast_http_uri_link(&statusuri);
ast_http_uri_link(&staticuri);
ast_cli_register_multiple(cli_http, sizeof(cli_http) / sizeof(struct ast_cli_entry));
+
return __ast_http_load(0);
}
diff --git a/main/manager.c b/main/manager.c
index 116b77a37..891df4c82 100644
--- a/main/manager.c
+++ b/main/manager.c
@@ -2592,6 +2592,44 @@ static struct mansession *find_session(unsigned long ident)
return s;
}
+int astman_verify_session_readpermissions(unsigned long ident, int perm)
+{
+ int result = 0;
+ struct mansession *s;
+
+ AST_LIST_LOCK(&sessions);
+ AST_LIST_TRAVERSE(&sessions, s, list) {
+ ast_mutex_lock(&s->__lock);
+ if ((s->managerid == ident) && (s->readperm & perm)) {
+ result = 1;
+ ast_mutex_unlock(&s->__lock);
+ break;
+ }
+ ast_mutex_unlock(&s->__lock);
+ }
+ AST_LIST_UNLOCK(&sessions);
+ return result;
+}
+
+int astman_verify_session_writepermissions(unsigned long ident, int perm)
+{
+ int result = 0;
+ struct mansession *s;
+
+ AST_LIST_LOCK(&sessions);
+ AST_LIST_TRAVERSE(&sessions, s, list) {
+ ast_mutex_lock(&s->__lock);
+ if ((s->managerid == ident) && (s->writeperm & perm)) {
+ result = 1;
+ ast_mutex_unlock(&s->__lock);
+ break;
+ }
+ ast_mutex_unlock(&s->__lock);
+ }
+ AST_LIST_UNLOCK(&sessions);
+ return result;
+}
+
/*
* convert to xml with various conversion:
* mode & 1 -> lowercase;
diff --git a/main/minimime/.cvsignore b/main/minimime/.cvsignore
new file mode 100644
index 000000000..f5e1bf873
--- /dev/null
+++ b/main/minimime/.cvsignore
@@ -0,0 +1,4 @@
+minimime
+*.so.*
+*.o
+*.swp
diff --git a/main/minimime/Doxyfile b/main/minimime/Doxyfile
new file mode 100644
index 000000000..5ad5e11ec
--- /dev/null
+++ b/main/minimime/Doxyfile
@@ -0,0 +1,1098 @@
+# Doxyfile 1.3.5
+
+# This file describes the settings to be used by the documentation system
+# doxygen (www.doxygen.org) for a project
+#
+# All text after a hash (#) is considered a comment and will be ignored
+# The format is:
+# TAG = value [value, ...]
+# For lists items can also be appended using:
+# TAG += value [value, ...]
+# Values that contain spaces should be placed between quotes (" ")
+
+#---------------------------------------------------------------------------
+# Project related configuration options
+#---------------------------------------------------------------------------
+
+# The PROJECT_NAME tag is a single word (or a sequence of words surrounded
+# by quotes) that should identify the project.
+
+PROJECT_NAME = MiniMIME
+
+# The PROJECT_NUMBER tag can be used to enter a project or revision number.
+# This could be handy for archiving the generated documentation or
+# if some version control system is used.
+
+PROJECT_NUMBER =
+
+# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute)
+# base path where the generated documentation will be put.
+# If a relative path is entered, it will be relative to the location
+# where doxygen was started. If left blank the current directory will be used.
+
+OUTPUT_DIRECTORY = mm-docs
+
+# The OUTPUT_LANGUAGE tag is used to specify the language in which all
+# documentation generated by doxygen is written. Doxygen will use this
+# information to generate all constant output in the proper language.
+# The default language is English, other supported languages are:
+# Brazilian, Catalan, Chinese, Chinese-Traditional, Croatian, Czech, Danish, Dutch,
+# Finnish, French, German, Greek, Hungarian, Italian, Japanese, Japanese-en
+# (Japanese with English messages), Korean, Norwegian, Polish, Portuguese,
+# Romanian, Russian, Serbian, Slovak, Slovene, Spanish, Swedish, and Ukrainian.
+
+OUTPUT_LANGUAGE = English
+
+# This tag can be used to specify the encoding used in the generated output.
+# The encoding is not always determined by the language that is chosen,
+# but also whether or not the output is meant for Windows or non-Windows users.
+# In case there is a difference, setting the USE_WINDOWS_ENCODING tag to YES
+# forces the Windows encoding (this is the default for the Windows binary),
+# whereas setting the tag to NO uses a Unix-style encoding (the default for
+# all platforms other than Windows).
+
+USE_WINDOWS_ENCODING = NO
+
+# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will
+# include brief member descriptions after the members that are listed in
+# the file and class documentation (similar to JavaDoc).
+# Set to NO to disable this.
+
+BRIEF_MEMBER_DESC = YES
+
+# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend
+# the brief description of a member or function before the detailed description.
+# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
+# brief descriptions will be completely suppressed.
+
+REPEAT_BRIEF = YES
+
+# This tag implements a quasi-intelligent brief description abbreviator
+# that is used to form the text in various listings. Each string
+# in this list, if found as the leading text of the brief description, will be
+# stripped from the text and the result after processing the whole list, is used
+# as the annotated text. Otherwise, the brief description is used as-is. If left
+# blank, the following values are used ("$name" is automatically replaced with the
+# name of the entity): "The $name class" "The $name widget" "The $name file"
+# "is" "provides" "specifies" "contains" "represents" "a" "an" "the"
+
+ABBREVIATE_BRIEF =
+
+# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
+# Doxygen will generate a detailed section even if there is only a brief
+# description.
+
+ALWAYS_DETAILED_SEC = NO
+
+# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all inherited
+# members of a class in the documentation of that class as if those members were
+# ordinary class members. Constructors, destructors and assignment operators of
+# the base classes will not be shown.
+
+INLINE_INHERITED_MEMB = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full
+# path before files name in the file list and in the header files. If set
+# to NO the shortest path that makes the file name unique will be used.
+
+FULL_PATH_NAMES = NO
+
+# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
+# can be used to strip a user-defined part of the path. Stripping is
+# only done if one of the specified strings matches the left-hand part of
+# the path. It is allowed to use relative paths in the argument list.
+
+STRIP_FROM_PATH =
+
+# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter
+# (but less readable) file names. This can be useful is your file systems
+# doesn't support long names like on DOS, Mac, or CD-ROM.
+
+SHORT_NAMES = NO
+
+# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen
+# will interpret the first line (until the first dot) of a JavaDoc-style
+# comment as the brief description. If set to NO, the JavaDoc
+# comments will behave just like the Qt-style comments (thus requiring an
+# explicit @brief command for a brief description.
+
+JAVADOC_AUTOBRIEF = NO
+
+# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen
+# treat a multi-line C++ special comment block (i.e. a block of //! or ///
+# comments) as a brief description. This used to be the default behaviour.
+# The new default is to treat a multi-line C++ comment block as a detailed
+# description. Set this tag to YES if you prefer the old behaviour instead.
+
+MULTILINE_CPP_IS_BRIEF = NO
+
+# If the DETAILS_AT_TOP tag is set to YES then Doxygen
+# will output the detailed description near the top, like JavaDoc.
+# If set to NO, the detailed description appears after the member
+# documentation.
+
+DETAILS_AT_TOP = NO
+
+# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented
+# member inherits the documentation from any documented member that it
+# re-implements.
+
+INHERIT_DOCS = YES
+
+# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
+# tag is set to YES, then doxygen will reuse the documentation of the first
+# member in the group (if any) for the other members of the group. By default
+# all members of a group must be documented explicitly.
+
+DISTRIBUTE_GROUP_DOC = NO
+
+# The TAB_SIZE tag can be used to set the number of spaces in a tab.
+# Doxygen uses this value to replace tabs by spaces in code fragments.
+
+TAB_SIZE = 8
+
+# This tag can be used to specify a number of aliases that acts
+# as commands in the documentation. An alias has the form "name=value".
+# For example adding "sideeffect=\par Side Effects:\n" will allow you to
+# put the command \sideeffect (or @sideeffect) in the documentation, which
+# will result in a user-defined paragraph with heading "Side Effects:".
+# You can put \n's in the value part of an alias to insert newlines.
+
+ALIASES =
+
+# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
+# only. Doxygen will then generate output that is more tailored for C.
+# For instance, some of the names that are used will be different. The list
+# of all members will be omitted, etc.
+
+OPTIMIZE_OUTPUT_FOR_C = YES
+
+# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java sources
+# only. Doxygen will then generate output that is more tailored for Java.
+# For instance, namespaces will be presented as packages, qualified scopes
+# will look different, etc.
+
+OPTIMIZE_OUTPUT_JAVA = NO
+
+# Set the SUBGROUPING tag to YES (the default) to allow class member groups of
+# the same type (for instance a group of public functions) to be put as a
+# subgroup of that type (e.g. under the Public Functions section). Set it to
+# NO to prevent subgrouping. Alternatively, this can be done per class using
+# the \nosubgrouping command.
+
+SUBGROUPING = YES
+
+#---------------------------------------------------------------------------
+# Build related configuration options
+#---------------------------------------------------------------------------
+
+# If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in
+# documentation are documented, even if no documentation was available.
+# Private class members and static file members will be hidden unless
+# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES
+
+EXTRACT_ALL = NO
+
+# If the EXTRACT_PRIVATE tag is set to YES all private members of a class
+# will be included in the documentation.
+
+EXTRACT_PRIVATE = NO
+
+# If the EXTRACT_STATIC tag is set to YES all static members of a file
+# will be included in the documentation.
+
+EXTRACT_STATIC = NO
+
+# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs)
+# defined locally in source files will be included in the documentation.
+# If set to NO only classes defined in header files are included.
+
+EXTRACT_LOCAL_CLASSES = YES
+
+# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all
+# undocumented members of documented classes, files or namespaces.
+# If set to NO (the default) these members will be included in the
+# various overviews, but no documentation section is generated.
+# This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_MEMBERS = NO
+
+# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all
+# undocumented classes that are normally visible in the class hierarchy.
+# If set to NO (the default) these classes will be included in the various
+# overviews. This option has no effect if EXTRACT_ALL is enabled.
+
+HIDE_UNDOC_CLASSES = NO
+
+# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all
+# friend (class|struct|union) declarations.
+# If set to NO (the default) these declarations will be included in the
+# documentation.
+
+HIDE_FRIEND_COMPOUNDS = NO
+
+# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any
+# documentation blocks found inside the body of a function.
+# If set to NO (the default) these blocks will be appended to the
+# function's detailed documentation block.
+
+HIDE_IN_BODY_DOCS = NO
+
+# The INTERNAL_DOCS tag determines if documentation
+# that is typed after a \internal command is included. If the tag is set
+# to NO (the default) then the documentation will be excluded.
+# Set it to YES to include the internal documentation.
+
+INTERNAL_DOCS = NO
+
+# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate
+# file names in lower-case letters. If set to YES upper-case letters are also
+# allowed. This is useful if you have classes or files whose names only differ
+# in case and if your file system supports case sensitive file names. Windows
+# users are advised to set this option to NO.
+
+CASE_SENSE_NAMES = YES
+
+# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen
+# will show members with their full class and namespace scopes in the
+# documentation. If set to YES the scope will be hidden.
+
+HIDE_SCOPE_NAMES = NO
+
+# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen
+# will put a list of the files that are included by a file in the documentation
+# of that file.
+
+SHOW_INCLUDE_FILES = YES
+
+# If the INLINE_INFO tag is set to YES (the default) then a tag [inline]
+# is inserted in the documentation for inline members.
+
+INLINE_INFO = YES
+
+# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen
+# will sort the (detailed) documentation of file and class members
+# alphabetically by member name. If set to NO the members will appear in
+# declaration order.
+
+SORT_MEMBER_DOCS = YES
+
+# The GENERATE_TODOLIST tag can be used to enable (YES) or
+# disable (NO) the todo list. This list is created by putting \todo
+# commands in the documentation.
+
+GENERATE_TODOLIST = YES
+
+# The GENERATE_TESTLIST tag can be used to enable (YES) or
+# disable (NO) the test list. This list is created by putting \test
+# commands in the documentation.
+
+GENERATE_TESTLIST = YES
+
+# The GENERATE_BUGLIST tag can be used to enable (YES) or
+# disable (NO) the bug list. This list is created by putting \bug
+# commands in the documentation.
+
+GENERATE_BUGLIST = YES
+
+# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or
+# disable (NO) the deprecated list. This list is created by putting
+# \deprecated commands in the documentation.
+
+GENERATE_DEPRECATEDLIST= YES
+
+# The ENABLED_SECTIONS tag can be used to enable conditional
+# documentation sections, marked by \if sectionname ... \endif.
+
+ENABLED_SECTIONS =
+
+# The MAX_INITIALIZER_LINES tag determines the maximum number of lines
+# the initial value of a variable or define consists of for it to appear in
+# the documentation. If the initializer consists of more lines than specified
+# here it will be hidden. Use a value of 0 to hide initializers completely.
+# The appearance of the initializer of individual variables and defines in the
+# documentation can be controlled using \showinitializer or \hideinitializer
+# command in the documentation regardless of this setting.
+
+MAX_INITIALIZER_LINES = 30
+
+# Set the SHOW_USED_FILES tag to NO to disable the list of files generated
+# at the bottom of the documentation of classes and structs. If set to YES the
+# list will mention the files that were used to generate the documentation.
+
+SHOW_USED_FILES = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to warning and progress messages
+#---------------------------------------------------------------------------
+
+# The QUIET tag can be used to turn on/off the messages that are generated
+# by doxygen. Possible values are YES and NO. If left blank NO is used.
+
+QUIET = NO
+
+# The WARNINGS tag can be used to turn on/off the warning messages that are
+# generated by doxygen. Possible values are YES and NO. If left blank
+# NO is used.
+
+WARNINGS = YES
+
+# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings
+# for undocumented members. If EXTRACT_ALL is set to YES then this flag will
+# automatically be disabled.
+
+WARN_IF_UNDOCUMENTED = YES
+
+# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for
+# potential errors in the documentation, such as not documenting some
+# parameters in a documented function, or documenting parameters that
+# don't exist or using markup commands wrongly.
+
+WARN_IF_DOC_ERROR = YES
+
+# The WARN_FORMAT tag determines the format of the warning messages that
+# doxygen can produce. The string should contain the $file, $line, and $text
+# tags, which will be replaced by the file and line number from which the
+# warning originated and the warning text.
+
+WARN_FORMAT = "$file:$line: $text"
+
+# The WARN_LOGFILE tag can be used to specify a file to which warning
+# and error messages should be written. If left blank the output is written
+# to stderr.
+
+WARN_LOGFILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the input files
+#---------------------------------------------------------------------------
+
+# The INPUT tag can be used to specify the files and/or directories that contain
+# documented source files. You may enter file names like "myfile.cpp" or
+# directories like "/usr/src/myproject". Separate the files or directories
+# with spaces.
+
+INPUT =
+
+# If the value of the INPUT tag contains directories, you can use the
+# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank the following patterns are tested:
+# *.c *.cc *.cxx *.cpp *.c++ *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh *.hxx *.hpp
+# *.h++ *.idl *.odl *.cs *.php *.php3 *.inc
+
+FILE_PATTERNS =
+
+# The RECURSIVE tag can be used to turn specify whether or not subdirectories
+# should be searched for input files as well. Possible values are YES and NO.
+# If left blank NO is used.
+
+RECURSIVE = NO
+
+# The EXCLUDE tag can be used to specify files and/or directories that should
+# excluded from the INPUT source files. This way you can easily exclude a
+# subdirectory from a directory tree whose root is specified with the INPUT tag.
+
+EXCLUDE =
+
+# The EXCLUDE_SYMLINKS tag can be used select whether or not files or directories
+# that are symbolic links (a Unix filesystem feature) are excluded from the input.
+
+EXCLUDE_SYMLINKS = NO
+
+# If the value of the INPUT tag contains directories, you can use the
+# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
+# certain files from those directories.
+
+EXCLUDE_PATTERNS =
+
+# The EXAMPLE_PATH tag can be used to specify one or more files or
+# directories that contain example code fragments that are included (see
+# the \include command).
+
+EXAMPLE_PATH =
+
+# If the value of the EXAMPLE_PATH tag contains directories, you can use the
+# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp
+# and *.h) to filter out the source-files in the directories. If left
+# blank all files are included.
+
+EXAMPLE_PATTERNS =
+
+# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
+# searched for input files to be used with the \include or \dontinclude
+# commands irrespective of the value of the RECURSIVE tag.
+# Possible values are YES and NO. If left blank NO is used.
+
+EXAMPLE_RECURSIVE = NO
+
+# The IMAGE_PATH tag can be used to specify one or more files or
+# directories that contain image that are included in the documentation (see
+# the \image command).
+
+IMAGE_PATH =
+
+# The INPUT_FILTER tag can be used to specify a program that doxygen should
+# invoke to filter for each input file. Doxygen will invoke the filter program
+# by executing (via popen()) the command <filter> <input-file>, where <filter>
+# is the value of the INPUT_FILTER tag, and <input-file> is the name of an
+# input file. Doxygen will then use the output that the filter program writes
+# to standard output.
+
+INPUT_FILTER =
+
+# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
+# INPUT_FILTER) will be used to filter the input files when producing source
+# files to browse (i.e. when SOURCE_BROWSER is set to YES).
+
+FILTER_SOURCE_FILES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to source browsing
+#---------------------------------------------------------------------------
+
+# If the SOURCE_BROWSER tag is set to YES then a list of source files will
+# be generated. Documented entities will be cross-referenced with these sources.
+# Note: To get rid of all source code in the generated output, make sure also
+# VERBATIM_HEADERS is set to NO.
+
+SOURCE_BROWSER = NO
+
+# Setting the INLINE_SOURCES tag to YES will include the body
+# of functions and classes directly in the documentation.
+
+INLINE_SOURCES = NO
+
+# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct
+# doxygen to hide any special comment blocks from generated source code
+# fragments. Normal C and C++ comments will always remain visible.
+
+STRIP_CODE_COMMENTS = YES
+
+# If the REFERENCED_BY_RELATION tag is set to YES (the default)
+# then for each documented function all documented
+# functions referencing it will be listed.
+
+REFERENCED_BY_RELATION = YES
+
+# If the REFERENCES_RELATION tag is set to YES (the default)
+# then for each documented function all documented entities
+# called/used by that function will be listed.
+
+REFERENCES_RELATION = YES
+
+# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen
+# will generate a verbatim copy of the header file for each class for
+# which an include is specified. Set to NO to disable this.
+
+VERBATIM_HEADERS = YES
+
+#---------------------------------------------------------------------------
+# configuration options related to the alphabetical class index
+#---------------------------------------------------------------------------
+
+# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index
+# of all compounds will be generated. Enable this if the project
+# contains a lot of classes, structs, unions or interfaces.
+
+ALPHABETICAL_INDEX = NO
+
+# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then
+# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns
+# in which this list will be split (can be a number in the range [1..20])
+
+COLS_IN_ALPHA_INDEX = 5
+
+# In case all classes in a project start with a common prefix, all
+# classes will be put under the same header in the alphabetical index.
+# The IGNORE_PREFIX tag can be used to specify one or more prefixes that
+# should be ignored while generating the index headers.
+
+IGNORE_PREFIX =
+
+#---------------------------------------------------------------------------
+# configuration options related to the HTML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_HTML tag is set to YES (the default) Doxygen will
+# generate HTML output.
+
+GENERATE_HTML = YES
+
+# The HTML_OUTPUT tag is used to specify where the HTML docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `html' will be used as the default path.
+
+HTML_OUTPUT = html
+
+# The HTML_FILE_EXTENSION tag can be used to specify the file extension for
+# each generated HTML page (for example: .htm,.php,.asp). If it is left blank
+# doxygen will generate files with .html extension.
+
+HTML_FILE_EXTENSION = .html
+
+# The HTML_HEADER tag can be used to specify a personal HTML header for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard header.
+
+HTML_HEADER =
+
+# The HTML_FOOTER tag can be used to specify a personal HTML footer for
+# each generated HTML page. If it is left blank doxygen will generate a
+# standard footer.
+
+HTML_FOOTER =
+
+# The HTML_STYLESHEET tag can be used to specify a user-defined cascading
+# style sheet that is used by each HTML page. It can be used to
+# fine-tune the look of the HTML output. If the tag is left blank doxygen
+# will generate a default style sheet. Note that doxygen will try to copy
+# the style sheet file to the HTML output directory, so don't put your own
+# stylesheet in the HTML output directory as well, or it will be erased!
+
+HTML_STYLESHEET =
+
+# If the HTML_ALIGN_MEMBERS tag is set to YES, the members of classes,
+# files or namespaces will be aligned in HTML using tables. If set to
+# NO a bullet list will be used.
+
+HTML_ALIGN_MEMBERS = YES
+
+# If the GENERATE_HTMLHELP tag is set to YES, additional index files
+# will be generated that can be used as input for tools like the
+# Microsoft HTML help workshop to generate a compressed HTML help file (.chm)
+# of the generated HTML documentation.
+
+GENERATE_HTMLHELP = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can
+# be used to specify the file name of the resulting .chm file. You
+# can add a path in front of the file if the result should not be
+# written to the html output directory.
+
+CHM_FILE =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can
+# be used to specify the location (absolute path including file name) of
+# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run
+# the HTML help compiler on the generated index.hhp.
+
+HHC_LOCATION =
+
+# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag
+# controls if a separate .chi index file is generated (YES) or that
+# it should be included in the master .chm file (NO).
+
+GENERATE_CHI = NO
+
+# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag
+# controls whether a binary table of contents is generated (YES) or a
+# normal table of contents (NO) in the .chm file.
+
+BINARY_TOC = NO
+
+# The TOC_EXPAND flag can be set to YES to add extra items for group members
+# to the contents of the HTML help documentation and to the tree view.
+
+TOC_EXPAND = NO
+
+# The DISABLE_INDEX tag can be used to turn on/off the condensed index at
+# top of each HTML page. The value NO (the default) enables the index and
+# the value YES disables it.
+
+DISABLE_INDEX = NO
+
+# This tag can be used to set the number of enum values (range [1..20])
+# that doxygen will group on one line in the generated HTML documentation.
+
+ENUM_VALUES_PER_LINE = 4
+
+# If the GENERATE_TREEVIEW tag is set to YES, a side panel will be
+# generated containing a tree-like index structure (just like the one that
+# is generated for HTML Help). For this to work a browser that supports
+# JavaScript, DHTML, CSS and frames is required (for instance Mozilla 1.0+,
+# Netscape 6.0+, Internet explorer 5.0+, or Konqueror). Windows users are
+# probably better off using the HTML help feature.
+
+GENERATE_TREEVIEW = NO
+
+# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be
+# used to set the initial width (in pixels) of the frame in which the tree
+# is shown.
+
+TREEVIEW_WIDTH = 250
+
+#---------------------------------------------------------------------------
+# configuration options related to the LaTeX output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_LATEX tag is set to YES (the default) Doxygen will
+# generate Latex output.
+
+GENERATE_LATEX = YES
+
+# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `latex' will be used as the default path.
+
+LATEX_OUTPUT = latex
+
+# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
+# invoked. If left blank `latex' will be used as the default command name.
+
+LATEX_CMD_NAME = latex
+
+# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to
+# generate index for LaTeX. If left blank `makeindex' will be used as the
+# default command name.
+
+MAKEINDEX_CMD_NAME = makeindex
+
+# If the COMPACT_LATEX tag is set to YES Doxygen generates more compact
+# LaTeX documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_LATEX = NO
+
+# The PAPER_TYPE tag can be used to set the paper type that is used
+# by the printer. Possible values are: a4, a4wide, letter, legal and
+# executive. If left blank a4wide will be used.
+
+PAPER_TYPE = a4wide
+
+# The EXTRA_PACKAGES tag can be to specify one or more names of LaTeX
+# packages that should be included in the LaTeX output.
+
+EXTRA_PACKAGES =
+
+# The LATEX_HEADER tag can be used to specify a personal LaTeX header for
+# the generated latex document. The header should contain everything until
+# the first chapter. If it is left blank doxygen will generate a
+# standard header. Notice: only use this tag if you know what you are doing!
+
+LATEX_HEADER =
+
+# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated
+# is prepared for conversion to pdf (using ps2pdf). The pdf file will
+# contain links (just like the HTML output) instead of page references
+# This makes the output suitable for online browsing using a pdf viewer.
+
+PDF_HYPERLINKS = NO
+
+# If the USE_PDFLATEX tag is set to YES, pdflatex will be used instead of
+# plain latex in the generated Makefile. Set this option to YES to get a
+# higher quality PDF documentation.
+
+USE_PDFLATEX = NO
+
+# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \\batchmode.
+# command to the generated LaTeX files. This will instruct LaTeX to keep
+# running if errors occur, instead of asking the user for help.
+# This option is also used when generating formulas in HTML.
+
+LATEX_BATCHMODE = NO
+
+# If LATEX_HIDE_INDICES is set to YES then doxygen will not
+# include the index chapters (such as File Index, Compound Index, etc.)
+# in the output.
+
+LATEX_HIDE_INDICES = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the RTF output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_RTF tag is set to YES Doxygen will generate RTF output
+# The RTF output is optimized for Word 97 and may not look very pretty with
+# other RTF readers or editors.
+
+GENERATE_RTF = NO
+
+# The RTF_OUTPUT tag is used to specify where the RTF docs will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `rtf' will be used as the default path.
+
+RTF_OUTPUT = rtf
+
+# If the COMPACT_RTF tag is set to YES Doxygen generates more compact
+# RTF documents. This may be useful for small projects and may help to
+# save some trees in general.
+
+COMPACT_RTF = NO
+
+# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated
+# will contain hyperlink fields. The RTF file will
+# contain links (just like the HTML output) instead of page references.
+# This makes the output suitable for online browsing using WORD or other
+# programs which support those fields.
+# Note: wordpad (write) and others do not support links.
+
+RTF_HYPERLINKS = NO
+
+# Load stylesheet definitions from file. Syntax is similar to doxygen's
+# config file, i.e. a series of assignments. You only have to provide
+# replacements, missing definitions are set to their default value.
+
+RTF_STYLESHEET_FILE =
+
+# Set optional variables used in the generation of an rtf document.
+# Syntax is similar to doxygen's config file.
+
+RTF_EXTENSIONS_FILE =
+
+#---------------------------------------------------------------------------
+# configuration options related to the man page output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_MAN tag is set to YES (the default) Doxygen will
+# generate man pages
+
+GENERATE_MAN = NO
+
+# The MAN_OUTPUT tag is used to specify where the man pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `man' will be used as the default path.
+
+MAN_OUTPUT = man
+
+# The MAN_EXTENSION tag determines the extension that is added to
+# the generated man pages (default is the subroutine's section .3)
+
+MAN_EXTENSION = .3
+
+# If the MAN_LINKS tag is set to YES and Doxygen generates man output,
+# then it will generate one additional man file for each entity
+# documented in the real man page(s). These additional files
+# only source the real man page, but without them the man command
+# would be unable to find the correct page. The default is NO.
+
+MAN_LINKS = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the XML output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_XML tag is set to YES Doxygen will
+# generate an XML file that captures the structure of
+# the code including all documentation.
+
+GENERATE_XML = NO
+
+# The XML_OUTPUT tag is used to specify where the XML pages will be put.
+# If a relative path is entered the value of OUTPUT_DIRECTORY will be
+# put in front of it. If left blank `xml' will be used as the default path.
+
+XML_OUTPUT = xml
+
+# The XML_SCHEMA tag can be used to specify an XML schema,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_SCHEMA =
+
+# The XML_DTD tag can be used to specify an XML DTD,
+# which can be used by a validating XML parser to check the
+# syntax of the XML files.
+
+XML_DTD =
+
+# If the XML_PROGRAMLISTING tag is set to YES Doxygen will
+# dump the program listings (including syntax highlighting
+# and cross-referencing information) to the XML output. Note that
+# enabling this will significantly increase the size of the XML output.
+
+XML_PROGRAMLISTING = YES
+
+#---------------------------------------------------------------------------
+# configuration options for the AutoGen Definitions output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_AUTOGEN_DEF tag is set to YES Doxygen will
+# generate an AutoGen Definitions (see autogen.sf.net) file
+# that captures the structure of the code including all
+# documentation. Note that this feature is still experimental
+# and incomplete at the moment.
+
+GENERATE_AUTOGEN_DEF = NO
+
+#---------------------------------------------------------------------------
+# configuration options related to the Perl module output
+#---------------------------------------------------------------------------
+
+# If the GENERATE_PERLMOD tag is set to YES Doxygen will
+# generate a Perl module file that captures the structure of
+# the code including all documentation. Note that this
+# feature is still experimental and incomplete at the
+# moment.
+
+GENERATE_PERLMOD = NO
+
+# If the PERLMOD_LATEX tag is set to YES Doxygen will generate
+# the necessary Makefile rules, Perl scripts and LaTeX code to be able
+# to generate PDF and DVI output from the Perl module output.
+
+PERLMOD_LATEX = NO
+
+# If the PERLMOD_PRETTY tag is set to YES the Perl module output will be
+# nicely formatted so it can be parsed by a human reader. This is useful
+# if you want to understand what is going on. On the other hand, if this
+# tag is set to NO the size of the Perl module output will be much smaller
+# and Perl will parse it just the same.
+
+PERLMOD_PRETTY = YES
+
+# The names of the make variables in the generated doxyrules.make file
+# are prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX.
+# This is useful so different doxyrules.make files included by the same
+# Makefile don't overwrite each other's variables.
+
+PERLMOD_MAKEVAR_PREFIX =
+
+#---------------------------------------------------------------------------
+# Configuration options related to the preprocessor
+#---------------------------------------------------------------------------
+
+# If the ENABLE_PREPROCESSING tag is set to YES (the default) Doxygen will
+# evaluate all C-preprocessor directives found in the sources and include
+# files.
+
+ENABLE_PREPROCESSING = YES
+
+# If the MACRO_EXPANSION tag is set to YES Doxygen will expand all macro
+# names in the source code. If set to NO (the default) only conditional
+# compilation will be performed. Macro expansion can be done in a controlled
+# way by setting EXPAND_ONLY_PREDEF to YES.
+
+MACRO_EXPANSION = NO
+
+# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES
+# then the macro expansion is limited to the macros specified with the
+# PREDEFINED and EXPAND_AS_PREDEFINED tags.
+
+EXPAND_ONLY_PREDEF = NO
+
+# If the SEARCH_INCLUDES tag is set to YES (the default) the includes files
+# in the INCLUDE_PATH (see below) will be search if a #include is found.
+
+SEARCH_INCLUDES = YES
+
+# The INCLUDE_PATH tag can be used to specify one or more directories that
+# contain include files that are not input files but should be processed by
+# the preprocessor.
+
+INCLUDE_PATH =
+
+# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
+# patterns (like *.h and *.hpp) to filter out the header-files in the
+# directories. If left blank, the patterns specified with FILE_PATTERNS will
+# be used.
+
+INCLUDE_FILE_PATTERNS =
+
+# The PREDEFINED tag can be used to specify one or more macro names that
+# are defined before the preprocessor is started (similar to the -D option of
+# gcc). The argument of the tag is a list of macros of the form: name
+# or name=definition (no spaces). If the definition and the = are
+# omitted =1 is assumed.
+
+PREDEFINED =
+
+# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then
+# this tag can be used to specify a list of macro names that should be expanded.
+# The macro definition that is found in the sources will be used.
+# Use the PREDEFINED tag if you want to use a different macro definition.
+
+EXPAND_AS_DEFINED =
+
+# If the SKIP_FUNCTION_MACROS tag is set to YES (the default) then
+# doxygen's preprocessor will remove all function-like macros that are alone
+# on a line, have an all uppercase name, and do not end with a semicolon. Such
+# function macros are typically used for boiler-plate code, and will confuse the
+# parser if not removed.
+
+SKIP_FUNCTION_MACROS = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to external references
+#---------------------------------------------------------------------------
+
+# The TAGFILES option can be used to specify one or more tagfiles.
+# Optionally an initial location of the external documentation
+# can be added for each tagfile. The format of a tag file without
+# this location is as follows:
+# TAGFILES = file1 file2 ...
+# Adding location for the tag files is done as follows:
+# TAGFILES = file1=loc1 "file2 = loc2" ...
+# where "loc1" and "loc2" can be relative or absolute paths or
+# URLs. If a location is present for each tag, the installdox tool
+# does not have to be run to correct the links.
+# Note that each tag file must have a unique name
+# (where the name does NOT include the path)
+# If a tag file is not located in the directory in which doxygen
+# is run, you must also specify the path to the tagfile here.
+
+TAGFILES =
+
+# When a file name is specified after GENERATE_TAGFILE, doxygen will create
+# a tag file that is based on the input files it reads.
+
+GENERATE_TAGFILE =
+
+# If the ALLEXTERNALS tag is set to YES all external classes will be listed
+# in the class index. If set to NO only the inherited external classes
+# will be listed.
+
+ALLEXTERNALS = NO
+
+# If the EXTERNAL_GROUPS tag is set to YES all external groups will be listed
+# in the modules index. If set to NO, only the current project's groups will
+# be listed.
+
+EXTERNAL_GROUPS = YES
+
+# The PERL_PATH should be the absolute path and name of the perl script
+# interpreter (i.e. the result of `which perl').
+
+PERL_PATH = /usr/bin/perl
+
+#---------------------------------------------------------------------------
+# Configuration options related to the dot tool
+#---------------------------------------------------------------------------
+
+# If the CLASS_DIAGRAMS tag is set to YES (the default) Doxygen will
+# generate a inheritance diagram (in HTML, RTF and LaTeX) for classes with base or
+# super classes. Setting the tag to NO turns the diagrams off. Note that this
+# option is superseded by the HAVE_DOT option below. This is only a fallback. It is
+# recommended to install and use dot, since it yields more powerful graphs.
+
+CLASS_DIAGRAMS = YES
+
+# If set to YES, the inheritance and collaboration graphs will hide
+# inheritance and usage relations if the target is undocumented
+# or is not a class.
+
+HIDE_UNDOC_RELATIONS = YES
+
+# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
+# available from the path. This tool is part of Graphviz, a graph visualization
+# toolkit from AT&T and Lucent Bell Labs. The other options in this section
+# have no effect if this option is set to NO (the default)
+
+HAVE_DOT = NO
+
+# If the CLASS_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect inheritance relations. Setting this tag to YES will force the
+# the CLASS_DIAGRAMS tag to NO.
+
+CLASS_GRAPH = YES
+
+# If the COLLABORATION_GRAPH and HAVE_DOT tags are set to YES then doxygen
+# will generate a graph for each documented class showing the direct and
+# indirect implementation dependencies (inheritance, containment, and
+# class references variables) of the class with other documented classes.
+
+COLLABORATION_GRAPH = YES
+
+# If the UML_LOOK tag is set to YES doxygen will generate inheritance and
+# collaboration diagrams in a style similar to the OMG's Unified Modeling
+# Language.
+
+UML_LOOK = NO
+
+# If set to YES, the inheritance and collaboration graphs will show the
+# relations between templates and their instances.
+
+TEMPLATE_RELATIONS = NO
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDE_GRAPH, and HAVE_DOT
+# tags are set to YES then doxygen will generate a graph for each documented
+# file showing the direct and indirect include dependencies of the file with
+# other documented files.
+
+INCLUDE_GRAPH = YES
+
+# If the ENABLE_PREPROCESSING, SEARCH_INCLUDES, INCLUDED_BY_GRAPH, and
+# HAVE_DOT tags are set to YES then doxygen will generate a graph for each
+# documented header file showing the documented files that directly or
+# indirectly include this file.
+
+INCLUDED_BY_GRAPH = YES
+
+# If the CALL_GRAPH and HAVE_DOT tags are set to YES then doxygen will
+# generate a call dependency graph for every global function or class method.
+# Note that enabling this option will significantly increase the time of a run.
+# So in most cases it will be better to enable call graphs for selected
+# functions only using the \callgraph command.
+
+CALL_GRAPH = NO
+
+# If the GRAPHICAL_HIERARCHY and HAVE_DOT tags are set to YES then doxygen
+# will graphical hierarchy of all classes instead of a textual one.
+
+GRAPHICAL_HIERARCHY = YES
+
+# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
+# generated by dot. Possible values are png, jpg, or gif
+# If left blank png will be used.
+
+DOT_IMAGE_FORMAT = png
+
+# The tag DOT_PATH can be used to specify the path where the dot tool can be
+# found. If left blank, it is assumed the dot tool can be found on the path.
+
+DOT_PATH =
+
+# The DOTFILE_DIRS tag can be used to specify one or more directories that
+# contain dot files that are included in the documentation (see the
+# \dotfile command).
+
+DOTFILE_DIRS =
+
+# The MAX_DOT_GRAPH_WIDTH tag can be used to set the maximum allowed width
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_WIDTH = 1024
+
+# The MAX_DOT_GRAPH_HEIGHT tag can be used to set the maximum allows height
+# (in pixels) of the graphs generated by dot. If a graph becomes larger than
+# this value, doxygen will try to truncate the graph, so that it fits within
+# the specified constraint. Beware that most browsers cannot cope with very
+# large images.
+
+MAX_DOT_GRAPH_HEIGHT = 1024
+
+# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the
+# graphs generated by dot. A depth value of 3 means that only nodes reachable
+# from the root by following a path via at most 3 edges will be shown. Nodes that
+# lay further from the root node will be omitted. Note that setting this option to
+# 1 or 2 may greatly reduce the computation time needed for large code bases. Also
+# note that a graph may be further truncated if the graph's image dimensions are
+# not sufficient to fit the graph (see MAX_DOT_GRAPH_WIDTH and MAX_DOT_GRAPH_HEIGHT).
+# If 0 is used for the depth value (the default), the graph is not depth-constrained.
+
+MAX_DOT_GRAPH_DEPTH = 0
+
+# If the GENERATE_LEGEND tag is set to YES (the default) Doxygen will
+# generate a legend page explaining the meaning of the various boxes and
+# arrows in the dot generated graphs.
+
+GENERATE_LEGEND = YES
+
+# If the DOT_CLEANUP tag is set to YES (the default) Doxygen will
+# remove the intermediate dot files that are used to generate
+# the various graphs.
+
+DOT_CLEANUP = YES
+
+#---------------------------------------------------------------------------
+# Configuration::addtions related to the search engine
+#---------------------------------------------------------------------------
+
+# The SEARCHENGINE tag specifies whether or not a search engine should be
+# used. If set to NO the values of all tags below this one will be ignored.
+
+SEARCHENGINE = NO
diff --git a/main/minimime/Make.conf b/main/minimime/Make.conf
new file mode 100644
index 000000000..de149932a
--- /dev/null
+++ b/main/minimime/Make.conf
@@ -0,0 +1,7 @@
+CC=gcc
+PREFIX=/usr
+LIBNAME=libmmime.so.0.0
+HAVE_STRLCAT=
+HAVE_STRLCPY=
+INSTALL=/usr/bin/install
+HAVE_DEBUG=1
diff --git a/main/minimime/Makefile b/main/minimime/Makefile
new file mode 100644
index 000000000..4351afd2f
--- /dev/null
+++ b/main/minimime/Makefile
@@ -0,0 +1,60 @@
+#
+# Asterisk -- A telephony toolkit for Linux.
+#
+# Makefile for resource modules
+#
+# Copyright (C) 2007, Digium, Inc.
+#
+# This program is free software, distributed under the terms of
+# the GNU General Public License
+#
+
+-include $(ASTTOPDIR)/menuselect.makeopts $(ASTTOPDIR)/menuselect.makedeps
+
+include $(ASTTOPDIR)/Makefile.moddir_rules
+
+LIBMMIME:=libmmime.a
+MM_SRCS= \
+ mimeparser.tab.c \
+ mimeparser.yy.c \
+ mm_init.c \
+ mm_base64.c \
+ mm_codecs.c \
+ mm_contenttype.c \
+ mm_context.c \
+ mm_envelope.c \
+ mm_error.c \
+ mm_header.c \
+ mm_mem.c \
+ mm_mimepart.c \
+ mm_mimeutil.c \
+ mm_param.c \
+ mm_parse.c \
+ mm_util.c
+
+MM_OBJS:=$(MM_SRCS:%.c=%.o)
+MM_HDRS:=mm.h mm_util.h
+
+ASTCFLAGS:=$(filter-out -Werror -Wstrict-prototypes -Wmissing-declarations -Wmissing-prototypes,$(ASTCFLAGS))
+
+all: $(LIBMMIME)
+
+$(LIBMMIME): $(MM_OBJS)
+ $(ECHO_PREFIX) echo " [AR] $^ -> $@"
+ $(CMD_PREFIX) $(AR) cr $@ $^
+ $(CMD_PREFIX) $(RANLIB) $@
+
+#mimeparser.yy.c: mimeparser.l
+# flex -Pmimeparser_yy -omimeparser.yy.c mimeparser.l
+
+#mimeparser.tab.c: mimeparser.y
+# bison -d -pmimeparser_yy -omimeparser.tab.c mimeparser.y
+
+clean::
+ rm -f $(LIBMMIME) *.o
+
+.PHONY: clean all
+
+ifneq ($(wildcard .*.d),)
+ include .*.d
+endif
diff --git a/main/minimime/mimeparser.h b/main/minimime/mimeparser.h
new file mode 100644
index 000000000..3d8da816f
--- /dev/null
+++ b/main/minimime/mimeparser.h
@@ -0,0 +1,67 @@
+#ifndef _MIMEPARSER_H_INCLUDED
+#define _MIMEPARSER_H_INCLUDED
+
+#include "mm.h"
+
+struct s_position
+{
+ size_t opaque_start;
+ size_t start;
+ size_t end;
+};
+
+struct lexer_state
+{
+ int header_state;
+ int lineno;
+ size_t current_pos;
+ int condition;
+
+ int is_envelope;
+
+ size_t message_len;
+ size_t buffer_length;
+
+ /* temporary marker variables */
+ size_t body_opaque_start;
+ size_t body_start;
+ size_t body_end;
+ size_t preamble_start;
+ size_t preamble_end;
+ size_t postamble_start;
+ size_t postamble_end;
+
+ char *boundary_string;
+ char *endboundary_string;
+ char *message_buffer;
+};
+
+
+struct parser_state
+{
+ MM_CTX *ctx;
+ struct mm_mimepart *envelope;
+ struct mm_mimepart *temppart;
+ struct mm_mimepart *current_mimepart;
+ struct mm_content *ctype;
+ int parsemode;
+ int have_contenttype;
+ int debug;
+ int mime_parts;
+ struct lexer_state lstate;
+};
+
+
+#include "mimeparser.tab.h"
+
+/**
+ * Prototypes for functions used by the parser routines
+ */
+int count_lines(char *);
+int dprintf2(struct parser_state *, const char *, ...);
+int mimeparser_yyparse(struct parser_state *, void *);
+int mimeparser_yylex(YYSTYPE *, void *);
+int mimeparser_yyerror(struct parser_state *, void *, const char *);
+
+
+#endif /* ! _MIMEPARSER_H_INCLUDED */
diff --git a/main/minimime/mimeparser.l b/main/minimime/mimeparser.l
new file mode 100644
index 000000000..d45295f13
--- /dev/null
+++ b/main/minimime/mimeparser.l
@@ -0,0 +1,483 @@
+%{
+/*
+ * Copyright (c) 2004 Jann Fischer. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/**
+ * This is a lexer file for parsing MIME compatible messages. It is intended
+ * to satisfy at least RFC 2045 (Format of Internet Message Bodies). It still
+ * has quite a few problems:
+ *
+ * - The parsing could probably be done in a more elegant way
+ * - I don't know what performance impact REJECT has on the parser
+ */
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "mimeparser.h"
+#include "mimeparser.tab.h"
+
+#define NAMEOF(v) #v
+/* BC() is a debug wrapper for lex' BEGIN() macro */
+#define BC(x) do { \
+ struct lexer_state *lstate = yyget_extra(yyscanner); \
+ BEGIN(x); \
+ lstate->condition = x; \
+} while(0);
+
+#define ZERO(x) memset(x, '\0', sizeof(x))
+
+#define PREALLOC_BUFFER 100000
+#undef YY_BUF_SIZE
+#define YY_BUF_SIZE 65536
+
+enum header_states
+{
+ STATE_MAIL = 0,
+ STATE_CTYPE,
+ STATE_CDISP,
+ STATE_CENC,
+ STATE_MIME
+};
+
+
+
+%}
+
+%option reentrant
+%option yylineno
+%option bison-bridge
+
+%s headers
+%s header
+%s headervalue
+%s tspecialvalue
+%s comment
+%s body
+%s postamble
+%s preamble
+%s boundary
+%s endboundary
+%s endoffile
+
+STRING [a-zA-Z0-9\-\.\_]
+TSPECIAL [a-zA-Z0-9)(<>@,;:/\-.=_\+'? ]
+TSPECIAL_LITE [a-zA-Z0-9)(<>@,-._+'?\[\]]
+
+%%
+
+<INITIAL,headers>^[a-zA-Z]+[a-zA-Z0-9\-\_]* {
+ yylval_param->string=strdup(yytext);
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+ BC(header);
+
+ /* Depending on what header we are processing, we enter a different
+ * state and return a different value.
+ */
+ if (!strcasecmp(yytext, "Content-Type")) {
+ lstate->header_state = STATE_CTYPE;
+ return CONTENTTYPE_HEADER;
+ } else if (!strcasecmp(yytext, "Content-Transfer-Encoding")) {
+ lstate->header_state = STATE_CENC;
+ return CONTENTENCODING_HEADER;
+ } else if (!strcasecmp(yytext, "Content-Disposition")) {
+ lstate->header_state = STATE_CDISP;
+ return CONTENTDISPOSITION_HEADER;
+ } else if (!strcasecmp(yytext, "MIME-Version")) {
+ lstate->header_state = STATE_MAIL;
+ return MIMEVERSION_HEADER;
+ } else {
+ lstate->header_state = STATE_MAIL;
+ return MAIL_HEADER;
+ }
+}
+
+<INITIAL,headers>. {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ /* dprintf2("Unknown header char: %c\n", *yytext); */
+ lstate->current_pos += yyleng;
+ return ANY;
+}
+
+<headers>^(\r\n|\n) {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ lstate->lineno++;
+
+ lstate->current_pos += yyleng;
+
+ /* This marks the end of headers. Depending on whether we are in the
+ * envelope currently we need to parse either a body or the preamble
+ * now.
+ */
+ if (lstate->is_envelope == 0 || lstate->boundary_string == NULL) {
+ BC(body);
+ lstate->body_start = lstate->current_pos;
+ } else {
+ lstate->is_envelope = 0;
+ lstate->preamble_start = lstate->current_pos;
+ BC(preamble);
+ }
+
+ return ENDOFHEADERS;
+}
+
+<header>\: {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ BC(headervalue);
+ lstate->current_pos += yyleng;
+ return COLON;
+}
+
+<header>(\r\n|\n) {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ BC(headers);
+ /* dprintf2("Invalid header, returning EOL\n"); */
+ lstate->current_pos += yyleng;
+ return EOL;
+}
+
+<headervalue>(\n|\r\n)[\ \t]+ {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+}
+
+<headervalue>.+|(.+(\n|\r\n)[\ \t]+.+)+ {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ if (lstate->header_state != STATE_MAIL && lstate->header_state != STATE_CENC) {
+ REJECT;
+ }
+ lstate->current_pos += yyleng;
+ while (*yytext && isspace(*yytext)) yytext++;
+ /* Do we actually have a header value? */
+ if (*yytext == '\0') {
+ yylval_param->string = strdup("");
+ } else {
+ yylval_param->string=strdup(yytext);
+ lstate->lineno += count_lines(yytext);
+ }
+ return WORD;
+}
+
+<headervalue,tspecialvalue>(\r\n|\n) {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ /* marks the end of one header line */
+ lstate->lineno++;
+ BC(headers);
+ lstate->current_pos += yyleng;
+ return EOL;
+}
+
+<headervalue>;|;(\r\n|\n)[\ \t]+ {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ lstate->lineno += count_lines(yytext);
+ lstate->current_pos += yyleng;
+ return SEMICOLON;
+}
+
+<headervalue>\= {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+ return EQUAL;
+}
+
+<headervalue>\" {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ BC(tspecialvalue);
+ lstate->current_pos += yyleng;
+ return *yytext;
+}
+
+<headervalue>{STRING}+|{TSPECIAL_LITE}+ {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ yylval_param->string=strdup(yytext);
+ lstate->lineno += count_lines(yytext);
+ lstate->current_pos += yyleng;
+ return WORD;
+}
+
+<headervalue>[\ |\t]+ {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+}
+
+<tspecialvalue>{TSPECIAL}+ {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ lstate->lineno += count_lines(yytext);
+ yylval_param->string=strdup(yytext);
+ lstate->current_pos += yyleng;
+ return TSPECIAL;
+}
+
+<tspecialvalue>\" {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ BC(headervalue);
+ lstate->current_pos += yyleng;
+ return *yytext;
+}
+
+<body>^\-\-{TSPECIAL}+\-\- {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ /**
+ * Make sure we only catch matching boundaries, and not other lines
+ * that begin and end with two dashes. If we have catched a valid
+ * end boundary, which actually ends a body, we save the current
+ * position, put the token back on the input stream and let the
+ * endboundary condition parse the actual token.
+ */
+ if (lstate->endboundary_string != NULL) {
+ if (strcmp(lstate->endboundary_string, yytext)) {
+ /* dprintf2("YYTEXT != end_boundary: '%s'\n", yytext); */
+ REJECT;
+ } else {
+ lstate->current_pos += yyleng;
+ /* dprintf2("YYTEXT == lstate->end_boundary: '%s'\n", yytext); */
+ if (lstate->body_start) {
+ yylval_param->position.opaque_start =
+ lstate->body_opaque_start;
+ yylval_param->position.start = lstate->body_start;
+ yylval_param->position.end = lstate->current_pos - yyleng;
+ lstate->body_opaque_start = 0;
+ lstate->body_start = 0;
+ lstate->body_end = 0;
+ yyless(0);
+ BC(endboundary);
+ return BODY;
+ }
+ }
+ } else {
+ }
+
+ REJECT;
+}
+
+<body,preamble>^\-\-{TSPECIAL}+ {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ /**
+ * Make sure we only catch matching boundaries, and not other lines
+ * that begin with two dashes.
+ */
+ if (lstate->boundary_string != NULL) {
+ if (strcmp(lstate->boundary_string, yytext)) {
+ /* dprintf2("YYTEXT != boundary: '%s'\n", yytext);*/
+ REJECT;
+ } else {
+ /* dprintf2("YYTEXT == boundary: '%s'\n", yytext);*/
+ if (lstate->body_start) {
+ yylval_param->position.opaque_start = lstate->body_opaque_start;
+ yylval_param->position.start = lstate->body_start;
+ yylval_param->position.end = lstate->current_pos;
+ lstate->body_opaque_start = 0;
+ lstate->body_start = 0;
+ lstate->body_end = 0;
+ yyless(0);
+ BC(boundary);
+ return BODY;
+ } else if (lstate->preamble_start) {
+ yylval_param->position.start = lstate->preamble_start;
+ yylval_param->position.end = lstate->current_pos;
+ lstate->preamble_start = lstate->preamble_end = 0;
+ yyless(0);
+ BC(boundary);
+ return PREAMBLE;
+ } else {
+ BC(boundary);
+ yylval_param->string = strdup(yytext);
+ lstate->current_pos += yyleng;
+ return(BOUNDARY);
+ }
+ }
+ } else {
+ }
+
+ REJECT;
+}
+
+<body>(\r\n|\n) {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+ lstate->lineno++;
+}
+
+<body>\r {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+ /* dprintf2("stray CR in body...\n"); */
+}
+
+<body>[^\r\n]+ {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+}
+
+<body><<EOF>> {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ if (lstate->boundary_string == NULL && lstate->body_start) {
+ yylval_param->position.opaque_start = 0;
+ yylval_param->position.start = lstate->body_start;
+ yylval_param->position.end = lstate->current_pos;
+ lstate->body_start = 0;
+ return BODY;
+ } else if (lstate->body_start) {
+ return POSTAMBLE;
+ }
+ yyterminate();
+}
+
+<preamble,postamble>(\r\n|\n) {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ /* dprintf2("Preamble CR/LF at line %d\n", lineno); */
+ lstate->lineno++;
+ lstate->current_pos += yyleng;
+}
+
+<boundary>[^\r\n]+ {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ yylval_param->string = strdup(yytext);
+ lstate->current_pos += yyleng;
+ return BOUNDARY;
+}
+
+<endboundary>[^\r\n]+ {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ yylval_param->string = strdup(yytext);
+ lstate->current_pos += yyleng;
+ return ENDBOUNDARY;
+}
+
+<boundary>(\r\n|\n) {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ BC(headers);
+ lstate->lineno++;
+ lstate->current_pos += yyleng;
+ lstate->body_opaque_start = lstate->current_pos;
+ return EOL;
+}
+
+<endboundary>(\r\n|\n) {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ BC(postamble);
+ lstate->lineno++;
+ lstate->current_pos += yyleng;
+}
+
+<preamble>. {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+}
+
+
+<postamble>. {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+}
+
+(\r\n|\n) {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ lstate->lineno++;
+ lstate->current_pos += yyleng;
+ return EOL;
+}
+
+. {
+ struct lexer_state *lstate = yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+ return((int)*yytext);
+}
+
+
+%%
+
+void reset_lexer_state(void *yyscanner, struct parser_state *pstate)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ struct lexer_state *lstate = &(pstate->lstate);
+
+ yyset_extra((void*)lstate, yyscanner);
+ BEGIN(0);
+ lstate->header_state = STATE_MAIL;
+ lstate->lineno = 0;
+ lstate->current_pos = 1;
+ lstate->condition = 0;
+
+ lstate->is_envelope = 1;
+
+ lstate->message_len = 0;
+ lstate->buffer_length = 0;
+
+ /* temporary marker variables */
+ lstate->body_opaque_start = 0;
+ lstate->body_start = 0;
+ lstate->body_end = 0;
+ lstate->preamble_start = 0;
+ lstate->preamble_end = 0;
+ lstate->postamble_start = 0;
+ lstate->postamble_end = 0;
+}
+
+void
+PARSER_setbuffer(char *string, yyscan_t scanner)
+{
+ struct lexer_state *lstate = yyget_extra(scanner);
+ lstate->message_buffer = string;
+ yy_scan_string(string, scanner);
+}
+
+void
+PARSER_setfp(FILE *fp, yyscan_t yyscanner)
+{
+ /* looks like a bug in bison 2.2a -- the wrong code is generated for yyset_in !! */
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyg->yyin_r = fp;
+
+ if (0) {
+ /* This is just to make a compiler warning go away */
+ yyunput(0, NULL, yyscanner);
+ }
+}
+
+/**
+ * Counts how many lines a given string represents in the message (in case of
+ * folded header values, for example, or a message body).
+ */
+int
+count_lines(char *txt)
+{
+ char *o;
+ int line;
+
+ line = 0;
+
+ for (o = txt; *o != '\0'; o++)
+ if (*o == '\n')
+ line++;
+
+ return line;
+}
diff --git a/main/minimime/mimeparser.tab.c b/main/minimime/mimeparser.tab.c
new file mode 100644
index 000000000..509fa4d2d
--- /dev/null
+++ b/main/minimime/mimeparser.tab.c
@@ -0,0 +1,2341 @@
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Skeleton implementation for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program 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 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* C LALR(1) parser skeleton written by Richard Stallman, by
+ simplifying the original so-called "semantic" parser. */
+
+/* All symbols defined below should begin with yy or YY, to avoid
+ infringing on user name space. This should be done even for local
+ variables, as they might otherwise be expanded by user macros.
+ There are some unavoidable exceptions within include files to
+ define necessary library symbols; they are noted "INFRINGES ON
+ USER NAME SPACE" below. */
+
+/* Identify Bison output. */
+#define YYBISON 1
+
+/* Bison version. */
+#define YYBISON_VERSION "2.3"
+
+/* Skeleton name. */
+#define YYSKELETON_NAME "yacc.c"
+
+/* Pure parsers. */
+#define YYPURE 1
+
+/* Using locations. */
+#define YYLSP_NEEDED 0
+
+/* Substitute the variable and function names. */
+#define yyparse mimeparser_yyparse
+#define yylex mimeparser_yylex
+#define yyerror mimeparser_yyerror
+#define yylval mimeparser_yylval
+#define yychar mimeparser_yychar
+#define yydebug mimeparser_yydebug
+#define yynerrs mimeparser_yynerrs
+
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ ANY = 258,
+ COLON = 259,
+ DASH = 260,
+ DQUOTE = 261,
+ ENDOFHEADERS = 262,
+ EOL = 263,
+ EOM = 264,
+ EQUAL = 265,
+ MIMEVERSION_HEADER = 266,
+ SEMICOLON = 267,
+ CONTENTDISPOSITION_HEADER = 268,
+ CONTENTENCODING_HEADER = 269,
+ CONTENTTYPE_HEADER = 270,
+ MAIL_HEADER = 271,
+ HEADERVALUE = 272,
+ BOUNDARY = 273,
+ ENDBOUNDARY = 274,
+ CONTENTTYPE_VALUE = 275,
+ TSPECIAL = 276,
+ WORD = 277,
+ BODY = 278,
+ PREAMBLE = 279,
+ POSTAMBLE = 280
+ };
+#endif
+/* Tokens. */
+#define ANY 258
+#define COLON 259
+#define DASH 260
+#define DQUOTE 261
+#define ENDOFHEADERS 262
+#define EOL 263
+#define EOM 264
+#define EQUAL 265
+#define MIMEVERSION_HEADER 266
+#define SEMICOLON 267
+#define CONTENTDISPOSITION_HEADER 268
+#define CONTENTENCODING_HEADER 269
+#define CONTENTTYPE_HEADER 270
+#define MAIL_HEADER 271
+#define HEADERVALUE 272
+#define BOUNDARY 273
+#define ENDBOUNDARY 274
+#define CONTENTTYPE_VALUE 275
+#define TSPECIAL 276
+#define WORD 277
+#define BODY 278
+#define PREAMBLE 279
+#define POSTAMBLE 280
+
+
+
+
+/* Copy the first part of user declarations. */
+#line 1 "mimeparser.y"
+
+/*
+ * Copyright (c) 2004 Jann Fischer. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/**
+ * These are the grammatic definitions in yacc syntax to parse MIME conform
+ * messages.
+ *
+ * TODO:
+ * - honour parse flags passed to us (partly done)
+ * - parse Content-Disposition header (partly done)
+ * - parse Content-Encoding header
+ */
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "mimeparser.h"
+#include "mm.h"
+#include "mm_internal.h"
+
+int set_boundary(char *,struct parser_state *);
+int mimeparser_yywrap(void);
+void reset_environ(struct parser_state *pstate);
+int PARSER_initialize(struct parser_state *pstate, void *yyscanner);
+
+typedef void *yyscan_t;
+
+static char *PARSE_readmessagepart(size_t, size_t, size_t, size_t *,yyscan_t, struct parser_state *);
+FILE *mimeparser_yyget_in (yyscan_t yyscanner );
+
+
+
+/* Enabling traces. */
+#ifndef YYDEBUG
+# define YYDEBUG 0
+#endif
+
+/* Enabling verbose error messages. */
+#ifdef YYERROR_VERBOSE
+# undef YYERROR_VERBOSE
+# define YYERROR_VERBOSE 1
+#else
+# define YYERROR_VERBOSE 0
+#endif
+
+/* Enabling the token table. */
+#ifndef YYTOKEN_TABLE
+# define YYTOKEN_TABLE 0
+#endif
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 69 "mimeparser.y"
+{
+ int number;
+ char *string;
+ struct s_position position;
+}
+/* Line 193 of yacc.c. */
+#line 222 "mimeparser.tab.c"
+ YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
+/* Copy the second part of user declarations. */
+
+
+/* Line 216 of yacc.c. */
+#line 235 "mimeparser.tab.c"
+
+#ifdef short
+# undef short
+#endif
+
+#ifdef YYTYPE_UINT8
+typedef YYTYPE_UINT8 yytype_uint8;
+#else
+typedef unsigned char yytype_uint8;
+#endif
+
+#ifdef YYTYPE_INT8
+typedef YYTYPE_INT8 yytype_int8;
+#elif (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+typedef signed char yytype_int8;
+#else
+typedef short int yytype_int8;
+#endif
+
+#ifdef YYTYPE_UINT16
+typedef YYTYPE_UINT16 yytype_uint16;
+#else
+typedef unsigned short int yytype_uint16;
+#endif
+
+#ifdef YYTYPE_INT16
+typedef YYTYPE_INT16 yytype_int16;
+#else
+typedef short int yytype_int16;
+#endif
+
+#ifndef YYSIZE_T
+# ifdef __SIZE_TYPE__
+# define YYSIZE_T __SIZE_TYPE__
+# elif defined size_t
+# define YYSIZE_T size_t
+# elif ! defined YYSIZE_T && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stddef.h> /* INFRINGES ON USER NAME SPACE */
+# define YYSIZE_T size_t
+# else
+# define YYSIZE_T unsigned int
+# endif
+#endif
+
+#define YYSIZE_MAXIMUM ((YYSIZE_T) -1)
+
+#ifndef YY_
+# if YYENABLE_NLS
+# if ENABLE_NLS
+# include <libintl.h> /* INFRINGES ON USER NAME SPACE */
+# define YY_(msgid) dgettext ("bison-runtime", msgid)
+# endif
+# endif
+# ifndef YY_
+# define YY_(msgid) msgid
+# endif
+#endif
+
+/* Suppress unused-variable warnings by "using" E. */
+#if ! defined lint || defined __GNUC__
+# define YYUSE(e) ((void) (e))
+#else
+# define YYUSE(e) /* empty */
+#endif
+
+/* Identity function, used to suppress warnings about constant conditions. */
+#ifndef lint
+# define YYID(n) (n)
+#else
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static int
+YYID (int i)
+#else
+static int
+YYID (i)
+ int i;
+#endif
+{
+ return i;
+}
+#endif
+
+#if ! defined yyoverflow || YYERROR_VERBOSE
+
+/* The parser invokes alloca or malloc; define the necessary symbols. */
+
+# ifdef YYSTACK_USE_ALLOCA
+# if YYSTACK_USE_ALLOCA
+# ifdef __GNUC__
+# define YYSTACK_ALLOC __builtin_alloca
+# elif defined __BUILTIN_VA_ARG_INCR
+# include <alloca.h> /* INFRINGES ON USER NAME SPACE */
+# elif defined _AIX
+# define YYSTACK_ALLOC __alloca
+# elif defined _MSC_VER
+# include <malloc.h> /* INFRINGES ON USER NAME SPACE */
+# define alloca _alloca
+# else
+# define YYSTACK_ALLOC alloca
+# if ! defined _ALLOCA_H && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# endif
+# endif
+# endif
+
+# ifdef YYSTACK_ALLOC
+ /* Pacify GCC's `empty if-body' warning. */
+# define YYSTACK_FREE(Ptr) do { /* empty */; } while (YYID (0))
+# ifndef YYSTACK_ALLOC_MAXIMUM
+ /* The OS might guarantee only one guard page at the bottom of the stack,
+ and a page size can be as small as 4096 bytes. So we cannot safely
+ invoke alloca (N) if N exceeds 4096. Use a slightly smaller number
+ to allow for a few compiler-allocated temporary stack slots. */
+# define YYSTACK_ALLOC_MAXIMUM 4032 /* reasonable circa 2006 */
+# endif
+# else
+# define YYSTACK_ALLOC YYMALLOC
+# define YYSTACK_FREE YYFREE
+# ifndef YYSTACK_ALLOC_MAXIMUM
+# define YYSTACK_ALLOC_MAXIMUM YYSIZE_MAXIMUM
+# endif
+# if (defined __cplusplus && ! defined _STDLIB_H \
+ && ! ((defined YYMALLOC || defined malloc) \
+ && (defined YYFREE || defined free)))
+# include <stdlib.h> /* INFRINGES ON USER NAME SPACE */
+# ifndef _STDLIB_H
+# define _STDLIB_H 1
+# endif
+# endif
+# ifndef YYMALLOC
+# define YYMALLOC malloc
+# if ! defined malloc && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void *malloc (YYSIZE_T); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# ifndef YYFREE
+# define YYFREE free
+# if ! defined free && ! defined _STDLIB_H && (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+void free (void *); /* INFRINGES ON USER NAME SPACE */
+# endif
+# endif
+# endif
+#endif /* ! defined yyoverflow || YYERROR_VERBOSE */
+
+
+#if (! defined yyoverflow \
+ && (! defined __cplusplus \
+ || (defined YYSTYPE_IS_TRIVIAL && YYSTYPE_IS_TRIVIAL)))
+
+/* A type that is properly aligned for any stack member. */
+union yyalloc
+{
+ yytype_int16 yyss;
+ YYSTYPE yyvs;
+ };
+
+/* The size of the maximum gap between one aligned stack and the next. */
+# define YYSTACK_GAP_MAXIMUM (sizeof (union yyalloc) - 1)
+
+/* The size of an array large to enough to hold all stacks, each with
+ N elements. */
+# define YYSTACK_BYTES(N) \
+ ((N) * (sizeof (yytype_int16) + sizeof (YYSTYPE)) \
+ + YYSTACK_GAP_MAXIMUM)
+
+/* Copy COUNT objects from FROM to TO. The source and destination do
+ not overlap. */
+# ifndef YYCOPY
+# if defined __GNUC__ && 1 < __GNUC__
+# define YYCOPY(To, From, Count) \
+ __builtin_memcpy (To, From, (Count) * sizeof (*(From)))
+# else
+# define YYCOPY(To, From, Count) \
+ do \
+ { \
+ YYSIZE_T yyi; \
+ for (yyi = 0; yyi < (Count); yyi++) \
+ (To)[yyi] = (From)[yyi]; \
+ } \
+ while (YYID (0))
+# endif
+# endif
+
+/* Relocate STACK from its old location to the new one. The
+ local variables YYSIZE and YYSTACKSIZE give the old and new number of
+ elements in the stack, and YYPTR gives the new location of the
+ stack. Advance YYPTR to a properly aligned location for the next
+ stack. */
+# define YYSTACK_RELOCATE(Stack) \
+ do \
+ { \
+ YYSIZE_T yynewbytes; \
+ YYCOPY (&yyptr->Stack, Stack, yysize); \
+ Stack = &yyptr->Stack; \
+ yynewbytes = yystacksize * sizeof (*Stack) + YYSTACK_GAP_MAXIMUM; \
+ yyptr += yynewbytes / sizeof (*yyptr); \
+ } \
+ while (YYID (0))
+
+#endif
+
+/* YYFINAL -- State number of the termination state. */
+#define YYFINAL 26
+/* YYLAST -- Last index in YYTABLE. */
+#define YYLAST 61
+
+/* YYNTOKENS -- Number of terminals. */
+#define YYNTOKENS 28
+/* YYNNTS -- Number of nonterminals. */
+#define YYNNTS 29
+/* YYNRULES -- Number of rules. */
+#define YYNRULES 50
+/* YYNRULES -- Number of states. */
+#define YYNSTATES 83
+
+/* YYTRANSLATE(YYLEX) -- Bison symbol number corresponding to YYLEX. */
+#define YYUNDEFTOK 2
+#define YYMAXUTOK 280
+
+#define YYTRANSLATE(YYX) \
+ ((unsigned int) (YYX) <= YYMAXUTOK ? yytranslate[YYX] : YYUNDEFTOK)
+
+/* YYTRANSLATE[YYLEX] -- Bison symbol number corresponding to YYLEX. */
+static const yytype_uint8 yytranslate[] =
+{
+ 0, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 27, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 26, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 2, 2, 2, 2,
+ 2, 2, 2, 2, 2, 2, 1, 2, 3, 4,
+ 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
+ 15, 16, 17, 18, 19, 20, 21, 22, 23, 24,
+ 25
+};
+
+#if YYDEBUG
+/* YYPRHS[YYN] -- Index of the first RHS symbol of rule number YYN in
+ YYRHS. */
+static const yytype_uint8 yyprhs[] =
+{
+ 0, 0, 3, 5, 7, 8, 15, 18, 21, 23,
+ 25, 27, 28, 30, 31, 34, 36, 40, 42, 44,
+ 46, 48, 50, 52, 57, 61, 66, 72, 77, 83,
+ 85, 90, 95, 98, 101, 103, 107, 111, 114, 116,
+ 120, 123, 125, 129, 133, 135, 137, 141, 143, 146,
+ 148
+};
+
+/* YYRHS -- A `-1'-separated list of the rules' RHS. */
+static const yytype_int8 yyrhs[] =
+{
+ 29, 0, -1, 30, -1, 32, -1, -1, 33, 34,
+ 31, 36, 55, 35, -1, 33, 56, -1, 38, 33,
+ -1, 53, -1, 38, -1, 24, -1, -1, 25, -1,
+ -1, 36, 37, -1, 37, -1, 54, 33, 56, -1,
+ 39, -1, 40, -1, 41, -1, 43, -1, 44, -1,
+ 45, -1, 16, 4, 22, 8, -1, 16, 4, 8,
+ -1, 15, 4, 47, 8, -1, 15, 4, 47, 48,
+ 8, -1, 13, 4, 42, 8, -1, 13, 4, 42,
+ 49, 8, -1, 22, -1, 14, 4, 22, 8, -1,
+ 11, 4, 22, 8, -1, 46, 8, -1, 46, 3,
+ -1, 3, -1, 22, 26, 22, -1, 12, 50, 48,
+ -1, 12, 50, -1, 12, -1, 12, 51, 49, -1,
+ 12, 51, -1, 12, -1, 22, 10, 52, -1, 22,
+ 10, 52, -1, 22, -1, 21, -1, 27, 21, 27,
+ -1, 7, -1, 18, 8, -1, 19, -1, 23, -1
+};
+
+/* YYRLINE[YYN] -- source line where rule number YYN was defined. */
+static const yytype_uint16 yyrline[] =
+{
+ 0, 114, 114, 116, 121, 120, 133, 141, 143, 167,
+ 171, 186, 190, 193, 197, 199, 203, 218, 220, 230,
+ 232, 234, 236, 250, 257, 276, 284, 294, 300, 308,
+ 331, 338, 345, 349, 351, 355, 364, 366, 368, 382,
+ 384, 386, 400, 431, 445, 451, 466, 474, 481, 500,
+ 519
+};
+#endif
+
+#if YYDEBUG || YYERROR_VERBOSE || YYTOKEN_TABLE
+/* YYTNAME[SYMBOL-NUM] -- String name of the symbol SYMBOL-NUM.
+ First, the terminals, then, starting at YYNTOKENS, nonterminals. */
+static const char *const yytname[] =
+{
+ "$end", "error", "$undefined", "ANY", "COLON", "DASH", "DQUOTE",
+ "ENDOFHEADERS", "EOL", "EOM", "EQUAL", "MIMEVERSION_HEADER", "SEMICOLON",
+ "CONTENTDISPOSITION_HEADER", "CONTENTENCODING_HEADER",
+ "CONTENTTYPE_HEADER", "MAIL_HEADER", "HEADERVALUE", "BOUNDARY",
+ "ENDBOUNDARY", "CONTENTTYPE_VALUE", "TSPECIAL", "WORD", "BODY",
+ "PREAMBLE", "POSTAMBLE", "'/'", "'\"'", "$accept", "message",
+ "multipart_message", "@1", "singlepart_message", "headers", "preamble",
+ "postamble", "mimeparts", "mimepart", "header", "mail_header",
+ "contenttype_header", "contentdisposition_header", "content_disposition",
+ "contentencoding_header", "mimeversion_header", "invalid_header", "any",
+ "mimetype", "contenttype_parameters", "content_disposition_parameters",
+ "contenttype_parameter", "content_disposition_parameter",
+ "contenttype_parameter_value", "end_headers", "boundary", "endboundary",
+ "body", 0
+};
+#endif
+
+# ifdef YYPRINT
+/* YYTOKNUM[YYLEX-NUM] -- Internal token number corresponding to
+ token YYLEX-NUM. */
+static const yytype_uint16 yytoknum[] =
+{
+ 0, 256, 257, 258, 259, 260, 261, 262, 263, 264,
+ 265, 266, 267, 268, 269, 270, 271, 272, 273, 274,
+ 275, 276, 277, 278, 279, 280, 47, 34
+};
+# endif
+
+/* YYR1[YYN] -- Symbol number of symbol that rule YYN derives. */
+static const yytype_uint8 yyr1[] =
+{
+ 0, 28, 29, 29, 31, 30, 32, 33, 33, 33,
+ 34, 34, 35, 35, 36, 36, 37, 38, 38, 38,
+ 38, 38, 38, 39, 39, 40, 40, 41, 41, 42,
+ 43, 44, 45, 46, 46, 47, 48, 48, 48, 49,
+ 49, 49, 50, 51, 52, 52, 52, 53, 54, 55,
+ 56
+};
+
+/* YYR2[YYN] -- Number of symbols composing right hand side of rule YYN. */
+static const yytype_uint8 yyr2[] =
+{
+ 0, 2, 1, 1, 0, 6, 2, 2, 1, 1,
+ 1, 0, 1, 0, 2, 1, 3, 1, 1, 1,
+ 1, 1, 1, 4, 3, 4, 5, 4, 5, 1,
+ 4, 4, 2, 2, 1, 3, 3, 2, 1, 3,
+ 2, 1, 3, 3, 1, 1, 3, 1, 2, 1,
+ 1
+};
+
+/* YYDEFACT[STATE-NAME] -- Default rule to reduce with in state
+ STATE-NUM when YYTABLE doesn't specify something else to do. Zero
+ means the default is an error. */
+static const yytype_uint8 yydefact[] =
+{
+ 0, 34, 47, 0, 0, 0, 0, 0, 0, 2,
+ 3, 11, 9, 17, 18, 19, 20, 21, 22, 0,
+ 8, 0, 0, 0, 0, 0, 1, 50, 10, 4,
+ 6, 7, 33, 32, 0, 29, 0, 0, 0, 0,
+ 24, 0, 0, 31, 27, 41, 0, 30, 0, 25,
+ 38, 0, 23, 0, 0, 15, 0, 0, 40, 28,
+ 35, 0, 37, 26, 48, 49, 14, 13, 0, 0,
+ 39, 0, 36, 12, 5, 16, 45, 44, 0, 43,
+ 42, 0, 46
+};
+
+/* YYDEFGOTO[NTERM-NUM]. */
+static const yytype_int8 yydefgoto[] =
+{
+ -1, 8, 9, 42, 10, 11, 29, 74, 54, 55,
+ 12, 13, 14, 15, 36, 16, 17, 18, 19, 39,
+ 51, 46, 62, 58, 79, 20, 56, 67, 30
+};
+
+/* YYPACT[STATE-NUM] -- Index in YYTABLE of the portion describing
+ STATE-NUM. */
+#define YYPACT_NINF -20
+static const yytype_int8 yypact[] =
+{
+ 3, -20, -20, 17, 21, 22, 23, 24, 5, -20,
+ -20, -11, 3, -20, -20, -20, -20, -20, -20, 1,
+ -20, 7, 8, 9, 10, -7, -20, -20, -20, -20,
+ -20, -20, -20, -20, 25, -20, -1, 26, 11, 12,
+ -20, 27, 18, -20, -20, 16, 31, -20, 19, -20,
+ 20, 32, -20, 35, 4, -20, 3, 36, 33, -20,
+ -20, 37, 38, -20, -20, -20, -20, 28, 29, -19,
+ -20, -19, -20, -20, -20, -20, -20, -20, 30, -20,
+ -20, 34, -20
+};
+
+/* YYPGOTO[NTERM-NUM]. */
+static const yytype_int8 yypgoto[] =
+{
+ -20, -20, -20, -20, -20, -12, -20, -20, -20, -6,
+ -20, -20, -20, -20, -20, -20, -20, -20, -20, -20,
+ -13, -4, -20, -20, -16, -20, -20, -20, -10
+};
+
+/* YYTABLE[YYPACT[STATE-NUM]]. What to do in state STATE-NUM. If
+ positive, shift that token. If negative, reduce the rule which
+ number is the opposite. If zero, do what YYDEFACT says.
+ If YYTABLE_NINF, syntax error. */
+#define YYTABLE_NINF -1
+static const yytype_uint8 yytable[] =
+{
+ 31, 40, 76, 77, 32, 26, 1, 44, 78, 33,
+ 2, 45, 27, 28, 3, 41, 4, 5, 6, 7,
+ 49, 21, 53, 65, 50, 22, 23, 24, 25, 34,
+ 35, 37, 38, 43, 47, 52, 53, 48, 57, 59,
+ 63, 60, 61, 64, 68, 45, 69, 71, 66, 72,
+ 50, 81, 27, 73, 70, 80, 0, 0, 75, 0,
+ 0, 82
+};
+
+static const yytype_int8 yycheck[] =
+{
+ 12, 8, 21, 22, 3, 0, 3, 8, 27, 8,
+ 7, 12, 23, 24, 11, 22, 13, 14, 15, 16,
+ 8, 4, 18, 19, 12, 4, 4, 4, 4, 22,
+ 22, 22, 22, 8, 8, 8, 18, 26, 22, 8,
+ 8, 22, 22, 8, 56, 12, 10, 10, 54, 62,
+ 12, 21, 23, 25, 58, 71, -1, -1, 68, -1,
+ -1, 27
+};
+
+/* YYSTOS[STATE-NUM] -- The (internal number of the) accessing
+ symbol of state STATE-NUM. */
+static const yytype_uint8 yystos[] =
+{
+ 0, 3, 7, 11, 13, 14, 15, 16, 29, 30,
+ 32, 33, 38, 39, 40, 41, 43, 44, 45, 46,
+ 53, 4, 4, 4, 4, 4, 0, 23, 24, 34,
+ 56, 33, 3, 8, 22, 22, 42, 22, 22, 47,
+ 8, 22, 31, 8, 8, 12, 49, 8, 26, 8,
+ 12, 48, 8, 18, 36, 37, 54, 22, 51, 8,
+ 22, 22, 50, 8, 8, 19, 37, 55, 33, 10,
+ 49, 10, 48, 25, 35, 56, 21, 22, 27, 52,
+ 52, 21, 27
+};
+
+#define yyerrok (yyerrstatus = 0)
+#define yyclearin (yychar = YYEMPTY)
+#define YYEMPTY (-2)
+#define YYEOF 0
+
+#define YYACCEPT goto yyacceptlab
+#define YYABORT goto yyabortlab
+#define YYERROR goto yyerrorlab
+
+
+/* Like YYERROR except do call yyerror. This remains here temporarily
+ to ease the transition to the new meaning of YYERROR, for GCC.
+ Once GCC version 2 has supplanted version 1, this can go. */
+
+#define YYFAIL goto yyerrlab
+
+#define YYRECOVERING() (!!yyerrstatus)
+
+#define YYBACKUP(Token, Value) \
+do \
+ if (yychar == YYEMPTY && yylen == 1) \
+ { \
+ yychar = (Token); \
+ yylval = (Value); \
+ yytoken = YYTRANSLATE (yychar); \
+ YYPOPSTACK (1); \
+ goto yybackup; \
+ } \
+ else \
+ { \
+ yyerror (pstate, yyscanner, YY_("syntax error: cannot back up")); \
+ YYERROR; \
+ } \
+while (YYID (0))
+
+
+#define YYTERROR 1
+#define YYERRCODE 256
+
+
+/* YYLLOC_DEFAULT -- Set CURRENT to span from RHS[1] to RHS[N].
+ If N is 0, then set CURRENT to the empty location which ends
+ the previous symbol: RHS[0] (always defined). */
+
+#define YYRHSLOC(Rhs, K) ((Rhs)[K])
+#ifndef YYLLOC_DEFAULT
+# define YYLLOC_DEFAULT(Current, Rhs, N) \
+ do \
+ if (YYID (N)) \
+ { \
+ (Current).first_line = YYRHSLOC (Rhs, 1).first_line; \
+ (Current).first_column = YYRHSLOC (Rhs, 1).first_column; \
+ (Current).last_line = YYRHSLOC (Rhs, N).last_line; \
+ (Current).last_column = YYRHSLOC (Rhs, N).last_column; \
+ } \
+ else \
+ { \
+ (Current).first_line = (Current).last_line = \
+ YYRHSLOC (Rhs, 0).last_line; \
+ (Current).first_column = (Current).last_column = \
+ YYRHSLOC (Rhs, 0).last_column; \
+ } \
+ while (YYID (0))
+#endif
+
+
+/* YY_LOCATION_PRINT -- Print the location on the stream.
+ This macro was not mandated originally: define only if we know
+ we won't break user code: when these are the locations we know. */
+
+#ifndef YY_LOCATION_PRINT
+# if YYLTYPE_IS_TRIVIAL
+# define YY_LOCATION_PRINT(File, Loc) \
+ fprintf (File, "%d.%d-%d.%d", \
+ (Loc).first_line, (Loc).first_column, \
+ (Loc).last_line, (Loc).last_column)
+# else
+# define YY_LOCATION_PRINT(File, Loc) ((void) 0)
+# endif
+#endif
+
+
+/* YYLEX -- calling `yylex' with the right arguments. */
+
+#ifdef YYLEX_PARAM
+# define YYLEX yylex (&yylval, YYLEX_PARAM)
+#else
+# define YYLEX yylex (&yylval, yyscanner)
+#endif
+
+/* Enable debugging if requested. */
+#if YYDEBUG
+
+# ifndef YYFPRINTF
+# include <stdio.h> /* INFRINGES ON USER NAME SPACE */
+# define YYFPRINTF fprintf
+# endif
+
+# define YYDPRINTF(Args) \
+do { \
+ if (yydebug) \
+ YYFPRINTF Args; \
+} while (YYID (0))
+
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location) \
+do { \
+ if (yydebug) \
+ { \
+ YYFPRINTF (stderr, "%s ", Title); \
+ yy_symbol_print (stderr, \
+ Type, Value, pstate, yyscanner); \
+ YYFPRINTF (stderr, "\n"); \
+ } \
+} while (YYID (0))
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_value_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, struct parser_state *pstate, void *yyscanner)
+#else
+static void
+yy_symbol_value_print (yyoutput, yytype, yyvaluep, pstate, yyscanner)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ struct parser_state *pstate;
+ void *yyscanner;
+#endif
+{
+ if (!yyvaluep)
+ return;
+ YYUSE (pstate);
+ YYUSE (yyscanner);
+# ifdef YYPRINT
+ if (yytype < YYNTOKENS)
+ YYPRINT (yyoutput, yytoknum[yytype], *yyvaluep);
+# else
+ YYUSE (yyoutput);
+# endif
+ switch (yytype)
+ {
+ default:
+ break;
+ }
+}
+
+
+/*--------------------------------.
+| Print this symbol on YYOUTPUT. |
+`--------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_symbol_print (FILE *yyoutput, int yytype, YYSTYPE const * const yyvaluep, struct parser_state *pstate, void *yyscanner)
+#else
+static void
+yy_symbol_print (yyoutput, yytype, yyvaluep, pstate, yyscanner)
+ FILE *yyoutput;
+ int yytype;
+ YYSTYPE const * const yyvaluep;
+ struct parser_state *pstate;
+ void *yyscanner;
+#endif
+{
+ if (yytype < YYNTOKENS)
+ YYFPRINTF (yyoutput, "token %s (", yytname[yytype]);
+ else
+ YYFPRINTF (yyoutput, "nterm %s (", yytname[yytype]);
+
+ yy_symbol_value_print (yyoutput, yytype, yyvaluep, pstate, yyscanner);
+ YYFPRINTF (yyoutput, ")");
+}
+
+/*------------------------------------------------------------------.
+| yy_stack_print -- Print the state stack from its BOTTOM up to its |
+| TOP (included). |
+`------------------------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_stack_print (yytype_int16 *bottom, yytype_int16 *top)
+#else
+static void
+yy_stack_print (bottom, top)
+ yytype_int16 *bottom;
+ yytype_int16 *top;
+#endif
+{
+ YYFPRINTF (stderr, "Stack now");
+ for (; bottom <= top; ++bottom)
+ YYFPRINTF (stderr, " %d", *bottom);
+ YYFPRINTF (stderr, "\n");
+}
+
+# define YY_STACK_PRINT(Bottom, Top) \
+do { \
+ if (yydebug) \
+ yy_stack_print ((Bottom), (Top)); \
+} while (YYID (0))
+
+
+/*------------------------------------------------.
+| Report that the YYRULE is going to be reduced. |
+`------------------------------------------------*/
+
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yy_reduce_print (YYSTYPE *yyvsp, int yyrule, struct parser_state *pstate, void *yyscanner)
+#else
+static void
+yy_reduce_print (yyvsp, yyrule, pstate, yyscanner)
+ YYSTYPE *yyvsp;
+ int yyrule;
+ struct parser_state *pstate;
+ void *yyscanner;
+#endif
+{
+ int yynrhs = yyr2[yyrule];
+ int yyi;
+ unsigned long int yylno = yyrline[yyrule];
+ YYFPRINTF (stderr, "Reducing stack by rule %d (line %lu):\n",
+ yyrule - 1, yylno);
+ /* The symbols being reduced. */
+ for (yyi = 0; yyi < yynrhs; yyi++)
+ {
+ fprintf (stderr, " $%d = ", yyi + 1);
+ yy_symbol_print (stderr, yyrhs[yyprhs[yyrule] + yyi],
+ &(yyvsp[(yyi + 1) - (yynrhs)])
+ , pstate, yyscanner);
+ fprintf (stderr, "\n");
+ }
+}
+
+# define YY_REDUCE_PRINT(Rule) \
+do { \
+ if (yydebug) \
+ yy_reduce_print (yyvsp, Rule, pstate, yyscanner); \
+} while (YYID (0))
+
+/* Nonzero means print parse trace. It is left uninitialized so that
+ multiple parsers can coexist. */
+int yydebug;
+#else /* !YYDEBUG */
+# define YYDPRINTF(Args)
+# define YY_SYMBOL_PRINT(Title, Type, Value, Location)
+# define YY_STACK_PRINT(Bottom, Top)
+# define YY_REDUCE_PRINT(Rule)
+#endif /* !YYDEBUG */
+
+
+/* YYINITDEPTH -- initial size of the parser's stacks. */
+#ifndef YYINITDEPTH
+# define YYINITDEPTH 200
+#endif
+
+/* YYMAXDEPTH -- maximum size the stacks can grow to (effective only
+ if the built-in stack extension method is used).
+
+ Do not make this value too large; the results are undefined if
+ YYSTACK_ALLOC_MAXIMUM < YYSTACK_BYTES (YYMAXDEPTH)
+ evaluated with infinite-precision integer arithmetic. */
+
+#ifndef YYMAXDEPTH
+# define YYMAXDEPTH 10000
+#endif
+
+
+
+#if YYERROR_VERBOSE
+
+# ifndef yystrlen
+# if defined __GLIBC__ && defined _STRING_H
+# define yystrlen strlen
+# else
+/* Return the length of YYSTR. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static YYSIZE_T
+yystrlen (const char *yystr)
+#else
+static YYSIZE_T
+yystrlen (yystr)
+ const char *yystr;
+#endif
+{
+ YYSIZE_T yylen;
+ for (yylen = 0; yystr[yylen]; yylen++)
+ continue;
+ return yylen;
+}
+# endif
+# endif
+
+# ifndef yystpcpy
+# if defined __GLIBC__ && defined _STRING_H && defined _GNU_SOURCE
+# define yystpcpy stpcpy
+# else
+/* Copy YYSRC to YYDEST, returning the address of the terminating '\0' in
+ YYDEST. */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static char *
+yystpcpy (char *yydest, const char *yysrc)
+#else
+static char *
+yystpcpy (yydest, yysrc)
+ char *yydest;
+ const char *yysrc;
+#endif
+{
+ char *yyd = yydest;
+ const char *yys = yysrc;
+
+ while ((*yyd++ = *yys++) != '\0')
+ continue;
+
+ return yyd - 1;
+}
+# endif
+# endif
+
+# ifndef yytnamerr
+/* Copy to YYRES the contents of YYSTR after stripping away unnecessary
+ quotes and backslashes, so that it's suitable for yyerror. The
+ heuristic is that double-quoting is unnecessary unless the string
+ contains an apostrophe, a comma, or backslash (other than
+ backslash-backslash). YYSTR is taken from yytname. If YYRES is
+ null, do not copy; instead, return the length of what the result
+ would have been. */
+static YYSIZE_T
+yytnamerr (char *yyres, const char *yystr)
+{
+ if (*yystr == '"')
+ {
+ YYSIZE_T yyn = 0;
+ char const *yyp = yystr;
+
+ for (;;)
+ switch (*++yyp)
+ {
+ case '\'':
+ case ',':
+ goto do_not_strip_quotes;
+
+ case '\\':
+ if (*++yyp != '\\')
+ goto do_not_strip_quotes;
+ /* Fall through. */
+ default:
+ if (yyres)
+ yyres[yyn] = *yyp;
+ yyn++;
+ break;
+
+ case '"':
+ if (yyres)
+ yyres[yyn] = '\0';
+ return yyn;
+ }
+ do_not_strip_quotes: ;
+ }
+
+ if (! yyres)
+ return yystrlen (yystr);
+
+ return yystpcpy (yyres, yystr) - yyres;
+}
+# endif
+
+/* Copy into YYRESULT an error message about the unexpected token
+ YYCHAR while in state YYSTATE. Return the number of bytes copied,
+ including the terminating null byte. If YYRESULT is null, do not
+ copy anything; just return the number of bytes that would be
+ copied. As a special case, return 0 if an ordinary "syntax error"
+ message will do. Return YYSIZE_MAXIMUM if overflow occurs during
+ size calculation. */
+static YYSIZE_T
+yysyntax_error (char *yyresult, int yystate, int yychar)
+{
+ int yyn = yypact[yystate];
+
+ if (! (YYPACT_NINF < yyn && yyn <= YYLAST))
+ return 0;
+ else
+ {
+ int yytype = YYTRANSLATE (yychar);
+ YYSIZE_T yysize0 = yytnamerr (0, yytname[yytype]);
+ YYSIZE_T yysize = yysize0;
+ YYSIZE_T yysize1;
+ int yysize_overflow = 0;
+ enum { YYERROR_VERBOSE_ARGS_MAXIMUM = 5 };
+ char const *yyarg[YYERROR_VERBOSE_ARGS_MAXIMUM];
+ int yyx;
+
+# if 0
+ /* This is so xgettext sees the translatable formats that are
+ constructed on the fly. */
+ YY_("syntax error, unexpected %s");
+ YY_("syntax error, unexpected %s, expecting %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s");
+ YY_("syntax error, unexpected %s, expecting %s or %s or %s or %s");
+# endif
+ char *yyfmt;
+ char const *yyf;
+ static char const yyunexpected[] = "syntax error, unexpected %s";
+ static char const yyexpecting[] = ", expecting %s";
+ static char const yyor[] = " or %s";
+ char yyformat[sizeof yyunexpected
+ + sizeof yyexpecting - 1
+ + ((YYERROR_VERBOSE_ARGS_MAXIMUM - 2)
+ * (sizeof yyor - 1))];
+ char const *yyprefix = yyexpecting;
+
+ /* Start YYX at -YYN if negative to avoid negative indexes in
+ YYCHECK. */
+ int yyxbegin = yyn < 0 ? -yyn : 0;
+
+ /* Stay within bounds of both yycheck and yytname. */
+ int yychecklim = YYLAST - yyn + 1;
+ int yyxend = yychecklim < YYNTOKENS ? yychecklim : YYNTOKENS;
+ int yycount = 1;
+
+ yyarg[0] = yytname[yytype];
+ yyfmt = yystpcpy (yyformat, yyunexpected);
+
+ for (yyx = yyxbegin; yyx < yyxend; ++yyx)
+ if (yycheck[yyx + yyn] == yyx && yyx != YYTERROR)
+ {
+ if (yycount == YYERROR_VERBOSE_ARGS_MAXIMUM)
+ {
+ yycount = 1;
+ yysize = yysize0;
+ yyformat[sizeof yyunexpected - 1] = '\0';
+ break;
+ }
+ yyarg[yycount++] = yytname[yyx];
+ yysize1 = yysize + yytnamerr (0, yytname[yyx]);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+ yyfmt = yystpcpy (yyfmt, yyprefix);
+ yyprefix = yyor;
+ }
+
+ yyf = YY_(yyformat);
+ yysize1 = yysize + yystrlen (yyf);
+ yysize_overflow |= (yysize1 < yysize);
+ yysize = yysize1;
+
+ if (yysize_overflow)
+ return YYSIZE_MAXIMUM;
+
+ if (yyresult)
+ {
+ /* Avoid sprintf, as that infringes on the user's name space.
+ Don't have undefined behavior even if the translation
+ produced a string with the wrong number of "%s"s. */
+ char *yyp = yyresult;
+ int yyi = 0;
+ while ((*yyp = *yyf) != '\0')
+ {
+ if (*yyp == '%' && yyf[1] == 's' && yyi < yycount)
+ {
+ yyp += yytnamerr (yyp, yyarg[yyi++]);
+ yyf += 2;
+ }
+ else
+ {
+ yyp++;
+ yyf++;
+ }
+ }
+ }
+ return yysize;
+ }
+}
+#endif /* YYERROR_VERBOSE */
+
+
+/*-----------------------------------------------.
+| Release the memory associated to this symbol. |
+`-----------------------------------------------*/
+
+/*ARGSUSED*/
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+static void
+yydestruct (const char *yymsg, int yytype, YYSTYPE *yyvaluep, struct parser_state *pstate, void *yyscanner)
+#else
+static void
+yydestruct (yymsg, yytype, yyvaluep, pstate, yyscanner)
+ const char *yymsg;
+ int yytype;
+ YYSTYPE *yyvaluep;
+ struct parser_state *pstate;
+ void *yyscanner;
+#endif
+{
+ YYUSE (yyvaluep);
+ YYUSE (pstate);
+ YYUSE (yyscanner);
+
+ if (!yymsg)
+ yymsg = "Deleting";
+ YY_SYMBOL_PRINT (yymsg, yytype, yyvaluep, yylocationp);
+
+ switch (yytype)
+ {
+
+ default:
+ break;
+ }
+}
+
+
+/* Prevent warnings from -Wmissing-prototypes. */
+
+#ifdef YYPARSE_PARAM
+#if defined __STDC__ || defined __cplusplus
+int yyparse (void *YYPARSE_PARAM);
+#else
+int yyparse ();
+#endif
+#else /* ! YYPARSE_PARAM */
+#if defined __STDC__ || defined __cplusplus
+int yyparse (struct parser_state *pstate, void *yyscanner);
+#else
+int yyparse ();
+#endif
+#endif /* ! YYPARSE_PARAM */
+
+
+
+
+
+
+/*----------.
+| yyparse. |
+`----------*/
+
+#ifdef YYPARSE_PARAM
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (void *YYPARSE_PARAM)
+#else
+int
+yyparse (YYPARSE_PARAM)
+ void *YYPARSE_PARAM;
+#endif
+#else /* ! YYPARSE_PARAM */
+#if (defined __STDC__ || defined __C99__FUNC__ \
+ || defined __cplusplus || defined _MSC_VER)
+int
+yyparse (struct parser_state *pstate, void *yyscanner)
+#else
+int
+yyparse (pstate, yyscanner)
+ struct parser_state *pstate;
+ void *yyscanner;
+#endif
+#endif
+{
+ /* The look-ahead symbol. */
+int yychar;
+
+/* The semantic value of the look-ahead symbol. */
+YYSTYPE yylval;
+
+/* Number of syntax errors so far. */
+int yynerrs;
+
+ int yystate;
+ int yyn;
+ int yyresult;
+ /* Number of tokens to shift before error messages enabled. */
+ int yyerrstatus;
+ /* Look-ahead token as an internal (translated) token number. */
+ int yytoken = 0;
+#if YYERROR_VERBOSE
+ /* Buffer for error messages, and its allocated size. */
+ char yymsgbuf[128];
+ char *yymsg = yymsgbuf;
+ YYSIZE_T yymsg_alloc = sizeof yymsgbuf;
+#endif
+
+ /* Three stacks and their tools:
+ `yyss': related to states,
+ `yyvs': related to semantic values,
+ `yyls': related to locations.
+
+ Refer to the stacks thru separate pointers, to allow yyoverflow
+ to reallocate them elsewhere. */
+
+ /* The state stack. */
+ yytype_int16 yyssa[YYINITDEPTH];
+ yytype_int16 *yyss = yyssa;
+ yytype_int16 *yyssp;
+
+ /* The semantic value stack. */
+ YYSTYPE yyvsa[YYINITDEPTH];
+ YYSTYPE *yyvs = yyvsa;
+ YYSTYPE *yyvsp;
+
+
+
+#define YYPOPSTACK(N) (yyvsp -= (N), yyssp -= (N))
+
+ YYSIZE_T yystacksize = YYINITDEPTH;
+
+ /* The variables used to return semantic value and location from the
+ action routines. */
+ YYSTYPE yyval;
+
+
+ /* The number of symbols on the RHS of the reduced rule.
+ Keep to zero when no symbol should be popped. */
+ int yylen = 0;
+
+ YYDPRINTF ((stderr, "Starting parse\n"));
+
+ yystate = 0;
+ yyerrstatus = 0;
+ yynerrs = 0;
+ yychar = YYEMPTY; /* Cause a token to be read. */
+
+ /* Initialize stack pointers.
+ Waste one element of value and location stack
+ so that they stay on the same level as the state stack.
+ The wasted elements are never initialized. */
+
+ yyssp = yyss;
+ yyvsp = yyvs;
+
+ goto yysetstate;
+
+/*------------------------------------------------------------.
+| yynewstate -- Push a new state, which is found in yystate. |
+`------------------------------------------------------------*/
+ yynewstate:
+ /* In all cases, when you get here, the value and location stacks
+ have just been pushed. So pushing a state here evens the stacks. */
+ yyssp++;
+
+ yysetstate:
+ *yyssp = yystate;
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ {
+ /* Get the current used size of the three stacks, in elements. */
+ YYSIZE_T yysize = yyssp - yyss + 1;
+
+#ifdef yyoverflow
+ {
+ /* Give user a chance to reallocate the stack. Use copies of
+ these so that the &'s don't force the real ones into
+ memory. */
+ YYSTYPE *yyvs1 = yyvs;
+ yytype_int16 *yyss1 = yyss;
+
+
+ /* Each stack pointer address is followed by the size of the
+ data in use in that stack, in bytes. This used to be a
+ conditional around just the two extra args, but that might
+ be undefined if yyoverflow is a macro. */
+ yyoverflow (YY_("memory exhausted"),
+ &yyss1, yysize * sizeof (*yyssp),
+ &yyvs1, yysize * sizeof (*yyvsp),
+
+ &yystacksize);
+
+ yyss = yyss1;
+ yyvs = yyvs1;
+ }
+#else /* no yyoverflow */
+# ifndef YYSTACK_RELOCATE
+ goto yyexhaustedlab;
+# else
+ /* Extend the stack our own way. */
+ if (YYMAXDEPTH <= yystacksize)
+ goto yyexhaustedlab;
+ yystacksize *= 2;
+ if (YYMAXDEPTH < yystacksize)
+ yystacksize = YYMAXDEPTH;
+
+ {
+ yytype_int16 *yyss1 = yyss;
+ union yyalloc *yyptr =
+ (union yyalloc *) YYSTACK_ALLOC (YYSTACK_BYTES (yystacksize));
+ if (! yyptr)
+ goto yyexhaustedlab;
+ YYSTACK_RELOCATE (yyss);
+ YYSTACK_RELOCATE (yyvs);
+
+# undef YYSTACK_RELOCATE
+ if (yyss1 != yyssa)
+ YYSTACK_FREE (yyss1);
+ }
+# endif
+#endif /* no yyoverflow */
+
+ yyssp = yyss + yysize - 1;
+ yyvsp = yyvs + yysize - 1;
+
+
+ YYDPRINTF ((stderr, "Stack size increased to %lu\n",
+ (unsigned long int) yystacksize));
+
+ if (yyss + yystacksize - 1 <= yyssp)
+ YYABORT;
+ }
+
+ YYDPRINTF ((stderr, "Entering state %d\n", yystate));
+
+ goto yybackup;
+
+/*-----------.
+| yybackup. |
+`-----------*/
+yybackup:
+
+ /* Do appropriate processing given the current state. Read a
+ look-ahead token if we need one and don't already have one. */
+
+ /* First try to decide what to do without reference to look-ahead token. */
+ yyn = yypact[yystate];
+ if (yyn == YYPACT_NINF)
+ goto yydefault;
+
+ /* Not known => get a look-ahead token if don't already have one. */
+
+ /* YYCHAR is either YYEMPTY or YYEOF or a valid look-ahead symbol. */
+ if (yychar == YYEMPTY)
+ {
+ YYDPRINTF ((stderr, "Reading a token: "));
+ yychar = YYLEX;
+ }
+
+ if (yychar <= YYEOF)
+ {
+ yychar = yytoken = YYEOF;
+ YYDPRINTF ((stderr, "Now at end of input.\n"));
+ }
+ else
+ {
+ yytoken = YYTRANSLATE (yychar);
+ YY_SYMBOL_PRINT ("Next token is", yytoken, &yylval, &yylloc);
+ }
+
+ /* If the proper action on seeing token YYTOKEN is to reduce or to
+ detect an error, take that action. */
+ yyn += yytoken;
+ if (yyn < 0 || YYLAST < yyn || yycheck[yyn] != yytoken)
+ goto yydefault;
+ yyn = yytable[yyn];
+ if (yyn <= 0)
+ {
+ if (yyn == 0 || yyn == YYTABLE_NINF)
+ goto yyerrlab;
+ yyn = -yyn;
+ goto yyreduce;
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ /* Count tokens shifted since error; after three, turn off error
+ status. */
+ if (yyerrstatus)
+ yyerrstatus--;
+
+ /* Shift the look-ahead token. */
+ YY_SYMBOL_PRINT ("Shifting", yytoken, &yylval, &yylloc);
+
+ /* Discard the shifted token unless it is eof. */
+ if (yychar != YYEOF)
+ yychar = YYEMPTY;
+
+ yystate = yyn;
+ *++yyvsp = yylval;
+
+ goto yynewstate;
+
+
+/*-----------------------------------------------------------.
+| yydefault -- do the default action for the current state. |
+`-----------------------------------------------------------*/
+yydefault:
+ yyn = yydefact[yystate];
+ if (yyn == 0)
+ goto yyerrlab;
+ goto yyreduce;
+
+
+/*-----------------------------.
+| yyreduce -- Do a reduction. |
+`-----------------------------*/
+yyreduce:
+ /* yyn is the number of a rule to reduce with. */
+ yylen = yyr2[yyn];
+
+ /* If YYLEN is nonzero, implement the default value of the action:
+ `$$ = $1'.
+
+ Otherwise, the following line sets YYVAL to garbage.
+ This behavior is undocumented and Bison
+ users should not rely upon it. Assigning to YYVAL
+ unconditionally makes the parser a bit smaller, and it avoids a
+ GCC warning that YYVAL may be used uninitialized. */
+ yyval = yyvsp[1-yylen];
+
+
+ YY_REDUCE_PRINT (yyn);
+ switch (yyn)
+ {
+ case 4:
+#line 121 "mimeparser.y"
+ {
+ mm_context_attachpart(pstate->ctx, pstate->current_mimepart);
+ pstate->current_mimepart = mm_mimepart_new();
+ pstate->have_contenttype = 0;
+ }
+ break;
+
+ case 5:
+#line 127 "mimeparser.y"
+ {
+ dprintf2(pstate,"This was a multipart message\n");
+ }
+ break;
+
+ case 6:
+#line 134 "mimeparser.y"
+ {
+ dprintf2(pstate,"This was a single part message\n");
+ mm_context_attachpart(pstate->ctx, pstate->current_mimepart);
+ }
+ break;
+
+ case 8:
+#line 144 "mimeparser.y"
+ {
+ /* If we did not find a Content-Type header for the current
+ * MIME part (or envelope), we create one and attach it.
+ * According to the RFC, a type of "text/plain" and a
+ * charset of "us-ascii" can be assumed.
+ */
+ struct mm_content *ct;
+ struct mm_param *param;
+
+ if (!pstate->have_contenttype) {
+ ct = mm_content_new();
+ mm_content_settype(ct, "text/plain");
+
+ param = mm_param_new();
+ param->name = xstrdup("charset");
+ param->value = xstrdup("us-ascii");
+
+ mm_content_attachtypeparam(ct, param);
+ mm_mimepart_attachcontenttype(pstate->current_mimepart, ct);
+ }
+ pstate->have_contenttype = 0;
+ }
+ break;
+
+ case 10:
+#line 172 "mimeparser.y"
+ {
+ char *preamble;
+ size_t offset;
+
+ if ((yyvsp[(1) - (1)].position).start != (yyvsp[(1) - (1)].position).end) {
+ preamble = PARSE_readmessagepart(0, (yyvsp[(1) - (1)].position).start, (yyvsp[(1) - (1)].position).end,
+ &offset,yyscanner,pstate);
+ if (preamble == NULL) {
+ return(-1);
+ }
+ pstate->ctx->preamble = preamble;
+ dprintf2(pstate,"PREAMBLE:\n%s\n", preamble);
+ }
+ }
+ break;
+
+ case 12:
+#line 191 "mimeparser.y"
+ {
+ }
+ break;
+
+ case 16:
+#line 204 "mimeparser.y"
+ {
+
+ if (mm_context_attachpart(pstate->ctx, pstate->current_mimepart) == -1) {
+ mm_errno = MM_ERROR_ERRNO;
+ return(-1);
+ }
+
+ pstate->temppart = mm_mimepart_new();
+ pstate->current_mimepart = pstate->temppart;
+ pstate->mime_parts++;
+ }
+ break;
+
+ case 18:
+#line 221 "mimeparser.y"
+ {
+ pstate->have_contenttype = 1;
+ if (mm_content_iscomposite(pstate->envelope->type)) {
+ pstate->ctx->messagetype = MM_MSGTYPE_MULTIPART;
+ } else {
+ pstate->ctx->messagetype = MM_MSGTYPE_FLAT;
+ }
+ }
+ break;
+
+ case 22:
+#line 237 "mimeparser.y"
+ {
+ if (pstate->parsemode != MM_PARSE_LOOSE) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("invalid header encountered");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(-1);
+ } else {
+ /* TODO: attach MM_WARNING_INVHDR */
+ }
+ }
+ break;
+
+ case 23:
+#line 251 "mimeparser.y"
+ {
+ struct mm_mimeheader *hdr;
+ hdr = mm_mimeheader_generate((yyvsp[(1) - (4)].string), (yyvsp[(3) - (4)].string));
+ mm_mimepart_attachheader(pstate->current_mimepart, hdr);
+ }
+ break;
+
+ case 24:
+#line 258 "mimeparser.y"
+ {
+ struct mm_mimeheader *hdr;
+
+ if (pstate->parsemode != MM_PARSE_LOOSE) {
+ mm_errno = MM_ERROR_MIME;
+ mm_error_setmsg("invalid header encountered");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(-1);
+ } else {
+ /* TODO: attach MM_WARNING_INVHDR */
+ }
+
+ hdr = mm_mimeheader_generate((yyvsp[(1) - (3)].string), xstrdup(""));
+ mm_mimepart_attachheader(pstate->current_mimepart, hdr);
+ }
+ break;
+
+ case 25:
+#line 277 "mimeparser.y"
+ {
+ mm_content_settype(pstate->ctype, "%s", (yyvsp[(3) - (4)].string));
+ mm_mimepart_attachcontenttype(pstate->current_mimepart, pstate->ctype);
+ dprintf2(pstate,"Content-Type -> %s\n", (yyvsp[(3) - (4)].string));
+ pstate->ctype = mm_content_new();
+ }
+ break;
+
+ case 26:
+#line 285 "mimeparser.y"
+ {
+ mm_content_settype(pstate->ctype, "%s", (yyvsp[(3) - (5)].string));
+ mm_mimepart_attachcontenttype(pstate->current_mimepart, pstate->ctype);
+ dprintf2(pstate,"Content-Type (P) -> %s\n", (yyvsp[(3) - (5)].string));
+ pstate->ctype = mm_content_new();
+ }
+ break;
+
+ case 27:
+#line 295 "mimeparser.y"
+ {
+ dprintf2(pstate,"Content-Disposition -> %s\n", (yyvsp[(3) - (4)].string));
+ pstate->ctype->disposition_type = xstrdup((yyvsp[(3) - (4)].string));
+ }
+ break;
+
+ case 28:
+#line 301 "mimeparser.y"
+ {
+ dprintf2(pstate,"Content-Disposition (P) -> %s; params\n", (yyvsp[(3) - (5)].string));
+ pstate->ctype->disposition_type = xstrdup((yyvsp[(3) - (5)].string));
+ }
+ break;
+
+ case 29:
+#line 309 "mimeparser.y"
+ {
+ /*
+ * According to RFC 2183, the content disposition value may
+ * only be "inline", "attachment" or an extension token. We
+ * catch invalid values here if we are not in loose parsing
+ * mode.
+ */
+ if (strcasecmp((yyvsp[(1) - (1)].string), "inline") && strcasecmp((yyvsp[(1) - (1)].string), "attachment")
+ && strncasecmp((yyvsp[(1) - (1)].string), "X-", 2)) {
+ if (pstate->parsemode != MM_PARSE_LOOSE) {
+ mm_errno = MM_ERROR_MIME;
+ mm_error_setmsg("invalid content-disposition");
+ return(-1);
+ }
+ } else {
+ /* TODO: attach MM_WARNING_INVHDR */
+ }
+ (yyval.string) = (yyvsp[(1) - (1)].string);
+ }
+ break;
+
+ case 30:
+#line 332 "mimeparser.y"
+ {
+ dprintf2(pstate,"Content-Transfer-Encoding -> %s\n", (yyvsp[(3) - (4)].string));
+ }
+ break;
+
+ case 31:
+#line 339 "mimeparser.y"
+ {
+ dprintf2(pstate,"MIME-Version -> '%s'\n", (yyvsp[(3) - (4)].string));
+ }
+ break;
+
+ case 35:
+#line 356 "mimeparser.y"
+ {
+ char type[255];
+ snprintf(type, sizeof(type), "%s/%s", (yyvsp[(1) - (3)].string), (yyvsp[(3) - (3)].string));
+ (yyval.string) = type;
+ }
+ break;
+
+ case 38:
+#line 369 "mimeparser.y"
+ {
+ if (pstate->parsemode != MM_PARSE_LOOSE) {
+ mm_errno = MM_ERROR_MIME;
+ mm_error_setmsg("invalid Content-Type header");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(-1);
+ } else {
+ /* TODO: attach MM_WARNING_INVHDR */
+ }
+ }
+ break;
+
+ case 41:
+#line 387 "mimeparser.y"
+ {
+ if (pstate->parsemode != MM_PARSE_LOOSE) {
+ mm_errno = MM_ERROR_MIME;
+ mm_error_setmsg("invalid Content-Disposition header");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(-1);
+ } else {
+ /* TODO: attach MM_WARNING_INVHDR */
+ }
+ }
+ break;
+
+ case 42:
+#line 401 "mimeparser.y"
+ {
+ struct mm_param *param;
+ param = mm_param_new();
+
+ dprintf2(pstate,"Param: '%s', Value: '%s'\n", (yyvsp[(1) - (3)].string), (yyvsp[(3) - (3)].string));
+
+ /* Catch an eventual boundary identifier */
+ if (!strcasecmp((yyvsp[(1) - (3)].string), "boundary")) {
+ if (pstate->lstate.boundary_string == NULL) {
+ set_boundary((yyvsp[(3) - (3)].string),pstate);
+ } else {
+ if (pstate->parsemode != MM_PARSE_LOOSE) {
+ mm_errno = MM_ERROR_MIME;
+ mm_error_setmsg("duplicate boundary "
+ "found");
+ return -1;
+ } else {
+ /* TODO: attach MM_WARNING_DUPPARAM */
+ }
+ }
+ }
+
+ param->name = xstrdup((yyvsp[(1) - (3)].string));
+ param->value = xstrdup((yyvsp[(3) - (3)].string));
+
+ mm_content_attachtypeparam(pstate->ctype, param);
+ }
+ break;
+
+ case 43:
+#line 432 "mimeparser.y"
+ {
+ struct mm_param *param;
+ param = mm_param_new();
+
+ param->name = xstrdup((yyvsp[(1) - (3)].string));
+ param->value = xstrdup((yyvsp[(3) - (3)].string));
+
+ mm_content_attachdispositionparam(pstate->ctype, param);
+
+ }
+ break;
+
+ case 44:
+#line 446 "mimeparser.y"
+ {
+ dprintf2(pstate,"contenttype_param_val: WORD=%s\n", (yyvsp[(1) - (1)].string));
+ (yyval.string) = (yyvsp[(1) - (1)].string);
+ }
+ break;
+
+ case 45:
+#line 452 "mimeparser.y"
+ {
+ dprintf2(pstate,"contenttype_param_val: TSPECIAL\n");
+ /* For broken MIME implementation */
+ if (pstate->parsemode != MM_PARSE_LOOSE) {
+ mm_errno = MM_ERROR_MIME;
+ mm_error_setmsg("tspecial without quotes");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(-1);
+ } else {
+ /* TODO: attach MM_WARNING_INVAL */
+ }
+ (yyval.string) = (yyvsp[(1) - (1)].string);
+ }
+ break;
+
+ case 46:
+#line 467 "mimeparser.y"
+ {
+ dprintf2(pstate,"contenttype_param_val: \"TSPECIAL\"\n" );
+ (yyval.string) = (yyvsp[(2) - (3)].string);
+ }
+ break;
+
+ case 47:
+#line 475 "mimeparser.y"
+ {
+ dprintf2(pstate,"End of headers at line %d\n", pstate->lstate.lineno);
+ }
+ break;
+
+ case 48:
+#line 482 "mimeparser.y"
+ {
+ if (pstate->lstate.boundary_string == NULL) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("internal incosistency");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(-1);
+ }
+ if (strcmp(pstate->lstate.boundary_string, (yyvsp[(1) - (2)].string))) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("invalid boundary: '%s' (%d)", (yyvsp[(1) - (2)].string), strlen((yyvsp[(1) - (2)].string)));
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(-1);
+ }
+ dprintf2(pstate,"New MIME part... (%s)\n", (yyvsp[(1) - (2)].string));
+ }
+ break;
+
+ case 49:
+#line 501 "mimeparser.y"
+ {
+ if (pstate->lstate.endboundary_string == NULL) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("internal incosistency");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(-1);
+ }
+ if (strcmp(pstate->lstate.endboundary_string, (yyvsp[(1) - (1)].string))) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("invalid end boundary: %s", (yyvsp[(1) - (1)].string));
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(-1);
+ }
+ dprintf2(pstate,"End of MIME message\n");
+ }
+ break;
+
+ case 50:
+#line 520 "mimeparser.y"
+ {
+ char *body;
+ size_t offset;
+
+ dprintf2(pstate,"BODY (%d/%d), SIZE %d\n", (yyvsp[(1) - (1)].position).start, (yyvsp[(1) - (1)].position).end, (yyvsp[(1) - (1)].position).end - (yyvsp[(1) - (1)].position).start);
+
+ body = PARSE_readmessagepart((yyvsp[(1) - (1)].position).opaque_start, (yyvsp[(1) - (1)].position).start, (yyvsp[(1) - (1)].position).end,
+ &offset,yyscanner,pstate);
+
+ if (body == NULL) {
+ return(-1);
+ }
+ pstate->current_mimepart->opaque_body = body;
+ pstate->current_mimepart->body = body + offset;
+ pstate->current_mimepart->opaque_length = (yyvsp[(1) - (1)].position).end - (yyvsp[(1) - (1)].position).start - 2 + offset;
+ pstate->current_mimepart->length = pstate->current_mimepart->opaque_length - offset;
+ }
+ break;
+
+
+/* Line 1267 of yacc.c. */
+#line 1915 "mimeparser.tab.c"
+ default: break;
+ }
+ YY_SYMBOL_PRINT ("-> $$ =", yyr1[yyn], &yyval, &yyloc);
+
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+
+ *++yyvsp = yyval;
+
+
+ /* Now `shift' the result of the reduction. Determine what state
+ that goes to, based on the state we popped back to and the rule
+ number reduced by. */
+
+ yyn = yyr1[yyn];
+
+ yystate = yypgoto[yyn - YYNTOKENS] + *yyssp;
+ if (0 <= yystate && yystate <= YYLAST && yycheck[yystate] == *yyssp)
+ yystate = yytable[yystate];
+ else
+ yystate = yydefgoto[yyn - YYNTOKENS];
+
+ goto yynewstate;
+
+
+/*------------------------------------.
+| yyerrlab -- here on detecting error |
+`------------------------------------*/
+yyerrlab:
+ /* If not already recovering from an error, report this error. */
+ if (!yyerrstatus)
+ {
+ ++yynerrs;
+#if ! YYERROR_VERBOSE
+ yyerror (pstate, yyscanner, YY_("syntax error"));
+#else
+ {
+ YYSIZE_T yysize = yysyntax_error (0, yystate, yychar);
+ if (yymsg_alloc < yysize && yymsg_alloc < YYSTACK_ALLOC_MAXIMUM)
+ {
+ YYSIZE_T yyalloc = 2 * yysize;
+ if (! (yysize <= yyalloc && yyalloc <= YYSTACK_ALLOC_MAXIMUM))
+ yyalloc = YYSTACK_ALLOC_MAXIMUM;
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+ yymsg = (char *) YYSTACK_ALLOC (yyalloc);
+ if (yymsg)
+ yymsg_alloc = yyalloc;
+ else
+ {
+ yymsg = yymsgbuf;
+ yymsg_alloc = sizeof yymsgbuf;
+ }
+ }
+
+ if (0 < yysize && yysize <= yymsg_alloc)
+ {
+ (void) yysyntax_error (yymsg, yystate, yychar);
+ yyerror (pstate, yyscanner, yymsg);
+ }
+ else
+ {
+ yyerror (pstate, yyscanner, YY_("syntax error"));
+ if (yysize != 0)
+ goto yyexhaustedlab;
+ }
+ }
+#endif
+ }
+
+
+
+ if (yyerrstatus == 3)
+ {
+ /* If just tried and failed to reuse look-ahead token after an
+ error, discard it. */
+
+ if (yychar <= YYEOF)
+ {
+ /* Return failure if at end of input. */
+ if (yychar == YYEOF)
+ YYABORT;
+ }
+ else
+ {
+ yydestruct ("Error: discarding",
+ yytoken, &yylval, pstate, yyscanner);
+ yychar = YYEMPTY;
+ }
+ }
+
+ /* Else will try to reuse look-ahead token after shifting the error
+ token. */
+ goto yyerrlab1;
+
+
+/*---------------------------------------------------.
+| yyerrorlab -- error raised explicitly by YYERROR. |
+`---------------------------------------------------*/
+yyerrorlab:
+
+ /* Pacify compilers like GCC when the user code never invokes
+ YYERROR and the label yyerrorlab therefore never appears in user
+ code. */
+ if (/*CONSTCOND*/ 0)
+ goto yyerrorlab;
+
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYERROR. */
+ YYPOPSTACK (yylen);
+ yylen = 0;
+ YY_STACK_PRINT (yyss, yyssp);
+ yystate = *yyssp;
+ goto yyerrlab1;
+
+
+/*-------------------------------------------------------------.
+| yyerrlab1 -- common code for both syntax error and YYERROR. |
+`-------------------------------------------------------------*/
+yyerrlab1:
+ yyerrstatus = 3; /* Each real token shifted decrements this. */
+
+ for (;;)
+ {
+ yyn = yypact[yystate];
+ if (yyn != YYPACT_NINF)
+ {
+ yyn += YYTERROR;
+ if (0 <= yyn && yyn <= YYLAST && yycheck[yyn] == YYTERROR)
+ {
+ yyn = yytable[yyn];
+ if (0 < yyn)
+ break;
+ }
+ }
+
+ /* Pop the current state because it cannot handle the error token. */
+ if (yyssp == yyss)
+ YYABORT;
+
+
+ yydestruct ("Error: popping",
+ yystos[yystate], yyvsp, pstate, yyscanner);
+ YYPOPSTACK (1);
+ yystate = *yyssp;
+ YY_STACK_PRINT (yyss, yyssp);
+ }
+
+ if (yyn == YYFINAL)
+ YYACCEPT;
+
+ *++yyvsp = yylval;
+
+
+ /* Shift the error token. */
+ YY_SYMBOL_PRINT ("Shifting", yystos[yyn], yyvsp, yylsp);
+
+ yystate = yyn;
+ goto yynewstate;
+
+
+/*-------------------------------------.
+| yyacceptlab -- YYACCEPT comes here. |
+`-------------------------------------*/
+yyacceptlab:
+ yyresult = 0;
+ goto yyreturn;
+
+/*-----------------------------------.
+| yyabortlab -- YYABORT comes here. |
+`-----------------------------------*/
+yyabortlab:
+ yyresult = 1;
+ goto yyreturn;
+
+#ifndef yyoverflow
+/*-------------------------------------------------.
+| yyexhaustedlab -- memory exhaustion comes here. |
+`-------------------------------------------------*/
+yyexhaustedlab:
+ yyerror (pstate, yyscanner, YY_("memory exhausted"));
+ yyresult = 2;
+ /* Fall through. */
+#endif
+
+yyreturn:
+ if (yychar != YYEOF && yychar != YYEMPTY)
+ yydestruct ("Cleanup: discarding lookahead",
+ yytoken, &yylval, pstate, yyscanner);
+ /* Do not reclaim the symbols of the rule which action triggered
+ this YYABORT or YYACCEPT. */
+ YYPOPSTACK (yylen);
+ YY_STACK_PRINT (yyss, yyssp);
+ while (yyssp != yyss)
+ {
+ yydestruct ("Cleanup: popping",
+ yystos[*yyssp], yyvsp, pstate, yyscanner);
+ YYPOPSTACK (1);
+ }
+#ifndef yyoverflow
+ if (yyss != yyssa)
+ YYSTACK_FREE (yyss);
+#endif
+#if YYERROR_VERBOSE
+ if (yymsg != yymsgbuf)
+ YYSTACK_FREE (yymsg);
+#endif
+ /* Make sure YYID is used. */
+ return YYID (yyresult);
+}
+
+
+#line 539 "mimeparser.y"
+
+
+/*
+ * This function gets the specified part from the currently parsed message.
+ */
+static char *
+PARSE_readmessagepart(size_t opaque_start, size_t real_start, size_t end,
+ size_t *offset, yyscan_t yyscanner, struct parser_state *pstate)
+{
+ size_t body_size;
+ size_t current;
+ size_t start;
+ char *body;
+
+ /* calculate start and offset markers for the opaque and
+ * header stripped body message.
+ */
+ if (opaque_start > 0) {
+ /* Multipart message */
+ if (real_start) {
+ if (real_start < opaque_start) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("internal incosistency (S:%d/O:%d)",
+ real_start,
+ opaque_start);
+ return(NULL);
+ }
+ start = opaque_start;
+ *offset = real_start - start;
+ /* Flat message */
+ } else {
+ start = opaque_start;
+ *offset = 0;
+ }
+ } else {
+ start = real_start;
+ *offset = 0;
+ }
+
+ /* The next three cases should NOT happen anytime */
+ if (end <= start) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("internal incosistency,2");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(NULL);
+ }
+ if (start < *offset) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("internal incosistency, S:%d,O:%d,L:%d", start, offset, pstate->lstate.lineno);
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(NULL);
+ }
+ if (start < 0 || end < 0) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("internal incosistency,4");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(NULL);
+ }
+
+ /* XXX: do we want to enforce a maximum body size? make it a
+ * parser option? */
+
+ /* Read in the body message */
+ body_size = end - start;
+
+ if (body_size < 1) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("size of body cannot be < 1");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(NULL);
+ }
+
+ body = (char *)malloc(body_size + 1);
+ if (body == NULL) {
+ mm_errno = MM_ERROR_ERRNO;
+ return(NULL);
+ }
+
+ /* Get the message body either from a stream or a memory
+ * buffer.
+ */
+ if (mimeparser_yyget_in(yyscanner) != NULL) {
+ FILE *x = mimeparser_yyget_in(yyscanner);
+ current = ftell(x);
+ fseek(x, start - 1, SEEK_SET);
+ fread(body, body_size - 1, 1, x);
+ fseek(x, current, SEEK_SET);
+ } else if (pstate->lstate.message_buffer != NULL) {
+ strlcpy(body, pstate->lstate.message_buffer + start - 1, body_size);
+ }
+
+ return(body);
+
+}
+
+int
+yyerror(struct parser_state *pstate, void *yyscanner, const char *str)
+{
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("%s", str);
+ mm_error_setlineno(pstate->lstate.lineno);
+ return -1;
+}
+
+int
+mimeparser_yywrap(void)
+{
+ return 1;
+}
+
+/**
+ * Sets the boundary value for the current message
+ */
+int
+set_boundary(char *str, struct parser_state *pstate)
+{
+ size_t blen;
+
+ blen = strlen(str);
+
+ pstate->lstate.boundary_string = (char *)malloc(blen + 3);
+ pstate->lstate.endboundary_string = (char *)malloc(blen + 5);
+
+ if (pstate->lstate.boundary_string == NULL || pstate->lstate.endboundary_string == NULL) {
+ if (pstate->lstate.boundary_string != NULL) {
+ free(pstate->lstate.boundary_string);
+ }
+ if (pstate->lstate.endboundary_string != NULL) {
+ free(pstate->lstate.endboundary_string);
+ }
+ return -1;
+ }
+
+ pstate->ctx->boundary = xstrdup(str);
+
+ snprintf(pstate->lstate.boundary_string, blen + 3, "--%s", str);
+ snprintf(pstate->lstate.endboundary_string, blen + 5, "--%s--", str);
+
+ return 0;
+}
+
+/**
+ * Debug printf()
+ */
+int
+dprintf2(struct parser_state *pstate, const char *fmt, ...)
+{
+ va_list ap;
+ char *msg;
+ if (pstate->debug == 0) return 1;
+
+ va_start(ap, fmt);
+ vasprintf(&msg, fmt, ap);
+ va_end(ap);
+
+ fprintf(stderr, "%s", msg);
+ free(msg);
+
+ return 0;
+
+}
+
+void reset_environ(struct parser_state *pstate)
+{
+ pstate->lstate.lineno = 0;
+ pstate->lstate.boundary_string = NULL;
+ pstate->lstate.endboundary_string = NULL;
+ pstate->lstate.message_buffer = NULL;
+ pstate->mime_parts = 0;
+ pstate->debug = 0;
+ pstate->envelope = NULL;
+ pstate->temppart = NULL;
+ pstate->ctype = NULL;
+ pstate->current_mimepart = NULL;
+
+ pstate->have_contenttype = 0;
+}
+/**
+ * Initializes the parser engine.
+ */
+int
+PARSER_initialize(struct parser_state *pstate, void *yyscanner)
+{
+ void reset_lexer_state(void *yyscanner, struct parser_state *);
+#if 0
+ if (pstate->ctx != NULL) {
+ xfree(pstate->ctx);
+ pstate->ctx = NULL;
+ }
+ if (pstate->envelope != NULL) {
+ xfree(pstate->envelope);
+ pstate->envelope = NULL;
+ }
+ if (pstate->ctype != NULL) {
+ xfree(pstate->ctype);
+ pstate->ctype = NULL;
+ }
+#endif
+ /* yydebug = 1; */
+ reset_environ(pstate);
+ reset_lexer_state(yyscanner,pstate);
+
+ pstate->envelope = mm_mimepart_new();
+ pstate->current_mimepart = pstate->envelope;
+ pstate->ctype = mm_content_new();
+
+ pstate->have_contenttype = 0;
+
+ return 1;
+}
+
+
+
diff --git a/main/minimime/mimeparser.tab.h b/main/minimime/mimeparser.tab.h
new file mode 100644
index 000000000..6cf3f22a2
--- /dev/null
+++ b/main/minimime/mimeparser.tab.h
@@ -0,0 +1,112 @@
+/* A Bison parser, made by GNU Bison 2.3. */
+
+/* Skeleton interface for Bison's Yacc-like parsers in C
+
+ Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006
+ Free Software Foundation, Inc.
+
+ This program 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 2, or (at your option)
+ any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ Boston, MA 02110-1301, USA. */
+
+/* As a special exception, you may create a larger work that contains
+ part or all of the Bison parser skeleton and distribute that work
+ under terms of your choice, so long as that work isn't itself a
+ parser generator using the skeleton or a modified version thereof
+ as a parser skeleton. Alternatively, if you modify or redistribute
+ the parser skeleton itself, you may (at your option) remove this
+ special exception, which will cause the skeleton and the resulting
+ Bison output files to be licensed under the GNU General Public
+ License without this special exception.
+
+ This special exception was added by the Free Software Foundation in
+ version 2.2 of Bison. */
+
+/* Tokens. */
+#ifndef YYTOKENTYPE
+# define YYTOKENTYPE
+ /* Put the tokens into the symbol table, so that GDB and other debuggers
+ know about them. */
+ enum yytokentype {
+ ANY = 258,
+ COLON = 259,
+ DASH = 260,
+ DQUOTE = 261,
+ ENDOFHEADERS = 262,
+ EOL = 263,
+ EOM = 264,
+ EQUAL = 265,
+ MIMEVERSION_HEADER = 266,
+ SEMICOLON = 267,
+ CONTENTDISPOSITION_HEADER = 268,
+ CONTENTENCODING_HEADER = 269,
+ CONTENTTYPE_HEADER = 270,
+ MAIL_HEADER = 271,
+ HEADERVALUE = 272,
+ BOUNDARY = 273,
+ ENDBOUNDARY = 274,
+ CONTENTTYPE_VALUE = 275,
+ TSPECIAL = 276,
+ WORD = 277,
+ BODY = 278,
+ PREAMBLE = 279,
+ POSTAMBLE = 280
+ };
+#endif
+/* Tokens. */
+#define ANY 258
+#define COLON 259
+#define DASH 260
+#define DQUOTE 261
+#define ENDOFHEADERS 262
+#define EOL 263
+#define EOM 264
+#define EQUAL 265
+#define MIMEVERSION_HEADER 266
+#define SEMICOLON 267
+#define CONTENTDISPOSITION_HEADER 268
+#define CONTENTENCODING_HEADER 269
+#define CONTENTTYPE_HEADER 270
+#define MAIL_HEADER 271
+#define HEADERVALUE 272
+#define BOUNDARY 273
+#define ENDBOUNDARY 274
+#define CONTENTTYPE_VALUE 275
+#define TSPECIAL 276
+#define WORD 277
+#define BODY 278
+#define PREAMBLE 279
+#define POSTAMBLE 280
+
+
+
+
+#if ! defined YYSTYPE && ! defined YYSTYPE_IS_DECLARED
+typedef union YYSTYPE
+#line 69 "mimeparser.y"
+{
+ int number;
+ char *string;
+ struct s_position position;
+}
+/* Line 1529 of yacc.c. */
+#line 105 "mimeparser.tab.h"
+ YYSTYPE;
+# define yystype YYSTYPE /* obsolescent; will be withdrawn */
+# define YYSTYPE_IS_DECLARED 1
+# define YYSTYPE_IS_TRIVIAL 1
+#endif
+
+
+
diff --git a/main/minimime/mimeparser.y b/main/minimime/mimeparser.y
new file mode 100644
index 000000000..18f409f35
--- /dev/null
+++ b/main/minimime/mimeparser.y
@@ -0,0 +1,750 @@
+%{
+/*
+ * Copyright (c) 2004 Jann Fischer. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/**
+ * These are the grammatic definitions in yacc syntax to parse MIME conform
+ * messages.
+ *
+ * TODO:
+ * - honour parse flags passed to us (partly done)
+ * - parse Content-Disposition header (partly done)
+ * - parse Content-Encoding header
+ */
+#include <stdio.h>
+#include <stdarg.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "mimeparser.h"
+#include "mm.h"
+#include "mm_internal.h"
+
+int set_boundary(char *,struct parser_state *);
+int mimeparser_yywrap(void);
+void reset_environ(struct parser_state *pstate);
+int PARSER_initialize(struct parser_state *pstate, void *yyscanner);
+
+typedef void *yyscan_t;
+
+static char *PARSE_readmessagepart(size_t, size_t, size_t, size_t *,yyscan_t, struct parser_state *);
+FILE *mimeparser_yyget_in (yyscan_t yyscanner );
+
+%}
+
+%pure-parser
+%parse-param {struct parser_state *pstate}
+%parse-param {void *yyscanner}
+%lex-param {void *yyscanner}
+
+%union
+{
+ int number;
+ char *string;
+ struct s_position position;
+}
+
+%token ANY
+%token COLON
+%token DASH
+%token DQUOTE
+%token ENDOFHEADERS
+%token EOL
+%token EOM
+%token EQUAL
+%token MIMEVERSION_HEADER
+%token SEMICOLON
+
+%token <string> CONTENTDISPOSITION_HEADER
+%token <string> CONTENTENCODING_HEADER
+%token <string> CONTENTTYPE_HEADER
+%token <string> MAIL_HEADER
+%token <string> HEADERVALUE
+%token <string> BOUNDARY
+%token <string> ENDBOUNDARY
+%token <string> CONTENTTYPE_VALUE
+%token <string> TSPECIAL
+%token <string> WORD
+
+%token <position> BODY
+%token <position> PREAMBLE
+%token <position> POSTAMBLE
+
+%type <string> content_disposition
+%type <string> contenttype_parameter_value
+%type <string> mimetype
+%type <string> body
+
+%start message
+
+%%
+
+/* This is a parser for a MIME-conform message, which is in either single
+ * part or multi part format.
+ */
+message :
+ multipart_message
+ |
+ singlepart_message
+ ;
+
+multipart_message:
+ headers preamble
+ {
+ mm_context_attachpart(pstate->ctx, pstate->current_mimepart);
+ pstate->current_mimepart = mm_mimepart_new();
+ pstate->have_contenttype = 0;
+ }
+ mimeparts endboundary postamble
+ {
+ dprintf2(pstate,"This was a multipart message\n");
+ }
+ ;
+
+singlepart_message:
+ headers body
+ {
+ dprintf2(pstate,"This was a single part message\n");
+ mm_context_attachpart(pstate->ctx, pstate->current_mimepart);
+ }
+ ;
+
+headers :
+ header headers
+ |
+ end_headers
+ {
+ /* If we did not find a Content-Type header for the current
+ * MIME part (or envelope), we create one and attach it.
+ * According to the RFC, a type of "text/plain" and a
+ * charset of "us-ascii" can be assumed.
+ */
+ struct mm_content *ct;
+ struct mm_param *param;
+
+ if (!pstate->have_contenttype) {
+ ct = mm_content_new();
+ mm_content_settype(ct, "text/plain");
+
+ param = mm_param_new();
+ param->name = xstrdup("charset");
+ param->value = xstrdup("us-ascii");
+
+ mm_content_attachtypeparam(ct, param);
+ mm_mimepart_attachcontenttype(pstate->current_mimepart, ct);
+ }
+ pstate->have_contenttype = 0;
+ }
+ |
+ header
+ ;
+
+preamble:
+ PREAMBLE
+ {
+ char *preamble;
+ size_t offset;
+
+ if ($1.start != $1.end) {
+ preamble = PARSE_readmessagepart(0, $1.start, $1.end,
+ &offset,yyscanner,pstate);
+ if (preamble == NULL) {
+ return(-1);
+ }
+ pstate->ctx->preamble = preamble;
+ dprintf2(pstate,"PREAMBLE:\n%s\n", preamble);
+ }
+ }
+ |
+ ;
+
+postamble:
+ POSTAMBLE
+ {
+ }
+ |
+ ;
+
+mimeparts:
+ mimeparts mimepart
+ |
+ mimepart
+ ;
+
+mimepart:
+ boundary headers body
+ {
+
+ if (mm_context_attachpart(pstate->ctx, pstate->current_mimepart) == -1) {
+ mm_errno = MM_ERROR_ERRNO;
+ return(-1);
+ }
+
+ pstate->temppart = mm_mimepart_new();
+ pstate->current_mimepart = pstate->temppart;
+ pstate->mime_parts++;
+ }
+ ;
+
+header :
+ mail_header
+ |
+ contenttype_header
+ {
+ pstate->have_contenttype = 1;
+ if (mm_content_iscomposite(pstate->envelope->type)) {
+ pstate->ctx->messagetype = MM_MSGTYPE_MULTIPART;
+ } else {
+ pstate->ctx->messagetype = MM_MSGTYPE_FLAT;
+ }
+ }
+ |
+ contentdisposition_header
+ |
+ contentencoding_header
+ |
+ mimeversion_header
+ |
+ invalid_header
+ {
+ if (pstate->parsemode != MM_PARSE_LOOSE) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("invalid header encountered");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(-1);
+ } else {
+ /* TODO: attach MM_WARNING_INVHDR */
+ }
+ }
+ ;
+
+mail_header:
+ MAIL_HEADER COLON WORD EOL
+ {
+ struct mm_mimeheader *hdr;
+ hdr = mm_mimeheader_generate($1, $3);
+ mm_mimepart_attachheader(pstate->current_mimepart, hdr);
+ }
+ |
+ MAIL_HEADER COLON EOL
+ {
+ struct mm_mimeheader *hdr;
+
+ if (pstate->parsemode != MM_PARSE_LOOSE) {
+ mm_errno = MM_ERROR_MIME;
+ mm_error_setmsg("invalid header encountered");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(-1);
+ } else {
+ /* TODO: attach MM_WARNING_INVHDR */
+ }
+
+ hdr = mm_mimeheader_generate($1, xstrdup(""));
+ mm_mimepart_attachheader(pstate->current_mimepart, hdr);
+ }
+ ;
+
+contenttype_header:
+ CONTENTTYPE_HEADER COLON mimetype EOL
+ {
+ mm_content_settype(pstate->ctype, "%s", $3);
+ mm_mimepart_attachcontenttype(pstate->current_mimepart, pstate->ctype);
+ dprintf2(pstate,"Content-Type -> %s\n", $3);
+ pstate->ctype = mm_content_new();
+ }
+ |
+ CONTENTTYPE_HEADER COLON mimetype contenttype_parameters EOL
+ {
+ mm_content_settype(pstate->ctype, "%s", $3);
+ mm_mimepart_attachcontenttype(pstate->current_mimepart, pstate->ctype);
+ dprintf2(pstate,"Content-Type (P) -> %s\n", $3);
+ pstate->ctype = mm_content_new();
+ }
+ ;
+
+contentdisposition_header:
+ CONTENTDISPOSITION_HEADER COLON content_disposition EOL
+ {
+ dprintf2(pstate,"Content-Disposition -> %s\n", $3);
+ pstate->ctype->disposition_type = xstrdup($3);
+ }
+ |
+ CONTENTDISPOSITION_HEADER COLON content_disposition content_disposition_parameters EOL
+ {
+ dprintf2(pstate,"Content-Disposition (P) -> %s; params\n", $3);
+ pstate->ctype->disposition_type = xstrdup($3);
+ }
+ ;
+
+content_disposition:
+ WORD
+ {
+ /*
+ * According to RFC 2183, the content disposition value may
+ * only be "inline", "attachment" or an extension token. We
+ * catch invalid values here if we are not in loose parsing
+ * mode.
+ */
+ if (strcasecmp($1, "inline") && strcasecmp($1, "attachment")
+ && strncasecmp($1, "X-", 2)) {
+ if (pstate->parsemode != MM_PARSE_LOOSE) {
+ mm_errno = MM_ERROR_MIME;
+ mm_error_setmsg("invalid content-disposition");
+ return(-1);
+ }
+ } else {
+ /* TODO: attach MM_WARNING_INVHDR */
+ }
+ $$ = $1;
+ }
+ ;
+
+contentencoding_header:
+ CONTENTENCODING_HEADER COLON WORD EOL
+ {
+ dprintf2(pstate,"Content-Transfer-Encoding -> %s\n", $3);
+ }
+ ;
+
+mimeversion_header:
+ MIMEVERSION_HEADER COLON WORD EOL
+ {
+ dprintf2(pstate,"MIME-Version -> '%s'\n", $3);
+ }
+ ;
+
+invalid_header:
+ any EOL
+ ;
+
+any:
+ any ANY
+ |
+ ANY
+ ;
+
+mimetype:
+ WORD '/' WORD
+ {
+ char type[255];
+ snprintf(type, sizeof(type), "%s/%s", $1, $3);
+ $$ = type;
+ }
+ ;
+
+contenttype_parameters:
+ SEMICOLON contenttype_parameter contenttype_parameters
+ |
+ SEMICOLON contenttype_parameter
+ |
+ SEMICOLON
+ {
+ if (pstate->parsemode != MM_PARSE_LOOSE) {
+ mm_errno = MM_ERROR_MIME;
+ mm_error_setmsg("invalid Content-Type header");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(-1);
+ } else {
+ /* TODO: attach MM_WARNING_INVHDR */
+ }
+ }
+ ;
+
+content_disposition_parameters:
+ SEMICOLON content_disposition_parameter content_disposition_parameters
+ |
+ SEMICOLON content_disposition_parameter
+ |
+ SEMICOLON
+ {
+ if (pstate->parsemode != MM_PARSE_LOOSE) {
+ mm_errno = MM_ERROR_MIME;
+ mm_error_setmsg("invalid Content-Disposition header");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(-1);
+ } else {
+ /* TODO: attach MM_WARNING_INVHDR */
+ }
+ }
+ ;
+
+contenttype_parameter:
+ WORD EQUAL contenttype_parameter_value
+ {
+ struct mm_param *param;
+ param = mm_param_new();
+
+ dprintf2(pstate,"Param: '%s', Value: '%s'\n", $1, $3);
+
+ /* Catch an eventual boundary identifier */
+ if (!strcasecmp($1, "boundary")) {
+ if (pstate->lstate.boundary_string == NULL) {
+ set_boundary($3,pstate);
+ } else {
+ if (pstate->parsemode != MM_PARSE_LOOSE) {
+ mm_errno = MM_ERROR_MIME;
+ mm_error_setmsg("duplicate boundary "
+ "found");
+ return -1;
+ } else {
+ /* TODO: attach MM_WARNING_DUPPARAM */
+ }
+ }
+ }
+
+ param->name = xstrdup($1);
+ param->value = xstrdup($3);
+
+ mm_content_attachtypeparam(pstate->ctype, param);
+ }
+ ;
+
+content_disposition_parameter:
+ WORD EQUAL contenttype_parameter_value
+ {
+ struct mm_param *param;
+ param = mm_param_new();
+
+ param->name = xstrdup($1);
+ param->value = xstrdup($3);
+
+ mm_content_attachdispositionparam(pstate->ctype, param);
+
+ }
+ ;
+
+contenttype_parameter_value:
+ WORD
+ {
+ dprintf2(pstate,"contenttype_param_val: WORD=%s\n", $1);
+ $$ = $1;
+ }
+ |
+ TSPECIAL
+ {
+ dprintf2(pstate,"contenttype_param_val: TSPECIAL\n");
+ /* For broken MIME implementation */
+ if (pstate->parsemode != MM_PARSE_LOOSE) {
+ mm_errno = MM_ERROR_MIME;
+ mm_error_setmsg("tspecial without quotes");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(-1);
+ } else {
+ /* TODO: attach MM_WARNING_INVAL */
+ }
+ $$ = $1;
+ }
+ |
+ '"' TSPECIAL '"'
+ {
+ dprintf2(pstate,"contenttype_param_val: \"TSPECIAL\"\n" );
+ $$ = $2;
+ }
+ ;
+
+end_headers :
+ ENDOFHEADERS
+ {
+ dprintf2(pstate,"End of headers at line %d\n", pstate->lstate.lineno);
+ }
+ ;
+
+boundary :
+ BOUNDARY EOL
+ {
+ if (pstate->lstate.boundary_string == NULL) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("internal incosistency");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(-1);
+ }
+ if (strcmp(pstate->lstate.boundary_string, $1)) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("invalid boundary: '%s' (%d)", $1, strlen($1));
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(-1);
+ }
+ dprintf2(pstate,"New MIME part... (%s)\n", $1);
+ }
+ ;
+
+endboundary :
+ ENDBOUNDARY
+ {
+ if (pstate->lstate.endboundary_string == NULL) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("internal incosistency");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(-1);
+ }
+ if (strcmp(pstate->lstate.endboundary_string, $1)) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("invalid end boundary: %s", $1);
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(-1);
+ }
+ dprintf2(pstate,"End of MIME message\n");
+ }
+ ;
+
+body:
+ BODY
+ {
+ char *body;
+ size_t offset;
+
+ dprintf2(pstate,"BODY (%d/%d), SIZE %d\n", $1.start, $1.end, $1.end - $1.start);
+
+ body = PARSE_readmessagepart($1.opaque_start, $1.start, $1.end,
+ &offset,yyscanner,pstate);
+
+ if (body == NULL) {
+ return(-1);
+ }
+ pstate->current_mimepart->opaque_body = body;
+ pstate->current_mimepart->body = body + offset;
+ pstate->current_mimepart->opaque_length = $1.end - $1.start - 2 + offset;
+ pstate->current_mimepart->length = pstate->current_mimepart->opaque_length - offset;
+ }
+ ;
+
+%%
+
+/*
+ * This function gets the specified part from the currently parsed message.
+ */
+static char *
+PARSE_readmessagepart(size_t opaque_start, size_t real_start, size_t end,
+ size_t *offset, yyscan_t yyscanner, struct parser_state *pstate)
+{
+ size_t body_size;
+ size_t current;
+ size_t start;
+ char *body;
+
+ /* calculate start and offset markers for the opaque and
+ * header stripped body message.
+ */
+ if (opaque_start > 0) {
+ /* Multipart message */
+ if (real_start) {
+ if (real_start < opaque_start) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("internal incosistency (S:%d/O:%d)",
+ real_start,
+ opaque_start);
+ return(NULL);
+ }
+ start = opaque_start;
+ *offset = real_start - start;
+ /* Flat message */
+ } else {
+ start = opaque_start;
+ *offset = 0;
+ }
+ } else {
+ start = real_start;
+ *offset = 0;
+ }
+
+ /* The next three cases should NOT happen anytime */
+ if (end <= start) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("internal incosistency,2");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(NULL);
+ }
+ if (start < *offset) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("internal incosistency, S:%d,O:%d,L:%d", start, offset, pstate->lstate.lineno);
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(NULL);
+ }
+ if (start < 0 || end < 0) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("internal incosistency,4");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(NULL);
+ }
+
+ /* XXX: do we want to enforce a maximum body size? make it a
+ * parser option? */
+
+ /* Read in the body message */
+ body_size = end - start;
+
+ if (body_size < 1) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("size of body cannot be < 1");
+ mm_error_setlineno(pstate->lstate.lineno);
+ return(NULL);
+ }
+
+ body = (char *)malloc(body_size + 1);
+ if (body == NULL) {
+ mm_errno = MM_ERROR_ERRNO;
+ return(NULL);
+ }
+
+ /* Get the message body either from a stream or a memory
+ * buffer.
+ */
+ if (mimeparser_yyget_in(yyscanner) != NULL) {
+ FILE *x = mimeparser_yyget_in(yyscanner);
+ current = ftell(x);
+ fseek(x, start - 1, SEEK_SET);
+ fread(body, body_size - 1, 1, x);
+ fseek(x, current, SEEK_SET);
+ } else if (pstate->lstate.message_buffer != NULL) {
+ strlcpy(body, pstate->lstate.message_buffer + start - 1, body_size);
+ }
+
+ return(body);
+
+}
+
+int
+yyerror(struct parser_state *pstate, void *yyscanner, const char *str)
+{
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("%s", str);
+ mm_error_setlineno(pstate->lstate.lineno);
+ return -1;
+}
+
+int
+mimeparser_yywrap(void)
+{
+ return 1;
+}
+
+/**
+ * Sets the boundary value for the current message
+ */
+int
+set_boundary(char *str, struct parser_state *pstate)
+{
+ size_t blen;
+
+ blen = strlen(str);
+
+ pstate->lstate.boundary_string = (char *)malloc(blen + 3);
+ pstate->lstate.endboundary_string = (char *)malloc(blen + 5);
+
+ if (pstate->lstate.boundary_string == NULL || pstate->lstate.endboundary_string == NULL) {
+ if (pstate->lstate.boundary_string != NULL) {
+ free(pstate->lstate.boundary_string);
+ }
+ if (pstate->lstate.endboundary_string != NULL) {
+ free(pstate->lstate.endboundary_string);
+ }
+ return -1;
+ }
+
+ pstate->ctx->boundary = xstrdup(str);
+
+ snprintf(pstate->lstate.boundary_string, blen + 3, "--%s", str);
+ snprintf(pstate->lstate.endboundary_string, blen + 5, "--%s--", str);
+
+ return 0;
+}
+
+/**
+ * Debug printf()
+ */
+int
+dprintf2(struct parser_state *pstate, const char *fmt, ...)
+{
+ va_list ap;
+ char *msg;
+ if (pstate->debug == 0) return 1;
+
+ va_start(ap, fmt);
+ vasprintf(&msg, fmt, ap);
+ va_end(ap);
+
+ fprintf(stderr, "%s", msg);
+ free(msg);
+
+ return 0;
+
+}
+
+void reset_environ(struct parser_state *pstate)
+{
+ pstate->lstate.lineno = 0;
+ pstate->lstate.boundary_string = NULL;
+ pstate->lstate.endboundary_string = NULL;
+ pstate->lstate.message_buffer = NULL;
+ pstate->mime_parts = 0;
+ pstate->debug = 0;
+ pstate->envelope = NULL;
+ pstate->temppart = NULL;
+ pstate->ctype = NULL;
+ pstate->current_mimepart = NULL;
+
+ pstate->have_contenttype = 0;
+}
+/**
+ * Initializes the parser engine.
+ */
+int
+PARSER_initialize(struct parser_state *pstate, void *yyscanner)
+{
+ void reset_lexer_state(void *yyscanner, struct parser_state *);
+#if 0
+ if (pstate->ctx != NULL) {
+ xfree(pstate->ctx);
+ pstate->ctx = NULL;
+ }
+ if (pstate->envelope != NULL) {
+ xfree(pstate->envelope);
+ pstate->envelope = NULL;
+ }
+ if (pstate->ctype != NULL) {
+ xfree(pstate->ctype);
+ pstate->ctype = NULL;
+ }
+#endif
+ /* yydebug = 1; */
+ reset_environ(pstate);
+ reset_lexer_state(yyscanner,pstate);
+
+ pstate->envelope = mm_mimepart_new();
+ pstate->current_mimepart = pstate->envelope;
+ pstate->ctype = mm_content_new();
+
+ pstate->have_contenttype = 0;
+
+ return 1;
+}
+
+
diff --git a/main/minimime/mimeparser.yy.c b/main/minimime/mimeparser.yy.c
new file mode 100644
index 000000000..40d6bd9fa
--- /dev/null
+++ b/main/minimime/mimeparser.yy.c
@@ -0,0 +1,2622 @@
+#line 2 "mimeparser.yy.c"
+
+#line 4 "mimeparser.yy.c"
+
+#define YY_INT_ALIGNED short int
+
+/* A lexical scanner generated by flex */
+
+#define FLEX_SCANNER
+#define YY_FLEX_MAJOR_VERSION 2
+#define YY_FLEX_MINOR_VERSION 5
+#define YY_FLEX_SUBMINOR_VERSION 33
+#if YY_FLEX_SUBMINOR_VERSION > 0
+#define FLEX_BETA
+#endif
+
+/* First, we deal with platform-specific or compiler-specific issues. */
+
+/* begin standard C headers. */
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <stdlib.h>
+
+/* end standard C headers. */
+
+/* flex integer type definitions */
+
+#ifndef FLEXINT_H
+#define FLEXINT_H
+
+/* C99 systems have <inttypes.h>. Non-C99 systems may or may not. */
+
+#if __STDC_VERSION__ >= 199901L
+
+/* C99 says to define __STDC_LIMIT_MACROS before including stdint.h,
+ * if you want the limit (max/min) macros for int types.
+ */
+#ifndef __STDC_LIMIT_MACROS
+#define __STDC_LIMIT_MACROS 1
+#endif
+
+#include <inttypes.h>
+typedef int8_t flex_int8_t;
+typedef uint8_t flex_uint8_t;
+typedef int16_t flex_int16_t;
+typedef uint16_t flex_uint16_t;
+typedef int32_t flex_int32_t;
+typedef uint32_t flex_uint32_t;
+#else
+typedef signed char flex_int8_t;
+typedef short int flex_int16_t;
+typedef int flex_int32_t;
+typedef unsigned char flex_uint8_t;
+typedef unsigned short int flex_uint16_t;
+typedef unsigned int flex_uint32_t;
+#endif /* ! C99 */
+
+/* Limits of integral types. */
+#ifndef INT8_MIN
+#define INT8_MIN (-128)
+#endif
+#ifndef INT16_MIN
+#define INT16_MIN (-32767-1)
+#endif
+#ifndef INT32_MIN
+#define INT32_MIN (-2147483647-1)
+#endif
+#ifndef INT8_MAX
+#define INT8_MAX (127)
+#endif
+#ifndef INT16_MAX
+#define INT16_MAX (32767)
+#endif
+#ifndef INT32_MAX
+#define INT32_MAX (2147483647)
+#endif
+#ifndef UINT8_MAX
+#define UINT8_MAX (255U)
+#endif
+#ifndef UINT16_MAX
+#define UINT16_MAX (65535U)
+#endif
+#ifndef UINT32_MAX
+#define UINT32_MAX (4294967295U)
+#endif
+
+#endif /* ! FLEXINT_H */
+
+#ifdef __cplusplus
+
+/* The "const" storage-class-modifier is valid. */
+#define YY_USE_CONST
+
+#else /* ! __cplusplus */
+
+#if __STDC__
+
+#define YY_USE_CONST
+
+#endif /* __STDC__ */
+#endif /* ! __cplusplus */
+
+#ifdef YY_USE_CONST
+#define yyconst const
+#else
+#define yyconst
+#endif
+
+/* Returned upon end-of-file. */
+#define YY_NULL 0
+
+/* Promotes a possibly negative, possibly signed char to an unsigned
+ * integer for use as an array index. If the signed char is negative,
+ * we want to instead treat it as an 8-bit unsigned char, hence the
+ * double cast.
+ */
+#define YY_SC_TO_UI(c) ((unsigned int) (unsigned char) c)
+
+/* An opaque pointer. */
+#ifndef YY_TYPEDEF_YY_SCANNER_T
+#define YY_TYPEDEF_YY_SCANNER_T
+typedef void* yyscan_t;
+#endif
+
+/* For convenience, these vars (plus the bison vars far below)
+ are macros in the reentrant scanner. */
+#define yyin yyg->yyin_r
+#define yyout yyg->yyout_r
+#define yyextra yyg->yyextra_r
+#define yyleng yyg->yyleng_r
+#define yytext yyg->yytext_r
+#define yylineno (YY_CURRENT_BUFFER_LVALUE->yy_bs_lineno)
+#define yycolumn (YY_CURRENT_BUFFER_LVALUE->yy_bs_column)
+#define yy_flex_debug yyg->yy_flex_debug_r
+
+int mimeparser_yylex_init (yyscan_t* scanner);
+
+/* Enter a start condition. This macro really ought to take a parameter,
+ * but we do it the disgusting crufty way forced on us by the ()-less
+ * definition of BEGIN.
+ */
+#define BEGIN yyg->yy_start = 1 + 2 *
+
+/* Translate the current start state into a value that can be later handed
+ * to BEGIN to return to the state. The YYSTATE alias is for lex
+ * compatibility.
+ */
+#define YY_START ((yyg->yy_start - 1) / 2)
+#define YYSTATE YY_START
+
+/* Action number for EOF rule of a given start state. */
+#define YY_STATE_EOF(state) (YY_END_OF_BUFFER + state + 1)
+
+/* Special action meaning "start processing a new file". */
+#define YY_NEW_FILE mimeparser_yyrestart(yyin ,yyscanner )
+
+#define YY_END_OF_BUFFER_CHAR 0
+
+/* Size of default input buffer. */
+#ifndef YY_BUF_SIZE
+#define YY_BUF_SIZE 16384
+#endif
+
+/* The state buf must be large enough to hold one state per character in the main buffer.
+ */
+#define YY_STATE_BUF_SIZE ((YY_BUF_SIZE + 2) * sizeof(yy_state_type))
+
+#ifndef YY_TYPEDEF_YY_BUFFER_STATE
+#define YY_TYPEDEF_YY_BUFFER_STATE
+typedef struct yy_buffer_state *YY_BUFFER_STATE;
+#endif
+
+#define EOB_ACT_CONTINUE_SCAN 0
+#define EOB_ACT_END_OF_FILE 1
+#define EOB_ACT_LAST_MATCH 2
+
+ /* Note: We specifically omit the test for yy_rule_can_match_eol because it requires
+ * access to the local variable yy_act. Since yyless() is a macro, it would break
+ * existing scanners that call yyless() from OUTSIDE mimeparser_yylex.
+ * One obvious solution it to make yy_act a global. I tried that, and saw
+ * a 5% performance hit in a non-yylineno scanner, because yy_act is
+ * normally declared as a register variable-- so it is not worth it.
+ */
+ #define YY_LESS_LINENO(n) \
+ do { \
+ int yyl;\
+ for ( yyl = n; yyl < yyleng; ++yyl )\
+ if ( yytext[yyl] == '\n' )\
+ --yylineno;\
+ }while(0)
+
+/* Return all but the first "n" matched characters back to the input stream. */
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ *yy_cp = yyg->yy_hold_char; \
+ YY_RESTORE_YY_MORE_OFFSET \
+ yyg->yy_c_buf_p = yy_cp = yy_bp + yyless_macro_arg - YY_MORE_ADJ; \
+ YY_DO_BEFORE_ACTION; /* set up yytext again */ \
+ } \
+ while ( 0 )
+
+#define unput(c) yyunput( c, yyg->yytext_ptr , yyscanner )
+
+/* The following is because we cannot portably get our hands on size_t
+ * (without autoconf's help, which isn't available because we want
+ * flex-generated scanners to compile on their own).
+ */
+
+#ifndef YY_TYPEDEF_YY_SIZE_T
+#define YY_TYPEDEF_YY_SIZE_T
+typedef unsigned int yy_size_t;
+#endif
+
+#ifndef YY_STRUCT_YY_BUFFER_STATE
+#define YY_STRUCT_YY_BUFFER_STATE
+struct yy_buffer_state
+ {
+ FILE *yy_input_file;
+
+ char *yy_ch_buf; /* input buffer */
+ char *yy_buf_pos; /* current position in input buffer */
+
+ /* Size of input buffer in bytes, not including room for EOB
+ * characters.
+ */
+ yy_size_t yy_buf_size;
+
+ /* Number of characters read into yy_ch_buf, not including EOB
+ * characters.
+ */
+ int yy_n_chars;
+
+ /* Whether we "own" the buffer - i.e., we know we created it,
+ * and can realloc() it to grow it, and should free() it to
+ * delete it.
+ */
+ int yy_is_our_buffer;
+
+ /* Whether this is an "interactive" input source; if so, and
+ * if we're using stdio for input, then we want to use getc()
+ * instead of fread(), to make sure we stop fetching input after
+ * each newline.
+ */
+ int yy_is_interactive;
+
+ /* Whether we're considered to be at the beginning of a line.
+ * If so, '^' rules will be active on the next match, otherwise
+ * not.
+ */
+ int yy_at_bol;
+
+ int yy_bs_lineno; /**< The line count. */
+ int yy_bs_column; /**< The column count. */
+
+ /* Whether to try to fill the input buffer when we reach the
+ * end of it.
+ */
+ int yy_fill_buffer;
+
+ int yy_buffer_status;
+
+#define YY_BUFFER_NEW 0
+#define YY_BUFFER_NORMAL 1
+ /* When an EOF's been seen but there's still some text to process
+ * then we mark the buffer as YY_EOF_PENDING, to indicate that we
+ * shouldn't try reading from the input source any more. We might
+ * still have a bunch of tokens to match, though, because of
+ * possible backing-up.
+ *
+ * When we actually see the EOF, we change the status to "new"
+ * (via mimeparser_yyrestart()), so that the user can continue scanning by
+ * just pointing yyin at a new input file.
+ */
+#define YY_BUFFER_EOF_PENDING 2
+
+ };
+#endif /* !YY_STRUCT_YY_BUFFER_STATE */
+
+/* We provide macros for accessing buffer states in case in the
+ * future we want to put the buffer states in a more general
+ * "scanner state".
+ *
+ * Returns the top of the stack, or NULL.
+ */
+#define YY_CURRENT_BUFFER ( yyg->yy_buffer_stack \
+ ? yyg->yy_buffer_stack[yyg->yy_buffer_stack_top] \
+ : NULL)
+
+/* Same as previous macro, but useful when we know that the buffer stack is not
+ * NULL or when we need an lvalue. For internal use only.
+ */
+#define YY_CURRENT_BUFFER_LVALUE yyg->yy_buffer_stack[yyg->yy_buffer_stack_top]
+
+void mimeparser_yyrestart (FILE *input_file ,yyscan_t yyscanner );
+void mimeparser_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+YY_BUFFER_STATE mimeparser_yy_create_buffer (FILE *file,int size ,yyscan_t yyscanner );
+void mimeparser_yy_delete_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void mimeparser_yy_flush_buffer (YY_BUFFER_STATE b ,yyscan_t yyscanner );
+void mimeparser_yypush_buffer_state (YY_BUFFER_STATE new_buffer ,yyscan_t yyscanner );
+void mimeparser_yypop_buffer_state (yyscan_t yyscanner );
+
+static void mimeparser_yyensure_buffer_stack (yyscan_t yyscanner );
+static void mimeparser_yy_load_buffer_state (yyscan_t yyscanner );
+static void mimeparser_yy_init_buffer (YY_BUFFER_STATE b,FILE *file ,yyscan_t yyscanner );
+
+#define YY_FLUSH_BUFFER mimeparser_yy_flush_buffer(YY_CURRENT_BUFFER ,yyscanner)
+
+YY_BUFFER_STATE mimeparser_yy_scan_buffer (char *base,yy_size_t size ,yyscan_t yyscanner );
+YY_BUFFER_STATE mimeparser_yy_scan_string (yyconst char *yy_str ,yyscan_t yyscanner );
+YY_BUFFER_STATE mimeparser_yy_scan_bytes (yyconst char *bytes,int len ,yyscan_t yyscanner );
+
+void *mimeparser_yyalloc (yy_size_t ,yyscan_t yyscanner );
+void *mimeparser_yyrealloc (void *,yy_size_t ,yyscan_t yyscanner );
+void mimeparser_yyfree (void * ,yyscan_t yyscanner );
+
+#define yy_new_buffer mimeparser_yy_create_buffer
+
+#define yy_set_interactive(is_interactive) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){ \
+ mimeparser_yyensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ mimeparser_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_is_interactive = is_interactive; \
+ }
+
+#define yy_set_bol(at_bol) \
+ { \
+ if ( ! YY_CURRENT_BUFFER ){\
+ mimeparser_yyensure_buffer_stack (yyscanner); \
+ YY_CURRENT_BUFFER_LVALUE = \
+ mimeparser_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner); \
+ } \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = at_bol; \
+ }
+
+#define YY_AT_BOL() (YY_CURRENT_BUFFER_LVALUE->yy_at_bol)
+
+/* Begin user sect3 */
+
+typedef unsigned char YY_CHAR;
+
+typedef int yy_state_type;
+
+#define yytext_ptr yytext_r
+
+static yy_state_type yy_get_previous_state (yyscan_t yyscanner );
+static yy_state_type yy_try_NUL_trans (yy_state_type current_state ,yyscan_t yyscanner);
+static int yy_get_next_buffer (yyscan_t yyscanner );
+static void yy_fatal_error (yyconst char msg[] ,yyscan_t yyscanner );
+
+/* Done after the current pattern has been matched and before the
+ * corresponding action - sets up yytext.
+ */
+#define YY_DO_BEFORE_ACTION \
+ yyg->yytext_ptr = yy_bp; \
+ yyleng = (size_t) (yy_cp - yy_bp); \
+ yyg->yy_hold_char = *yy_cp; \
+ *yy_cp = '\0'; \
+ yyg->yy_c_buf_p = yy_cp;
+
+#define YY_NUM_RULES 30
+#define YY_END_OF_BUFFER 31
+/* This struct is not used in this scanner,
+ but its presence is necessary. */
+struct yy_trans_info
+ {
+ flex_int32_t yy_verify;
+ flex_int32_t yy_nxt;
+ };
+static yyconst flex_int16_t yy_acclist[179] =
+ { 0,
+ 31, 2, 29, 30, 28, 30, 2, 29, 30, 1,
+ 2, 29, 30, 3, 28, 30, 2, 29, 30, 29,
+ 30, 5, 28, 30, 29, 30, 4, 29, 30, 7,
+ 29, 30, 7, 13, 29, 30, 8, 28, 30, 7,
+ 29, 30, 7, 11, 29, 30, 7, 12, 29, 30,
+ 7, 12, 29, 30, 7, 9, 29, 30, 7, 10,
+ 29, 30, 8, 28, 30, 29, 30, 14, 29, 30,
+ 15, 29, 30, 29, 30, 20, 29, 30, 18, 28,
+ 30, 19, 29, 30, 20, 29, 30, 27, 29, 30,
+ 21, 28, 30, 27, 29, 30, 26, 29, 30, 26,
+
+ 29, 30, 26, 29, 30, 22, 29, 30, 24, 28,
+ 30, 29, 30, 23, 29, 30, 25, 28, 30, 29,
+ 30, 28, 1, 1, 3, 28, 5, 28, 7, 7,
+ 7, 13, 6, 8, 28, 7, 12, 7, 12, 7,
+ 8, 28, 14, 20, 18, 28, 20, 21, 28, 22,
+ 24, 28, 23, 25, 28, 6, 9, 17, 20, 17,
+ 7, 7, 6, 7, 7, 9, 17, 20, 7, 7,
+ 6, 7, 7, 9, 16, 17, 20, 7
+ } ;
+
+static yyconst flex_int16_t yy_accept[112] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 2, 5, 7, 10, 14,
+ 17, 20, 22, 25, 27, 30, 33, 37, 40, 43,
+ 47, 51, 55, 59, 63, 66, 68, 71, 74, 76,
+ 79, 82, 85, 88, 91, 94, 97, 100, 103, 106,
+ 109, 112, 114, 117, 120, 122, 123, 124, 125, 127,
+ 129, 130, 130, 131, 133, 134, 136, 138, 140, 140,
+ 141, 143, 144, 145, 147, 148, 150, 150, 151, 153,
+ 154, 156, 156, 156, 157, 158, 158, 160, 161, 162,
+
+ 163, 165, 167, 169, 170, 171, 173, 175, 178, 179,
+ 179
+ } ;
+
+static yyconst flex_int32_t yy_ec[256] =
+ { 0,
+ 1, 1, 1, 1, 1, 1, 1, 1, 2, 3,
+ 1, 1, 4, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 5, 1, 6, 1, 1, 1, 1, 7, 7,
+ 7, 1, 7, 7, 8, 9, 10, 11, 11, 11,
+ 11, 11, 11, 11, 11, 11, 11, 12, 13, 7,
+ 14, 7, 7, 7, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 16, 1, 16, 1, 11, 1, 15, 15, 15, 15,
+
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 15, 15, 15, 15, 15, 15, 15, 15,
+ 15, 15, 1, 17, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1
+ } ;
+
+static yyconst flex_int32_t yy_meta[18] =
+ { 0,
+ 1, 1, 2, 3, 4, 1, 4, 5, 4, 4,
+ 5, 4, 4, 4, 5, 1, 1
+ } ;
+
+static yyconst flex_int16_t yy_base[128] =
+ { 0,
+ 0, 2, 4, 15, 28, 38, 50, 0, 67, 0,
+ 6, 8, 10, 82, 12, 17, 19, 88, 21, 23,
+ 25, 30, 32, 34, 228, 253, 253, 224, 208, 253,
+ 219, 253, 253, 165, 253, 40, 95, 43, 43, 84,
+ 110, 119, 90, 98, 253, 155, 0, 253, 153, 0,
+ 253, 148, 131, 253, 253, 132, 253, 128, 116, 0,
+ 253, 119, 0, 253, 108, 253, 0, 80, 253, 253,
+ 100, 103, 103, 0, 118, 127, 0, 0, 131, 106,
+ 253, 0, 0, 253, 136, 253, 0, 0, 253, 0,
+ 253, 138, 139, 143, 144, 145, 153, 0, 0, 155,
+
+ 160, 161, 81, 112, 169, 162, 173, 41, 173, 253,
+ 178, 183, 188, 193, 198, 203, 208, 34, 213, 215,
+ 220, 225, 230, 235, 237, 242, 247
+ } ;
+
+static yyconst flex_int16_t yy_def[128] =
+ { 0,
+ 111, 111, 111, 111, 112, 112, 110, 7, 110, 9,
+ 112, 112, 113, 113, 114, 114, 115, 115, 116, 116,
+ 117, 117, 112, 112, 110, 110, 110, 110, 118, 110,
+ 110, 110, 110, 110, 110, 119, 119, 110, 119, 119,
+ 119, 41, 119, 119, 110, 110, 120, 110, 110, 121,
+ 110, 110, 121, 110, 110, 110, 110, 110, 110, 122,
+ 110, 110, 123, 110, 110, 110, 118, 118, 110, 110,
+ 119, 110, 119, 37, 110, 110, 41, 42, 110, 119,
+ 110, 120, 121, 110, 124, 110, 125, 122, 110, 123,
+ 110, 126, 110, 126, 126, 110, 124, 125, 127, 127,
+
+ 127, 127, 97, 127, 127, 105, 105, 97, 127, 0,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110
+ } ;
+
+static yyconst flex_int16_t yy_nxt[271] =
+ { 0,
+ 110, 110, 27, 28, 27, 28, 27, 28, 27, 49,
+ 27, 49, 51, 52, 55, 56, 29, 30, 31, 55,
+ 56, 55, 58, 61, 62, 61, 62, 64, 65, 29,
+ 33, 34, 64, 65, 27, 49, 27, 49, 67, 35,
+ 33, 34, 72, 73, 75, 76, 73, 75, 108, 35,
+ 36, 37, 38, 39, 37, 40, 41, 42, 42, 36,
+ 42, 36, 43, 44, 42, 41, 37, 32, 32, 45,
+ 46, 47, 48, 47, 47, 47, 47, 47, 47, 47,
+ 47, 47, 32, 32, 51, 52, 72, 73, 108, 53,
+ 55, 58, 79, 80, 68, 59, 74, 72, 73, 74,
+
+ 72, 73, 72, 73, 92, 93, 73, 92, 96, 73,
+ 91, 74, 72, 73, 72, 109, 77, 77, 77, 75,
+ 77, 89, 75, 87, 77, 77, 78, 78, 94, 78,
+ 86, 94, 95, 78, 86, 95, 83, 83, 85, 100,
+ 92, 83, 100, 92, 101, 102, 95, 101, 102, 95,
+ 84, 83, 83, 83, 83, 66, 105, 81, 83, 105,
+ 103, 106, 107, 106, 106, 107, 106, 70, 83, 83,
+ 105, 72, 109, 105, 107, 93, 109, 107, 26, 26,
+ 26, 26, 26, 32, 32, 32, 32, 32, 50, 50,
+ 50, 50, 50, 54, 54, 54, 54, 54, 57, 57,
+
+ 57, 57, 57, 60, 60, 60, 60, 60, 63, 63,
+ 63, 63, 63, 71, 71, 71, 71, 71, 82, 82,
+ 83, 69, 68, 83, 83, 88, 66, 110, 88, 88,
+ 90, 110, 110, 90, 90, 97, 110, 110, 97, 97,
+ 98, 98, 99, 110, 99, 99, 99, 104, 110, 104,
+ 104, 104, 25, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110
+ } ;
+
+static yyconst flex_int16_t yy_chk[271] =
+ { 0,
+ 0, 0, 1, 1, 2, 2, 3, 3, 11, 11,
+ 12, 12, 13, 13, 15, 15, 2, 4, 4, 16,
+ 16, 17, 17, 19, 19, 20, 20, 21, 21, 4,
+ 5, 5, 22, 22, 23, 23, 24, 24, 118, 5,
+ 6, 6, 36, 36, 38, 39, 39, 38, 108, 6,
+ 7, 7, 7, 7, 7, 7, 7, 7, 7, 7,
+ 7, 7, 7, 7, 7, 7, 7, 9, 9, 9,
+ 9, 9, 9, 9, 9, 9, 9, 9, 9, 9,
+ 9, 9, 9, 9, 14, 14, 40, 40, 103, 14,
+ 18, 18, 43, 43, 68, 18, 37, 37, 37, 37,
+
+ 44, 44, 71, 71, 72, 73, 73, 72, 80, 80,
+ 65, 37, 41, 41, 104, 104, 41, 41, 41, 75,
+ 41, 62, 75, 59, 41, 41, 42, 42, 76, 42,
+ 58, 76, 79, 42, 56, 79, 85, 85, 53, 92,
+ 93, 85, 92, 93, 94, 95, 96, 94, 95, 96,
+ 52, 85, 85, 97, 97, 49, 100, 46, 97, 100,
+ 97, 101, 102, 106, 101, 102, 106, 34, 97, 97,
+ 105, 105, 105, 105, 107, 109, 109, 107, 111, 111,
+ 111, 111, 111, 112, 112, 112, 112, 112, 113, 113,
+ 113, 113, 113, 114, 114, 114, 114, 114, 115, 115,
+
+ 115, 115, 115, 116, 116, 116, 116, 116, 117, 117,
+ 117, 117, 117, 119, 119, 119, 119, 119, 120, 120,
+ 121, 31, 29, 121, 121, 122, 28, 25, 122, 122,
+ 123, 0, 0, 123, 123, 124, 0, 0, 124, 124,
+ 125, 125, 126, 0, 126, 126, 126, 127, 0, 127,
+ 127, 127, 110, 110, 110, 110, 110, 110, 110, 110,
+ 110, 110, 110, 110, 110, 110, 110, 110, 110, 110
+ } ;
+
+/* Table of booleans, true if rule could match eol. */
+static yyconst flex_int32_t yy_rule_can_match_eol[31] =
+ { 0,
+0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, };
+
+#define REJECT \
+{ \
+*yy_cp = yyg->yy_hold_char; /* undo effects of setting up yytext */ \
+yy_cp = yyg->yy_full_match; /* restore poss. backed-over text */ \
+++yyg->yy_lp; \
+goto find_rule; \
+}
+
+#define yymore() yymore_used_but_not_detected
+#define YY_MORE_ADJ 0
+#define YY_RESTORE_YY_MORE_OFFSET
+#line 1 "mimeparser.l"
+#line 2 "mimeparser.l"
+/*
+ * Copyright (c) 2004 Jann Fischer. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/**
+ * This is a lexer file for parsing MIME compatible messages. It is intended
+ * to satisfy at least RFC 2045 (Format of Internet Message Bodies). It still
+ * has quite a few problems:
+ *
+ * - The parsing could probably be done in a more elegant way
+ * - I don't know what performance impact REJECT has on the parser
+ */
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <errno.h>
+
+#include "mimeparser.h"
+#include "mimeparser.tab.h"
+
+#define NAMEOF(v) #v
+/* BC() is a debug wrapper for lex' BEGIN() macro */
+#define BC(x) do { \
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner); \
+ BEGIN(x); \
+ lstate->condition = x; \
+} while(0);
+
+#define ZERO(x) memset(x, '\0', sizeof(x))
+
+#define PREALLOC_BUFFER 100000
+#undef YY_BUF_SIZE
+#define YY_BUF_SIZE 65536
+
+enum header_states
+{
+ STATE_MAIL = 0,
+ STATE_CTYPE,
+ STATE_CDISP,
+ STATE_CENC,
+ STATE_MIME
+};
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+#line 658 "mimeparser.yy.c"
+
+#define INITIAL 0
+#define headers 1
+#define header 2
+#define headervalue 3
+#define tspecialvalue 4
+#define comment 5
+#define body 6
+#define postamble 7
+#define preamble 8
+#define boundary 9
+#define endboundary 10
+#define endoffile 11
+
+#ifndef YY_NO_UNISTD_H
+/* Special case for "unistd.h", since it is non-ANSI. We include it way
+ * down here because we want the user's section 1 to have been scanned first.
+ * The user has a chance to override it with an option.
+ */
+#include <unistd.h>
+#endif
+
+#ifndef YY_EXTRA_TYPE
+#define YY_EXTRA_TYPE void *
+#endif
+
+/* Holds the entire state of the reentrant scanner. */
+struct yyguts_t
+ {
+
+ /* User-defined. Not touched by flex. */
+ YY_EXTRA_TYPE yyextra_r;
+
+ /* The rest are the same as the globals declared in the non-reentrant scanner. */
+ FILE *yyin_r, *yyout_r;
+ size_t yy_buffer_stack_top; /**< index of top of stack. */
+ size_t yy_buffer_stack_max; /**< capacity of stack. */
+ YY_BUFFER_STATE * yy_buffer_stack; /**< Stack as an array. */
+ char yy_hold_char;
+ int yy_n_chars;
+ int yyleng_r;
+ char *yy_c_buf_p;
+ int yy_init;
+ int yy_start;
+ int yy_did_buffer_switch_on_eof;
+ int yy_start_stack_ptr;
+ int yy_start_stack_depth;
+ int *yy_start_stack;
+ yy_state_type yy_last_accepting_state;
+ char* yy_last_accepting_cpos;
+
+ int yylineno_r;
+ int yy_flex_debug_r;
+
+ yy_state_type *yy_state_buf;
+ yy_state_type *yy_state_ptr;
+ char *yy_full_match;
+ int yy_lp;
+
+ char *yytext_r;
+ int yy_more_flag;
+ int yy_more_len;
+
+ YYSTYPE * yylval_r;
+
+ }; /* end struct yyguts_t */
+
+static int yy_init_globals (yyscan_t yyscanner );
+
+ /* This must go here because YYSTYPE and YYLTYPE are included
+ * from bison output in section 1.*/
+ # define yylval yyg->yylval_r
+
+/* Accessor methods to globals.
+ These are made visible to non-reentrant scanners for convenience. */
+
+int mimeparser_yylex_destroy (yyscan_t yyscanner );
+
+int mimeparser_yyget_debug (yyscan_t yyscanner );
+
+void mimeparser_yyset_debug (int debug_flag ,yyscan_t yyscanner );
+
+YY_EXTRA_TYPE mimeparser_yyget_extra (yyscan_t yyscanner );
+
+void mimeparser_yyset_extra (YY_EXTRA_TYPE user_defined ,yyscan_t yyscanner );
+
+FILE *mimeparser_yyget_in (yyscan_t yyscanner );
+
+void mimeparser_yyset_in (FILE * in_str ,yyscan_t yyscanner );
+
+FILE *mimeparser_yyget_out (yyscan_t yyscanner );
+
+void mimeparser_yyset_out (FILE * out_str ,yyscan_t yyscanner );
+
+int mimeparser_yyget_leng (yyscan_t yyscanner );
+
+char *mimeparser_yyget_text (yyscan_t yyscanner );
+
+int mimeparser_yyget_lineno (yyscan_t yyscanner );
+
+void mimeparser_yyset_lineno (int line_number ,yyscan_t yyscanner );
+
+YYSTYPE * mimeparser_yyget_lval (yyscan_t yyscanner );
+
+void mimeparser_yyset_lval (YYSTYPE * yylval_param ,yyscan_t yyscanner );
+
+/* Macros after this point can all be overridden by user definitions in
+ * section 1.
+ */
+
+#ifndef YY_SKIP_YYWRAP
+#ifdef __cplusplus
+extern "C" int mimeparser_yywrap (yyscan_t yyscanner );
+#else
+extern int mimeparser_yywrap (yyscan_t yyscanner );
+#endif
+#endif
+
+ static void yyunput (int c,char *buf_ptr ,yyscan_t yyscanner);
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char *,yyconst char *,int ,yyscan_t yyscanner);
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * ,yyscan_t yyscanner);
+#endif
+
+#ifndef YY_NO_INPUT
+
+#ifdef __cplusplus
+static int yyinput (yyscan_t yyscanner );
+#else
+static int input (yyscan_t yyscanner );
+#endif
+
+#endif
+
+/* Amount of stuff to slurp up with each read. */
+#ifndef YY_READ_BUF_SIZE
+#define YY_READ_BUF_SIZE 8192
+#endif
+
+/* Copy whatever the last rule matched to the standard output. */
+#ifndef ECHO
+/* This used to be an fputs(), but since the string might contain NUL's,
+ * we now use fwrite().
+ */
+#define ECHO (void) fwrite( yytext, yyleng, 1, yyout )
+#endif
+
+/* Gets input and stuffs it into "buf". number of characters read, or YY_NULL,
+ * is returned in "result".
+ */
+#ifndef YY_INPUT
+#define YY_INPUT(buf,result,max_size) \
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_is_interactive ) \
+ { \
+ int c = '*'; \
+ size_t n; \
+ for ( n = 0; n < max_size && \
+ (c = getc( yyin )) != EOF && c != '\n'; ++n ) \
+ buf[n] = (char) c; \
+ if ( c == '\n' ) \
+ buf[n++] = (char) c; \
+ if ( c == EOF && ferror( yyin ) ) \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ result = n; \
+ } \
+ else \
+ { \
+ errno=0; \
+ while ( (result = fread(buf, 1, max_size, yyin))==0 && ferror(yyin)) \
+ { \
+ if( errno != EINTR) \
+ { \
+ YY_FATAL_ERROR( "input in flex scanner failed" ); \
+ break; \
+ } \
+ errno=0; \
+ clearerr(yyin); \
+ } \
+ }\
+\
+
+#endif
+
+/* No semi-colon after return; correct usage is to write "yyterminate();" -
+ * we don't want an extra ';' after the "return" because that will cause
+ * some compilers to complain about unreachable statements.
+ */
+#ifndef yyterminate
+#define yyterminate() return YY_NULL
+#endif
+
+/* Number of entries by which start-condition stack grows. */
+#ifndef YY_START_STACK_INCR
+#define YY_START_STACK_INCR 25
+#endif
+
+/* Report a fatal error. */
+#ifndef YY_FATAL_ERROR
+#define YY_FATAL_ERROR(msg) yy_fatal_error( msg , yyscanner)
+#endif
+
+/* end tables serialization structures and prototypes */
+
+/* Default declaration of generated scanner - a define so the user can
+ * easily add parameters.
+ */
+#ifndef YY_DECL
+#define YY_DECL_IS_OURS 1
+
+extern int mimeparser_yylex \
+ (YYSTYPE * yylval_param ,yyscan_t yyscanner);
+
+#define YY_DECL int mimeparser_yylex \
+ (YYSTYPE * yylval_param , yyscan_t yyscanner)
+#endif /* !YY_DECL */
+
+/* Code executed at the beginning of each rule, after yytext and yyleng
+ * have been set up.
+ */
+#ifndef YY_USER_ACTION
+#define YY_USER_ACTION
+#endif
+
+/* Code executed at the end of each rule. */
+#ifndef YY_BREAK
+#define YY_BREAK break;
+#endif
+
+#define YY_RULE_SETUP \
+ if ( yyleng > 0 ) \
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = \
+ (yytext[yyleng - 1] == '\n'); \
+ YY_USER_ACTION
+
+/** The main scanner function which does all the work.
+ */
+YY_DECL
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp, *yy_bp;
+ register int yy_act;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+#line 94 "mimeparser.l"
+
+
+#line 909 "mimeparser.yy.c"
+
+ yylval = yylval_param;
+
+ if ( !yyg->yy_init )
+ {
+ yyg->yy_init = 1;
+
+#ifdef YY_USER_INIT
+ YY_USER_INIT;
+#endif
+
+ /* Create the reject buffer large enough to save one state per allowed character. */
+ if ( ! yyg->yy_state_buf )
+ yyg->yy_state_buf = (yy_state_type *)mimeparser_yyalloc(YY_STATE_BUF_SIZE ,yyscanner);
+
+ if ( ! yyg->yy_start )
+ yyg->yy_start = 1; /* first start state */
+
+ if ( ! yyin )
+ yyin = stdin;
+
+ if ( ! yyout )
+ yyout = stdout;
+
+ if ( ! YY_CURRENT_BUFFER ) {
+ mimeparser_yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ mimeparser_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ mimeparser_yy_load_buffer_state(yyscanner );
+ }
+
+ while ( 1 ) /* loops until end-of-file is reached */
+ {
+ yy_cp = yyg->yy_c_buf_p;
+
+ /* Support of yytext. */
+ *yy_cp = yyg->yy_hold_char;
+
+ /* yy_bp points to the position in yy_ch_buf of the start of
+ * the current run.
+ */
+ yy_bp = yy_cp;
+
+ yy_current_state = yyg->yy_start;
+ yy_current_state += YY_AT_BOL();
+
+ yyg->yy_state_ptr = yyg->yy_state_buf;
+ *yyg->yy_state_ptr++ = yy_current_state;
+
+yy_match:
+ do
+ {
+ register YY_CHAR yy_c = yy_ec[YY_SC_TO_UI(*yy_cp)];
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 111 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ *yyg->yy_state_ptr++ = yy_current_state;
+ ++yy_cp;
+ }
+ while ( yy_base[yy_current_state] != 253 );
+
+yy_find_action:
+ yy_current_state = *--yyg->yy_state_ptr;
+ yyg->yy_lp = yy_accept[yy_current_state];
+find_rule: /* we branch to this label when backing up */
+ for ( ; ; ) /* until we find what rule we matched */
+ {
+ if ( yyg->yy_lp && yyg->yy_lp < yy_accept[yy_current_state + 1] )
+ {
+ yy_act = yy_acclist[yyg->yy_lp];
+ {
+ yyg->yy_full_match = yy_cp;
+ break;
+ }
+ }
+ --yy_cp;
+ yy_current_state = *--yyg->yy_state_ptr;
+ yyg->yy_lp = yy_accept[yy_current_state];
+ }
+
+ YY_DO_BEFORE_ACTION;
+
+ if ( yy_act != YY_END_OF_BUFFER && yy_rule_can_match_eol[yy_act] )
+ {
+ int yyl;
+ for ( yyl = 0; yyl < yyleng; ++yyl )
+ if ( yytext[yyl] == '\n' )
+
+ do{ yylineno++;
+ yycolumn=0;
+ }while(0)
+;
+ }
+
+do_action: /* This label is used only to access EOF actions. */
+
+ switch ( yy_act )
+ { /* beginning of action switch */
+case 1:
+YY_RULE_SETUP
+#line 96 "mimeparser.l"
+{
+ yylval_param->string=strdup(yytext);
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+ BC(header);
+
+ /* Depending on what header we are processing, we enter a different
+ * state and return a different value.
+ */
+ if (!strcasecmp(yytext, "Content-Type")) {
+ lstate->header_state = STATE_CTYPE;
+ return CONTENTTYPE_HEADER;
+ } else if (!strcasecmp(yytext, "Content-Transfer-Encoding")) {
+ lstate->header_state = STATE_CENC;
+ return CONTENTENCODING_HEADER;
+ } else if (!strcasecmp(yytext, "Content-Disposition")) {
+ lstate->header_state = STATE_CDISP;
+ return CONTENTDISPOSITION_HEADER;
+ } else if (!strcasecmp(yytext, "MIME-Version")) {
+ lstate->header_state = STATE_MAIL;
+ return MIMEVERSION_HEADER;
+ } else {
+ lstate->header_state = STATE_MAIL;
+ return MAIL_HEADER;
+ }
+}
+ YY_BREAK
+case 2:
+YY_RULE_SETUP
+#line 123 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ /* dprintf2("Unknown header char: %c\n", *yytext); */
+ lstate->current_pos += yyleng;
+ return ANY;
+}
+ YY_BREAK
+case 3:
+/* rule 3 can match eol */
+YY_RULE_SETUP
+#line 130 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ lstate->lineno++;
+
+ lstate->current_pos += yyleng;
+
+ /* This marks the end of headers. Depending on whether we are in the
+ * envelope currently we need to parse either a body or the preamble
+ * now.
+ */
+ if (lstate->is_envelope == 0 || lstate->boundary_string == NULL) {
+ BC(body);
+ lstate->body_start = lstate->current_pos;
+ } else {
+ lstate->is_envelope = 0;
+ lstate->preamble_start = lstate->current_pos;
+ BC(preamble);
+ }
+
+ return ENDOFHEADERS;
+}
+ YY_BREAK
+case 4:
+YY_RULE_SETUP
+#line 152 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ BC(headervalue);
+ lstate->current_pos += yyleng;
+ return COLON;
+}
+ YY_BREAK
+case 5:
+/* rule 5 can match eol */
+YY_RULE_SETUP
+#line 159 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ BC(headers);
+ /* dprintf2("Invalid header, returning EOL\n"); */
+ lstate->current_pos += yyleng;
+ return EOL;
+}
+ YY_BREAK
+case 6:
+/* rule 6 can match eol */
+YY_RULE_SETUP
+#line 167 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+}
+ YY_BREAK
+case 7:
+/* rule 7 can match eol */
+YY_RULE_SETUP
+#line 172 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ if (lstate->header_state != STATE_MAIL && lstate->header_state != STATE_CENC) {
+ REJECT;
+ }
+ lstate->current_pos += yyleng;
+ while (*yytext && isspace(*yytext)) yytext++;
+ /* Do we actually have a header value? */
+ if (*yytext == '\0') {
+ yylval_param->string = strdup("");
+ } else {
+ yylval_param->string=strdup(yytext);
+ lstate->lineno += count_lines(yytext);
+ }
+ return WORD;
+}
+ YY_BREAK
+case 8:
+/* rule 8 can match eol */
+YY_RULE_SETUP
+#line 189 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ /* marks the end of one header line */
+ lstate->lineno++;
+ BC(headers);
+ lstate->current_pos += yyleng;
+ return EOL;
+}
+ YY_BREAK
+case 9:
+/* rule 9 can match eol */
+YY_RULE_SETUP
+#line 198 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ lstate->lineno += count_lines(yytext);
+ lstate->current_pos += yyleng;
+ return SEMICOLON;
+}
+ YY_BREAK
+case 10:
+YY_RULE_SETUP
+#line 205 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+ return EQUAL;
+}
+ YY_BREAK
+case 11:
+YY_RULE_SETUP
+#line 211 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ BC(tspecialvalue);
+ lstate->current_pos += yyleng;
+ return *yytext;
+}
+ YY_BREAK
+case 12:
+YY_RULE_SETUP
+#line 218 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ yylval_param->string=strdup(yytext);
+ lstate->lineno += count_lines(yytext);
+ lstate->current_pos += yyleng;
+ return WORD;
+}
+ YY_BREAK
+case 13:
+YY_RULE_SETUP
+#line 226 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+}
+ YY_BREAK
+case 14:
+YY_RULE_SETUP
+#line 231 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ lstate->lineno += count_lines(yytext);
+ yylval_param->string=strdup(yytext);
+ lstate->current_pos += yyleng;
+ return TSPECIAL;
+}
+ YY_BREAK
+case 15:
+YY_RULE_SETUP
+#line 239 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ BC(headervalue);
+ lstate->current_pos += yyleng;
+ return *yytext;
+}
+ YY_BREAK
+case 16:
+YY_RULE_SETUP
+#line 246 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ /**
+ * Make sure we only catch matching boundaries, and not other lines
+ * that begin and end with two dashes. If we have catched a valid
+ * end boundary, which actually ends a body, we save the current
+ * position, put the token back on the input stream and let the
+ * endboundary condition parse the actual token.
+ */
+ if (lstate->endboundary_string != NULL) {
+ if (strcmp(lstate->endboundary_string, yytext)) {
+ /* dprintf2("YYTEXT != end_boundary: '%s'\n", yytext); */
+ REJECT;
+ } else {
+ lstate->current_pos += yyleng;
+ /* dprintf2("YYTEXT == lstate->end_boundary: '%s'\n", yytext); */
+ if (lstate->body_start) {
+ yylval_param->position.opaque_start =
+ lstate->body_opaque_start;
+ yylval_param->position.start = lstate->body_start;
+ yylval_param->position.end = lstate->current_pos - yyleng;
+ lstate->body_opaque_start = 0;
+ lstate->body_start = 0;
+ lstate->body_end = 0;
+ yyless(0);
+ BC(endboundary);
+ return BODY;
+ }
+ }
+ } else {
+ }
+
+ REJECT;
+}
+ YY_BREAK
+case 17:
+YY_RULE_SETUP
+#line 281 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ /**
+ * Make sure we only catch matching boundaries, and not other lines
+ * that begin with two dashes.
+ */
+ if (lstate->boundary_string != NULL) {
+ if (strcmp(lstate->boundary_string, yytext)) {
+ /* dprintf2("YYTEXT != boundary: '%s'\n", yytext);*/
+ REJECT;
+ } else {
+ /* dprintf2("YYTEXT == boundary: '%s'\n", yytext);*/
+ if (lstate->body_start) {
+ yylval_param->position.opaque_start = lstate->body_opaque_start;
+ yylval_param->position.start = lstate->body_start;
+ yylval_param->position.end = lstate->current_pos;
+ lstate->body_opaque_start = 0;
+ lstate->body_start = 0;
+ lstate->body_end = 0;
+ yyless(0);
+ BC(boundary);
+ return BODY;
+ } else if (lstate->preamble_start) {
+ yylval_param->position.start = lstate->preamble_start;
+ yylval_param->position.end = lstate->current_pos;
+ lstate->preamble_start = lstate->preamble_end = 0;
+ yyless(0);
+ BC(boundary);
+ return PREAMBLE;
+ } else {
+ BC(boundary);
+ yylval_param->string = strdup(yytext);
+ lstate->current_pos += yyleng;
+ return(BOUNDARY);
+ }
+ }
+ } else {
+ }
+
+ REJECT;
+}
+ YY_BREAK
+case 18:
+/* rule 18 can match eol */
+YY_RULE_SETUP
+#line 323 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+ lstate->lineno++;
+}
+ YY_BREAK
+case 19:
+YY_RULE_SETUP
+#line 329 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+ /* dprintf2("stray CR in body...\n"); */
+}
+ YY_BREAK
+case 20:
+YY_RULE_SETUP
+#line 335 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+}
+ YY_BREAK
+case YY_STATE_EOF(body):
+#line 340 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ if (lstate->boundary_string == NULL && lstate->body_start) {
+ yylval_param->position.opaque_start = 0;
+ yylval_param->position.start = lstate->body_start;
+ yylval_param->position.end = lstate->current_pos;
+ lstate->body_start = 0;
+ return BODY;
+ } else if (lstate->body_start) {
+ return POSTAMBLE;
+ }
+ yyterminate();
+}
+ YY_BREAK
+case 21:
+/* rule 21 can match eol */
+YY_RULE_SETUP
+#line 354 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ /* dprintf2("Preamble CR/LF at line %d\n", lineno); */
+ lstate->lineno++;
+ lstate->current_pos += yyleng;
+}
+ YY_BREAK
+case 22:
+YY_RULE_SETUP
+#line 361 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ yylval_param->string = strdup(yytext);
+ lstate->current_pos += yyleng;
+ return BOUNDARY;
+}
+ YY_BREAK
+case 23:
+YY_RULE_SETUP
+#line 368 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ yylval_param->string = strdup(yytext);
+ lstate->current_pos += yyleng;
+ return ENDBOUNDARY;
+}
+ YY_BREAK
+case 24:
+/* rule 24 can match eol */
+YY_RULE_SETUP
+#line 375 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ BC(headers);
+ lstate->lineno++;
+ lstate->current_pos += yyleng;
+ lstate->body_opaque_start = lstate->current_pos;
+ return EOL;
+}
+ YY_BREAK
+case 25:
+/* rule 25 can match eol */
+YY_RULE_SETUP
+#line 384 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ BC(postamble);
+ lstate->lineno++;
+ lstate->current_pos += yyleng;
+}
+ YY_BREAK
+case 26:
+YY_RULE_SETUP
+#line 391 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+}
+ YY_BREAK
+case 27:
+YY_RULE_SETUP
+#line 397 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+}
+ YY_BREAK
+case 28:
+/* rule 28 can match eol */
+YY_RULE_SETUP
+#line 402 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ lstate->lineno++;
+ lstate->current_pos += yyleng;
+ return EOL;
+}
+ YY_BREAK
+case 29:
+YY_RULE_SETUP
+#line 409 "mimeparser.l"
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(yyscanner);
+ lstate->current_pos += yyleng;
+ return((int)*yytext);
+}
+ YY_BREAK
+case 30:
+YY_RULE_SETUP
+#line 416 "mimeparser.l"
+ECHO;
+ YY_BREAK
+#line 1437 "mimeparser.yy.c"
+ case YY_STATE_EOF(INITIAL):
+ case YY_STATE_EOF(headers):
+ case YY_STATE_EOF(header):
+ case YY_STATE_EOF(headervalue):
+ case YY_STATE_EOF(tspecialvalue):
+ case YY_STATE_EOF(comment):
+ case YY_STATE_EOF(postamble):
+ case YY_STATE_EOF(preamble):
+ case YY_STATE_EOF(boundary):
+ case YY_STATE_EOF(endboundary):
+ case YY_STATE_EOF(endoffile):
+ yyterminate();
+
+ case YY_END_OF_BUFFER:
+ {
+ /* Amount of text matched not including the EOB char. */
+ int yy_amount_of_matched_text = (int) (yy_cp - yyg->yytext_ptr) - 1;
+
+ /* Undo the effects of YY_DO_BEFORE_ACTION. */
+ *yy_cp = yyg->yy_hold_char;
+ YY_RESTORE_YY_MORE_OFFSET
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_NEW )
+ {
+ /* We're scanning a new file or input source. It's
+ * possible that this happened because the user
+ * just pointed yyin at a new source and called
+ * mimeparser_yylex(). If so, then we have to assure
+ * consistency between YY_CURRENT_BUFFER and our
+ * globals. Here is the right place to do so, because
+ * this is the first action (other than possibly a
+ * back-up) that will match for the new input source.
+ */
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ YY_CURRENT_BUFFER_LVALUE->yy_input_file = yyin;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status = YY_BUFFER_NORMAL;
+ }
+
+ /* Note that here we test for yy_c_buf_p "<=" to the position
+ * of the first EOB in the buffer, since yy_c_buf_p will
+ * already have been incremented past the NUL character
+ * (since all states make transitions on EOB to the
+ * end-of-buffer state). Contrast this with the test
+ * in input().
+ */
+ if ( yyg->yy_c_buf_p <= &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ { /* This was really a NUL. */
+ yy_state_type yy_next_state;
+
+ yyg->yy_c_buf_p = yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ /* Okay, we're now positioned to make the NUL
+ * transition. We couldn't have
+ * yy_get_previous_state() go ahead and do it
+ * for us because it doesn't know how to deal
+ * with the possibility of jamming (and we don't
+ * want to build jamming into it because then it
+ * will run more slowly).
+ */
+
+ yy_next_state = yy_try_NUL_trans( yy_current_state , yyscanner);
+
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ if ( yy_next_state )
+ {
+ /* Consume the NUL. */
+ yy_cp = ++yyg->yy_c_buf_p;
+ yy_current_state = yy_next_state;
+ goto yy_match;
+ }
+
+ else
+ {
+ yy_cp = yyg->yy_c_buf_p;
+ goto yy_find_action;
+ }
+ }
+
+ else switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_END_OF_FILE:
+ {
+ yyg->yy_did_buffer_switch_on_eof = 0;
+
+ if ( mimeparser_yywrap(yyscanner ) )
+ {
+ /* Note: because we've taken care in
+ * yy_get_next_buffer() to have set up
+ * yytext, we can now set up
+ * yy_c_buf_p so that if some total
+ * hoser (like flex itself) wants to
+ * call the scanner after we return the
+ * YY_NULL, it'll still work - another
+ * YY_NULL will get returned.
+ */
+ yyg->yy_c_buf_p = yyg->yytext_ptr + YY_MORE_ADJ;
+
+ yy_act = YY_STATE_EOF(YY_START);
+ goto do_action;
+ }
+
+ else
+ {
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+ }
+ break;
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p =
+ yyg->yytext_ptr + yy_amount_of_matched_text;
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_match;
+
+ case EOB_ACT_LAST_MATCH:
+ yyg->yy_c_buf_p =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars];
+
+ yy_current_state = yy_get_previous_state( yyscanner );
+
+ yy_cp = yyg->yy_c_buf_p;
+ yy_bp = yyg->yytext_ptr + YY_MORE_ADJ;
+ goto yy_find_action;
+ }
+ break;
+ }
+
+ default:
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--no action found" );
+ } /* end of action switch */
+ } /* end of scanning one token */
+} /* end of mimeparser_yylex */
+
+/* yy_get_next_buffer - try to read in a new buffer
+ *
+ * Returns a code representing an action:
+ * EOB_ACT_LAST_MATCH -
+ * EOB_ACT_CONTINUE_SCAN - continue scanning from current position
+ * EOB_ACT_END_OF_FILE - end of file
+ */
+static int yy_get_next_buffer (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ register char *dest = YY_CURRENT_BUFFER_LVALUE->yy_ch_buf;
+ register char *source = yyg->yytext_ptr;
+ register int number_to_move, i;
+ int ret_val;
+
+ if ( yyg->yy_c_buf_p > &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] )
+ YY_FATAL_ERROR(
+ "fatal flex scanner internal error--end of buffer missed" );
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_fill_buffer == 0 )
+ { /* Don't try to fill the buffer, so this is an EOF. */
+ if ( yyg->yy_c_buf_p - yyg->yytext_ptr - YY_MORE_ADJ == 1 )
+ {
+ /* We matched a single character, the EOB, so
+ * treat this as a final EOF.
+ */
+ return EOB_ACT_END_OF_FILE;
+ }
+
+ else
+ {
+ /* We matched some text prior to the EOB, first
+ * process it.
+ */
+ return EOB_ACT_LAST_MATCH;
+ }
+ }
+
+ /* Try to read more data. */
+
+ /* First move last chars to start of buffer. */
+ number_to_move = (int) (yyg->yy_c_buf_p - yyg->yytext_ptr) - 1;
+
+ for ( i = 0; i < number_to_move; ++i )
+ *(dest++) = *(source++);
+
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_buffer_status == YY_BUFFER_EOF_PENDING )
+ /* don't do the read, it's not guaranteed to return an EOF,
+ * just force an EOF
+ */
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars = 0;
+
+ else
+ {
+ int num_to_read =
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size - number_to_move - 1;
+
+ while ( num_to_read <= 0 )
+ { /* Not enough room in the buffer - grow it. */
+
+ YY_FATAL_ERROR(
+"input buffer overflow, can't enlarge buffer because scanner uses REJECT" );
+
+ }
+
+ if ( num_to_read > YY_READ_BUF_SIZE )
+ num_to_read = YY_READ_BUF_SIZE;
+
+ /* Read in more data. */
+ YY_INPUT( (&YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move]),
+ yyg->yy_n_chars, num_to_read );
+
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ if ( yyg->yy_n_chars == 0 )
+ {
+ if ( number_to_move == YY_MORE_ADJ )
+ {
+ ret_val = EOB_ACT_END_OF_FILE;
+ mimeparser_yyrestart(yyin ,yyscanner);
+ }
+
+ else
+ {
+ ret_val = EOB_ACT_LAST_MATCH;
+ YY_CURRENT_BUFFER_LVALUE->yy_buffer_status =
+ YY_BUFFER_EOF_PENDING;
+ }
+ }
+
+ else
+ ret_val = EOB_ACT_CONTINUE_SCAN;
+
+ yyg->yy_n_chars += number_to_move;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] = YY_END_OF_BUFFER_CHAR;
+ YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars + 1] = YY_END_OF_BUFFER_CHAR;
+
+ yyg->yytext_ptr = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[0];
+
+ return ret_val;
+}
+
+/* yy_get_previous_state - get the state just before the EOB char was reached */
+
+ static yy_state_type yy_get_previous_state (yyscan_t yyscanner)
+{
+ register yy_state_type yy_current_state;
+ register char *yy_cp;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_current_state = yyg->yy_start;
+ yy_current_state += YY_AT_BOL();
+
+ yyg->yy_state_ptr = yyg->yy_state_buf;
+ *yyg->yy_state_ptr++ = yy_current_state;
+
+ for ( yy_cp = yyg->yytext_ptr + YY_MORE_ADJ; yy_cp < yyg->yy_c_buf_p; ++yy_cp )
+ {
+ register YY_CHAR yy_c = (*yy_cp ? yy_ec[YY_SC_TO_UI(*yy_cp)] : 1);
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 111 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ *yyg->yy_state_ptr++ = yy_current_state;
+ }
+
+ return yy_current_state;
+}
+
+/* yy_try_NUL_trans - try to make a transition on the NUL character
+ *
+ * synopsis
+ * next_state = yy_try_NUL_trans( current_state );
+ */
+ static yy_state_type yy_try_NUL_trans (yy_state_type yy_current_state , yyscan_t yyscanner)
+{
+ register int yy_is_jam;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner; /* This var may be unused depending upon options. */
+
+ register YY_CHAR yy_c = 1;
+ while ( yy_chk[yy_base[yy_current_state] + yy_c] != yy_current_state )
+ {
+ yy_current_state = (int) yy_def[yy_current_state];
+ if ( yy_current_state >= 111 )
+ yy_c = yy_meta[(unsigned int) yy_c];
+ }
+ yy_current_state = yy_nxt[yy_base[yy_current_state] + (unsigned int) yy_c];
+ yy_is_jam = (yy_current_state == 110);
+ if ( ! yy_is_jam )
+ *yyg->yy_state_ptr++ = yy_current_state;
+
+ return yy_is_jam ? 0 : yy_current_state;
+}
+
+ static void yyunput (int c, register char * yy_bp , yyscan_t yyscanner)
+{
+ register char *yy_cp;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ yy_cp = yyg->yy_c_buf_p;
+
+ /* undo effects of setting up yytext */
+ *yy_cp = yyg->yy_hold_char;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ { /* need to shift things up to make room */
+ /* +2 for EOB chars. */
+ register int number_to_move = yyg->yy_n_chars + 2;
+ register char *dest = &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_size + 2];
+ register char *source =
+ &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[number_to_move];
+
+ while ( source > YY_CURRENT_BUFFER_LVALUE->yy_ch_buf )
+ *--dest = *--source;
+
+ yy_cp += (int) (dest - source);
+ yy_bp += (int) (dest - source);
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars =
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_buf_size;
+
+ if ( yy_cp < YY_CURRENT_BUFFER_LVALUE->yy_ch_buf + 2 )
+ YY_FATAL_ERROR( "flex scanner push-back overflow" );
+ }
+
+ *--yy_cp = (char) c;
+
+ if ( c == '\n' ){
+ --yylineno;
+ }
+
+ yyg->yytext_ptr = yy_bp;
+ yyg->yy_hold_char = *yy_cp;
+ yyg->yy_c_buf_p = yy_cp;
+}
+
+#ifndef YY_NO_INPUT
+#ifdef __cplusplus
+ static int yyinput (yyscan_t yyscanner)
+#else
+ static int input (yyscan_t yyscanner)
+#endif
+
+{
+ int c;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+
+ if ( *yyg->yy_c_buf_p == YY_END_OF_BUFFER_CHAR )
+ {
+ /* yy_c_buf_p now points to the character we want to return.
+ * If this occurs *before* the EOB characters, then it's a
+ * valid NUL; if not, then we've hit the end of the buffer.
+ */
+ if ( yyg->yy_c_buf_p < &YY_CURRENT_BUFFER_LVALUE->yy_ch_buf[yyg->yy_n_chars] )
+ /* This was really a NUL. */
+ *yyg->yy_c_buf_p = '\0';
+
+ else
+ { /* need more input */
+ int offset = yyg->yy_c_buf_p - yyg->yytext_ptr;
+ ++yyg->yy_c_buf_p;
+
+ switch ( yy_get_next_buffer( yyscanner ) )
+ {
+ case EOB_ACT_LAST_MATCH:
+ /* This happens because yy_g_n_b()
+ * sees that we've accumulated a
+ * token and flags that we need to
+ * try matching the token before
+ * proceeding. But for input(),
+ * there's no matching to consider.
+ * So convert the EOB_ACT_LAST_MATCH
+ * to EOB_ACT_END_OF_FILE.
+ */
+
+ /* Reset buffer status. */
+ mimeparser_yyrestart(yyin ,yyscanner);
+
+ /*FALLTHROUGH*/
+
+ case EOB_ACT_END_OF_FILE:
+ {
+ if ( mimeparser_yywrap(yyscanner ) )
+ return EOF;
+
+ if ( ! yyg->yy_did_buffer_switch_on_eof )
+ YY_NEW_FILE;
+#ifdef __cplusplus
+ return yyinput(yyscanner);
+#else
+ return input(yyscanner);
+#endif
+ }
+
+ case EOB_ACT_CONTINUE_SCAN:
+ yyg->yy_c_buf_p = yyg->yytext_ptr + offset;
+ break;
+ }
+ }
+ }
+
+ c = *(unsigned char *) yyg->yy_c_buf_p; /* cast for 8-bit char's */
+ *yyg->yy_c_buf_p = '\0'; /* preserve yytext */
+ yyg->yy_hold_char = *++yyg->yy_c_buf_p;
+
+ YY_CURRENT_BUFFER_LVALUE->yy_at_bol = (c == '\n');
+ if ( YY_CURRENT_BUFFER_LVALUE->yy_at_bol )
+
+ do{ yylineno++;
+ yycolumn=0;
+ }while(0)
+;
+
+ return c;
+}
+#endif /* ifndef YY_NO_INPUT */
+
+/** Immediately switch to a different input stream.
+ * @param input_file A readable stream.
+ * @param yyscanner The scanner object.
+ * @note This function does not reset the start condition to @c INITIAL .
+ */
+ void mimeparser_yyrestart (FILE * input_file , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! YY_CURRENT_BUFFER ){
+ mimeparser_yyensure_buffer_stack (yyscanner);
+ YY_CURRENT_BUFFER_LVALUE =
+ mimeparser_yy_create_buffer(yyin,YY_BUF_SIZE ,yyscanner);
+ }
+
+ mimeparser_yy_init_buffer(YY_CURRENT_BUFFER,input_file ,yyscanner);
+ mimeparser_yy_load_buffer_state(yyscanner );
+}
+
+/** Switch to a different input buffer.
+ * @param new_buffer The new input buffer.
+ * @param yyscanner The scanner object.
+ */
+ void mimeparser_yy_switch_to_buffer (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* TODO. We should be able to replace this entire function body
+ * with
+ * mimeparser_yypop_buffer_state();
+ * mimeparser_yypush_buffer_state(new_buffer);
+ */
+ mimeparser_yyensure_buffer_stack (yyscanner);
+ if ( YY_CURRENT_BUFFER == new_buffer )
+ return;
+
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+ mimeparser_yy_load_buffer_state(yyscanner );
+
+ /* We don't actually know whether we did this switch during
+ * EOF (mimeparser_yywrap()) processing, but the only time this flag
+ * is looked at is after mimeparser_yywrap() is called, so it's safe
+ * to go ahead and always set it.
+ */
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+static void mimeparser_yy_load_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyg->yy_n_chars = YY_CURRENT_BUFFER_LVALUE->yy_n_chars;
+ yyg->yytext_ptr = yyg->yy_c_buf_p = YY_CURRENT_BUFFER_LVALUE->yy_buf_pos;
+ yyin = YY_CURRENT_BUFFER_LVALUE->yy_input_file;
+ yyg->yy_hold_char = *yyg->yy_c_buf_p;
+}
+
+/** Allocate and initialize an input buffer state.
+ * @param file A readable stream.
+ * @param size The character buffer size in bytes. When in doubt, use @c YY_BUF_SIZE.
+ * @param yyscanner The scanner object.
+ * @return the allocated buffer state.
+ */
+ YY_BUFFER_STATE mimeparser_yy_create_buffer (FILE * file, int size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ b = (YY_BUFFER_STATE) mimeparser_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in mimeparser_yy_create_buffer()" );
+
+ b->yy_buf_size = size;
+
+ /* yy_ch_buf has to be 2 characters longer than the size given because
+ * we need to put in 2 end-of-buffer characters.
+ */
+ b->yy_ch_buf = (char *) mimeparser_yyalloc(b->yy_buf_size + 2 ,yyscanner );
+ if ( ! b->yy_ch_buf )
+ YY_FATAL_ERROR( "out of dynamic memory in mimeparser_yy_create_buffer()" );
+
+ b->yy_is_our_buffer = 1;
+
+ mimeparser_yy_init_buffer(b,file ,yyscanner);
+
+ return b;
+}
+
+/** Destroy the buffer.
+ * @param b a buffer created with mimeparser_yy_create_buffer()
+ * @param yyscanner The scanner object.
+ */
+ void mimeparser_yy_delete_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if ( ! b )
+ return;
+
+ if ( b == YY_CURRENT_BUFFER ) /* Not sure if we should pop here. */
+ YY_CURRENT_BUFFER_LVALUE = (YY_BUFFER_STATE) 0;
+
+ if ( b->yy_is_our_buffer )
+ mimeparser_yyfree((void *) b->yy_ch_buf ,yyscanner );
+
+ mimeparser_yyfree((void *) b ,yyscanner );
+}
+
+#ifndef __cplusplus
+extern int isatty (int );
+#endif /* __cplusplus */
+
+/* Initializes or reinitializes a buffer.
+ * This function is sometimes called more than once on the same buffer,
+ * such as during a mimeparser_yyrestart() or at EOF.
+ */
+ static void mimeparser_yy_init_buffer (YY_BUFFER_STATE b, FILE * file , yyscan_t yyscanner)
+
+{
+ int oerrno = errno;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ mimeparser_yy_flush_buffer(b ,yyscanner);
+
+ b->yy_input_file = file;
+ b->yy_fill_buffer = 1;
+
+ /* If b is the current buffer, then mimeparser_yy_init_buffer was _probably_
+ * called from mimeparser_yyrestart() or through yy_get_next_buffer.
+ * In that case, we don't want to reset the lineno or column.
+ */
+ if (b != YY_CURRENT_BUFFER){
+ b->yy_bs_lineno = 1;
+ b->yy_bs_column = 0;
+ }
+
+ b->yy_is_interactive = file ? (isatty( fileno(file) ) > 0) : 0;
+
+ errno = oerrno;
+}
+
+/** Discard all buffered characters. On the next scan, YY_INPUT will be called.
+ * @param b the buffer state to be flushed, usually @c YY_CURRENT_BUFFER.
+ * @param yyscanner The scanner object.
+ */
+ void mimeparser_yy_flush_buffer (YY_BUFFER_STATE b , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if ( ! b )
+ return;
+
+ b->yy_n_chars = 0;
+
+ /* We always need two end-of-buffer characters. The first causes
+ * a transition to the end-of-buffer state. The second causes
+ * a jam in that state.
+ */
+ b->yy_ch_buf[0] = YY_END_OF_BUFFER_CHAR;
+ b->yy_ch_buf[1] = YY_END_OF_BUFFER_CHAR;
+
+ b->yy_buf_pos = &b->yy_ch_buf[0];
+
+ b->yy_at_bol = 1;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ if ( b == YY_CURRENT_BUFFER )
+ mimeparser_yy_load_buffer_state(yyscanner );
+}
+
+/** Pushes the new state onto the stack. The new state becomes
+ * the current state. This function will allocate the stack
+ * if necessary.
+ * @param new_buffer The new state.
+ * @param yyscanner The scanner object.
+ */
+void mimeparser_yypush_buffer_state (YY_BUFFER_STATE new_buffer , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (new_buffer == NULL)
+ return;
+
+ mimeparser_yyensure_buffer_stack(yyscanner);
+
+ /* This block is copied from mimeparser_yy_switch_to_buffer. */
+ if ( YY_CURRENT_BUFFER )
+ {
+ /* Flush out information for old buffer. */
+ *yyg->yy_c_buf_p = yyg->yy_hold_char;
+ YY_CURRENT_BUFFER_LVALUE->yy_buf_pos = yyg->yy_c_buf_p;
+ YY_CURRENT_BUFFER_LVALUE->yy_n_chars = yyg->yy_n_chars;
+ }
+
+ /* Only push if top exists. Otherwise, replace top. */
+ if (YY_CURRENT_BUFFER)
+ yyg->yy_buffer_stack_top++;
+ YY_CURRENT_BUFFER_LVALUE = new_buffer;
+
+ /* copied from mimeparser_yy_switch_to_buffer. */
+ mimeparser_yy_load_buffer_state(yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+}
+
+/** Removes and deletes the top of the stack, if present.
+ * The next element becomes the new top.
+ * @param yyscanner The scanner object.
+ */
+void mimeparser_yypop_buffer_state (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ if (!YY_CURRENT_BUFFER)
+ return;
+
+ mimeparser_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner);
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ if (yyg->yy_buffer_stack_top > 0)
+ --yyg->yy_buffer_stack_top;
+
+ if (YY_CURRENT_BUFFER) {
+ mimeparser_yy_load_buffer_state(yyscanner );
+ yyg->yy_did_buffer_switch_on_eof = 1;
+ }
+}
+
+/* Allocates the stack if it does not exist.
+ * Guarantees space for at least one push.
+ */
+static void mimeparser_yyensure_buffer_stack (yyscan_t yyscanner)
+{
+ int num_to_alloc;
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (!yyg->yy_buffer_stack) {
+
+ /* First allocation is just for 2 elements, since we don't know if this
+ * scanner will even need a stack. We use 2 instead of 1 to avoid an
+ * immediate realloc on the next call.
+ */
+ num_to_alloc = 1;
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)mimeparser_yyalloc
+ (num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+
+ memset(yyg->yy_buffer_stack, 0, num_to_alloc * sizeof(struct yy_buffer_state*));
+
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ yyg->yy_buffer_stack_top = 0;
+ return;
+ }
+
+ if (yyg->yy_buffer_stack_top >= (yyg->yy_buffer_stack_max) - 1){
+
+ /* Increase the buffer to prepare for a possible push. */
+ int grow_size = 8 /* arbitrary grow size */;
+
+ num_to_alloc = yyg->yy_buffer_stack_max + grow_size;
+ yyg->yy_buffer_stack = (struct yy_buffer_state**)mimeparser_yyrealloc
+ (yyg->yy_buffer_stack,
+ num_to_alloc * sizeof(struct yy_buffer_state*)
+ , yyscanner);
+
+ /* zero only the new slots.*/
+ memset(yyg->yy_buffer_stack + yyg->yy_buffer_stack_max, 0, grow_size * sizeof(struct yy_buffer_state*));
+ yyg->yy_buffer_stack_max = num_to_alloc;
+ }
+}
+
+/** Setup the input buffer state to scan directly from a user-specified character buffer.
+ * @param base the character buffer
+ * @param size the size in bytes of the character buffer
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE mimeparser_yy_scan_buffer (char * base, yy_size_t size , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+
+ if ( size < 2 ||
+ base[size-2] != YY_END_OF_BUFFER_CHAR ||
+ base[size-1] != YY_END_OF_BUFFER_CHAR )
+ /* They forgot to leave room for the EOB's. */
+ return 0;
+
+ b = (YY_BUFFER_STATE) mimeparser_yyalloc(sizeof( struct yy_buffer_state ) ,yyscanner );
+ if ( ! b )
+ YY_FATAL_ERROR( "out of dynamic memory in mimeparser_yy_scan_buffer()" );
+
+ b->yy_buf_size = size - 2; /* "- 2" to take care of EOB's */
+ b->yy_buf_pos = b->yy_ch_buf = base;
+ b->yy_is_our_buffer = 0;
+ b->yy_input_file = 0;
+ b->yy_n_chars = b->yy_buf_size;
+ b->yy_is_interactive = 0;
+ b->yy_at_bol = 1;
+ b->yy_fill_buffer = 0;
+ b->yy_buffer_status = YY_BUFFER_NEW;
+
+ mimeparser_yy_switch_to_buffer(b ,yyscanner );
+
+ return b;
+}
+
+/** Setup the input buffer state to scan a string. The next call to mimeparser_yylex() will
+ * scan from a @e copy of @a str.
+ * @param yystr a NUL-terminated string to scan
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ * @note If you want to scan bytes that may contain NUL values, then use
+ * mimeparser_yy_scan_bytes() instead.
+ */
+YY_BUFFER_STATE mimeparser_yy_scan_string (yyconst char * yystr , yyscan_t yyscanner)
+{
+
+ return mimeparser_yy_scan_bytes(yystr,strlen(yystr) ,yyscanner);
+}
+
+/** Setup the input buffer state to scan the given bytes. The next call to mimeparser_yylex() will
+ * scan from a @e copy of @a bytes.
+ * @param bytes the byte buffer to scan
+ * @param len the number of bytes in the buffer pointed to by @a bytes.
+ * @param yyscanner The scanner object.
+ * @return the newly allocated buffer state object.
+ */
+YY_BUFFER_STATE mimeparser_yy_scan_bytes (yyconst char * yybytes, int _yybytes_len , yyscan_t yyscanner)
+{
+ YY_BUFFER_STATE b;
+ char *buf;
+ yy_size_t n;
+ int i;
+
+ /* Get memory for full buffer, including space for trailing EOB's. */
+ n = _yybytes_len + 2;
+ buf = (char *) mimeparser_yyalloc(n ,yyscanner );
+ if ( ! buf )
+ YY_FATAL_ERROR( "out of dynamic memory in mimeparser_yy_scan_bytes()" );
+
+ for ( i = 0; i < _yybytes_len; ++i )
+ buf[i] = yybytes[i];
+
+ buf[_yybytes_len] = buf[_yybytes_len+1] = YY_END_OF_BUFFER_CHAR;
+
+ b = mimeparser_yy_scan_buffer(buf,n ,yyscanner);
+ if ( ! b )
+ YY_FATAL_ERROR( "bad buffer in mimeparser_yy_scan_bytes()" );
+
+ /* It's okay to grow etc. this buffer, and we should throw it
+ * away when we're done.
+ */
+ b->yy_is_our_buffer = 1;
+
+ return b;
+}
+
+#ifndef YY_EXIT_FAILURE
+#define YY_EXIT_FAILURE 2
+#endif
+
+static void yy_fatal_error (yyconst char* msg , yyscan_t yyscanner)
+{
+ (void) fprintf( stderr, "%s\n", msg );
+ exit( YY_EXIT_FAILURE );
+}
+
+/* Redefine yyless() so it works in section 3 code. */
+
+#undef yyless
+#define yyless(n) \
+ do \
+ { \
+ /* Undo effects of setting up yytext. */ \
+ int yyless_macro_arg = (n); \
+ YY_LESS_LINENO(yyless_macro_arg);\
+ yytext[yyleng] = yyg->yy_hold_char; \
+ yyg->yy_c_buf_p = yytext + yyless_macro_arg; \
+ yyg->yy_hold_char = *yyg->yy_c_buf_p; \
+ *yyg->yy_c_buf_p = '\0'; \
+ yyleng = yyless_macro_arg; \
+ } \
+ while ( 0 )
+
+/* Accessor methods (get/set functions) to struct members. */
+
+/** Get the user-defined data for this scanner.
+ * @param yyscanner The scanner object.
+ */
+YY_EXTRA_TYPE mimeparser_yyget_extra (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyextra;
+}
+
+/** Get the current line number.
+ * @param yyscanner The scanner object.
+ */
+int mimeparser_yyget_lineno (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yylineno;
+}
+
+/** Get the current column number.
+ * @param yyscanner The scanner object.
+ */
+int mimeparser_yyget_column (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ if (! YY_CURRENT_BUFFER)
+ return 0;
+
+ return yycolumn;
+}
+
+/** Get the input stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *mimeparser_yyget_in (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyin;
+}
+
+/** Get the output stream.
+ * @param yyscanner The scanner object.
+ */
+FILE *mimeparser_yyget_out (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyout;
+}
+
+/** Get the length of the current token.
+ * @param yyscanner The scanner object.
+ */
+int mimeparser_yyget_leng (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yyleng;
+}
+
+/** Get the current token.
+ * @param yyscanner The scanner object.
+ */
+
+char *mimeparser_yyget_text (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yytext;
+}
+
+/** Set the user-defined data. This data is never touched by the scanner.
+ * @param user_defined The data to be associated with this scanner.
+ * @param yyscanner The scanner object.
+ */
+void mimeparser_yyset_extra (YY_EXTRA_TYPE user_defined , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyextra = user_defined ;
+}
+
+/** Set the current line number.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void mimeparser_yyset_lineno (int line_number , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* lineno is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ yy_fatal_error( "mimeparser_yyset_lineno called with no buffer" , yyscanner);
+
+ yylineno = line_number;
+}
+
+/** Set the current column.
+ * @param line_number
+ * @param yyscanner The scanner object.
+ */
+void mimeparser_yyset_column (int column_no , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* column is only valid if an input buffer exists. */
+ if (! YY_CURRENT_BUFFER )
+ yy_fatal_error( "mimeparser_yyset_column called with no buffer" , yyscanner);
+
+ yycolumn = column_no;
+}
+
+/** Set the input stream. This does not discard the current
+ * input buffer.
+ * @param in_str A readable stream.
+ * @param yyscanner The scanner object.
+ * @see mimeparser_yy_switch_to_buffer
+ */
+void mimeparser_yyset_in (FILE * in_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyin = in_str ;
+}
+
+void mimeparser_yyset_out (FILE * out_str , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyout = out_str ;
+}
+
+int mimeparser_yyget_debug (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yy_flex_debug;
+}
+
+void mimeparser_yyset_debug (int bdebug , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yy_flex_debug = bdebug ;
+}
+
+/* Accessor methods for yylval and yylloc */
+
+YYSTYPE * mimeparser_yyget_lval (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ return yylval;
+}
+
+void mimeparser_yyset_lval (YYSTYPE * yylval_param , yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yylval = yylval_param;
+}
+
+/* User-visible API */
+
+/* mimeparser_yylex_init is special because it creates the scanner itself, so it is
+ * the ONLY reentrant function that doesn't take the scanner as the last argument.
+ * That's why we explicitly handle the declaration, instead of using our macros.
+ */
+
+int mimeparser_yylex_init(yyscan_t* ptr_yy_globals)
+
+{
+ if (ptr_yy_globals == NULL){
+ errno = EINVAL;
+ return 1;
+ }
+
+ *ptr_yy_globals = (yyscan_t) mimeparser_yyalloc ( sizeof( struct yyguts_t ), NULL );
+
+ if (*ptr_yy_globals == NULL){
+ errno = ENOMEM;
+ return 1;
+ }
+
+ /* By setting to 0xAA, we expose bugs in yy_init_globals. Leave at 0x00 for releases. */
+ memset(*ptr_yy_globals,0x00,sizeof(struct yyguts_t));
+
+ return yy_init_globals ( *ptr_yy_globals );
+}
+
+static int yy_init_globals (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ /* Initialization is the same as for the non-reentrant scanner.
+ * This function is called from mimeparser_yylex_destroy(), so don't allocate here.
+ */
+
+ yyg->yy_buffer_stack = 0;
+ yyg->yy_buffer_stack_top = 0;
+ yyg->yy_buffer_stack_max = 0;
+ yyg->yy_c_buf_p = (char *) 0;
+ yyg->yy_init = 0;
+ yyg->yy_start = 0;
+
+ yyg->yy_start_stack_ptr = 0;
+ yyg->yy_start_stack_depth = 0;
+ yyg->yy_start_stack = NULL;
+
+ yyg->yy_state_buf = 0;
+ yyg->yy_state_ptr = 0;
+ yyg->yy_full_match = 0;
+ yyg->yy_lp = 0;
+
+/* Defined in main.c */
+#ifdef YY_STDINIT
+ yyin = stdin;
+ yyout = stdout;
+#else
+ yyin = (FILE *) 0;
+ yyout = (FILE *) 0;
+#endif
+
+ /* For future reference: Set errno on error, since we are called by
+ * mimeparser_yylex_init()
+ */
+ return 0;
+}
+
+/* mimeparser_yylex_destroy is for both reentrant and non-reentrant scanners. */
+int mimeparser_yylex_destroy (yyscan_t yyscanner)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+
+ /* Pop the buffer stack, destroying each element. */
+ while(YY_CURRENT_BUFFER){
+ mimeparser_yy_delete_buffer(YY_CURRENT_BUFFER ,yyscanner );
+ YY_CURRENT_BUFFER_LVALUE = NULL;
+ mimeparser_yypop_buffer_state(yyscanner);
+ }
+
+ /* Destroy the stack itself. */
+ mimeparser_yyfree(yyg->yy_buffer_stack ,yyscanner);
+ yyg->yy_buffer_stack = NULL;
+
+ /* Destroy the start condition stack. */
+ mimeparser_yyfree(yyg->yy_start_stack ,yyscanner );
+ yyg->yy_start_stack = NULL;
+
+ mimeparser_yyfree ( yyg->yy_state_buf , yyscanner);
+ yyg->yy_state_buf = NULL;
+
+ /* Reset the globals. This is important in a non-reentrant scanner so the next time
+ * mimeparser_yylex() is called, initialization will occur. */
+ yy_init_globals( yyscanner);
+
+ /* Destroy the main struct (reentrant only). */
+ mimeparser_yyfree ( yyscanner , yyscanner );
+ yyscanner = NULL;
+ return 0;
+}
+
+/*
+ * Internal utility routines.
+ */
+
+#ifndef yytext_ptr
+static void yy_flex_strncpy (char* s1, yyconst char * s2, int n , yyscan_t yyscanner)
+{
+ register int i;
+ for ( i = 0; i < n; ++i )
+ s1[i] = s2[i];
+}
+#endif
+
+#ifdef YY_NEED_STRLEN
+static int yy_flex_strlen (yyconst char * s , yyscan_t yyscanner)
+{
+ register int n;
+ for ( n = 0; s[n]; ++n )
+ ;
+
+ return n;
+}
+#endif
+
+void *mimeparser_yyalloc (yy_size_t size , yyscan_t yyscanner)
+{
+ return (void *) malloc( size );
+}
+
+void *mimeparser_yyrealloc (void * ptr, yy_size_t size , yyscan_t yyscanner)
+{
+ /* The cast to (char *) in the following accommodates both
+ * implementations that use char* generic pointers, and those
+ * that use void* generic pointers. It works with the latter
+ * because both ANSI C and C++ allow castless assignment from
+ * any pointer type to void*, and deal with argument conversions
+ * as though doing an assignment.
+ */
+ return (void *) realloc( (char *) ptr, size );
+}
+
+void mimeparser_yyfree (void * ptr , yyscan_t yyscanner)
+{
+ free( (char *) ptr ); /* see mimeparser_yyrealloc() for (char *) cast */
+}
+
+#define YYTABLES_NAME "yytables"
+
+#line 416 "mimeparser.l"
+
+
+
+void reset_lexer_state(void *yyscanner, struct parser_state *pstate)
+{
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ struct lexer_state *lstate = &(pstate->lstate);
+
+ mimeparser_yyset_extra((void*)lstate,yyscanner);
+ BEGIN(0);
+ lstate->header_state = STATE_MAIL;
+ lstate->lineno = 0;
+ lstate->current_pos = 1;
+ lstate->condition = 0;
+
+ lstate->is_envelope = 1;
+
+ lstate->message_len = 0;
+ lstate->buffer_length = 0;
+
+ /* temporary marker variables */
+ lstate->body_opaque_start = 0;
+ lstate->body_start = 0;
+ lstate->body_end = 0;
+ lstate->preamble_start = 0;
+ lstate->preamble_end = 0;
+ lstate->postamble_start = 0;
+ lstate->postamble_end = 0;
+}
+
+void
+PARSER_setbuffer(char *string, yyscan_t scanner)
+{
+ struct lexer_state *lstate = mimeparser_yyget_extra(scanner);
+ lstate->message_buffer = string;
+ mimeparser_yy_scan_string(string,scanner);
+}
+
+void
+PARSER_setfp(FILE *fp, yyscan_t yyscanner)
+{
+ /* looks like a bug in bison 2.2a -- the wrong code is generated for mimeparser_yyset_in !! */
+ struct yyguts_t * yyg = (struct yyguts_t*)yyscanner;
+ yyg->yyin_r = fp;
+
+ if (0) {
+ /* This is just to make a compiler warning go away */
+ yyunput(0, NULL, yyscanner);
+ }
+}
+
+/**
+ * Counts how many lines a given string represents in the message (in case of
+ * folded header values, for example, or a message body).
+ */
+int
+count_lines(char *txt)
+{
+ char *o;
+ int line;
+
+ line = 0;
+
+ for (o = txt; *o != '\0'; o++)
+ if (*o == '\n')
+ line++;
+
+ return line;
+}
+
diff --git a/main/minimime/minimime.c b/main/minimime/minimime.c
new file mode 100644
index 000000000..f96b62fb1
--- /dev/null
+++ b/main/minimime/minimime.c
@@ -0,0 +1,245 @@
+/*
+ * Copyright (c) 2004 Jann Fischer. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * MiniMIME test program
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <err.h>
+
+#include "mm.h"
+
+void
+usage(void)
+{
+ fprintf(stderr,
+ "MiniMIME test suite\n"
+ "Usage: ./minimime [-m] <filename>\n\n"
+ " -m : use memory based scanning\n\n"
+ );
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ MM_CTX *ctx;
+ struct mm_mimeheader *header, *lastheader;
+ struct mm_warning *lastwarning;
+ struct mm_mimepart *part;
+ struct mm_content *ct;
+ int parts, i;
+ struct stat st;
+ int fd;
+ char *buf;
+ int scan_mode = 0;
+
+ lastheader = NULL;
+
+ while ((i = getopt(argc, argv, "m")) != -1) {
+ switch(i) {
+ case 'm':
+ scan_mode = 1;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1) {
+ usage();
+ }
+
+#ifdef __HAVE_LEAK_DETECTION
+ /* Initialize memory leak detection if compiled in */
+ MM_leakd_init();
+#endif
+
+ /* Initialize MiniMIME library */
+ mm_library_init();
+
+ /* Register all default codecs (base64/qp) */
+ mm_codec_registerdefaultcodecs();
+
+ do {
+ /* Create a new context */
+ ctx = mm_context_new();
+
+ /* Parse a file into our context */
+ if (scan_mode == 0) {
+ i = mm_parse_file(ctx, argv[0], MM_PARSE_LOOSE, 0);
+ } else {
+ if (stat(argv[0], &st) == -1) {
+ err(1, "stat");
+ }
+
+ if ((fd = open(argv[0], O_RDONLY)) == -1) {
+ err(1, "open");
+ }
+
+ buf = (char *)malloc(st.st_size);
+ if (buf == NULL) {
+ err(1, "malloc");
+ }
+
+ if (read(fd, buf, st.st_size) != st.st_size) {
+ err(1, "read");
+ }
+
+ close(fd);
+ buf[st.st_size] = '\0';
+
+ i = mm_parse_mem(ctx, buf, MM_PARSE_LOOSE, 0);
+ }
+
+ if (i == -1 || mm_errno != MM_ERROR_NONE) {
+ printf("ERROR: %s at line %d\n", mm_error_string(), mm_error_lineno());
+ exit(1);
+ }
+
+ /* Get the number of MIME parts */
+ parts = mm_context_countparts(ctx);
+ if (parts == 0) {
+ printf("ERROR: got zero MIME parts, huh\n");
+ exit(1);
+ } else {
+ if (mm_context_iscomposite(ctx)) {
+ printf("Got %d MIME parts\n", parts - 1);
+ } else {
+ printf("Flat message (not multipart)\n");
+ }
+ }
+
+ /* Get the main MIME part */
+ part = mm_context_getpart(ctx, 0);
+ if (part == NULL) {
+ fprintf(stderr, "Could not get envelope part\n");
+ exit(1);
+ }
+
+ printf("Printing envelope headers:\n");
+ /* Print all headers */
+ if (mm_mimepart_headers_start(part, &lastheader) == -1) {
+ fprintf(stderr, "No headers in envelope\n");
+ exit(1);
+ }
+ while ((header = mm_mimepart_headers_next(part, &lastheader)) != NULL) {
+ printf("%s: %s\n", header->name, header->value);
+ }
+
+ printf("%s\n", mm_content_tostring(part->type));
+ printf("\n");
+
+ ct = part->type;
+ assert(ct != NULL);
+
+ if (mm_context_iscomposite(ctx) == 0) {
+ printf("Printing body part for FLAT message:\n");
+ part = mm_context_getpart(ctx, 0);
+ printf("%s", part->body);
+ }
+
+ /* Loop through all MIME parts beginning with 1 */
+ for (i = 1; i < mm_context_countparts(ctx); i++) {
+ char *decoded;
+
+ printf("Printing headers for MIME part %d\n", i);
+
+ /* Get the current MIME entity */
+ part = mm_context_getpart(ctx, i);
+ if (part == NULL) {
+ fprintf(stderr, "Should have %d parts but "
+ "couldn't retrieve part %d",
+ mm_context_countparts(ctx), i);
+ exit(1);
+ }
+
+ /* Print all headers */
+ if (mm_mimepart_headers_start(part, &lastheader) == -1) {
+ printf("Ups no headers\n");
+ }
+ while ((header = mm_mimepart_headers_next(part, &lastheader)) != NULL) {
+ printf("%s: %s\n", header->name, header->value);
+ }
+
+ printf("Part Type: %s\n", mm_content_tostring(part->type));
+
+ /* Print MIME part body */
+ printf("\nPrinting message BODY:\n%s\n", (char *)part->opaque_body);
+ decoded = mm_mimepart_decode(part);
+ if (decoded != NULL) {
+ printf("DECODED:\n%s\n", decoded);
+ free(decoded);
+ }
+ }
+
+ /* Print out all warnings that we might have received */
+ if (mm_context_haswarnings(ctx) > 0) {
+ lastwarning = NULL;
+ fprintf(stderr, "WARNINGS:\n");
+#if 0
+ while ((warning = mm_warning_next(ctx, &lastwarning))
+ != NULL) {
+ fprintf(stderr, " -> %s\n", warning->message);
+ }
+#endif
+ }
+
+ printf("ENVELOPE:\n");
+
+ do {
+ char *env;
+ size_t env_len;
+
+ mm_context_flatten(ctx, &env, &env_len, 0);
+ printf("%s", env);
+
+ } while (0);
+
+ mm_context_free(ctx);
+ ctx = NULL;
+
+#ifdef __HAVE_LEAK_DETECTION
+ MM_leakd_printallocated();
+#endif
+
+ } while (0);
+
+ return 0;
+}
diff --git a/main/minimime/mm-docs/html/bug.html b/main/minimime/mm-docs/html/bug.html
new file mode 100644
index 000000000..61f89acc8
--- /dev/null
+++ b/main/minimime/mm-docs/html/bug.html
@@ -0,0 +1,28 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: Bug List</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<h1><a class="anchor" name="bug">Bug List</a></h1><a class="anchor" name="_bug000001"></a> <dl>
+<dt>Global <a class="el" href="group__contenttype.html#g7bab273d117c6c0cacad20361d8fb1c8">mm_content_setmaintype</a> </dt>
+<dd>The xfree() call could lead to undesirable results. Do we really need it? </dd>
+</dl>
+<p>
+<a class="anchor" name="_bug000002"></a> <dl>
+<dt>Global <a class="el" href="group__contenttype.html#g14b0738410d566ad2312405946f22212">mm_content_setsubtype</a> </dt>
+<dd>The xfree() call could lead to undesirable results. Do we really need it? </dd>
+</dl>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/doxygen.css b/main/minimime/mm-docs/html/doxygen.css
new file mode 100644
index 000000000..c7db1a8a0
--- /dev/null
+++ b/main/minimime/mm-docs/html/doxygen.css
@@ -0,0 +1,358 @@
+BODY,H1,H2,H3,H4,H5,H6,P,CENTER,TD,TH,UL,DL,DIV {
+ font-family: Geneva, Arial, Helvetica, sans-serif;
+}
+BODY,TD {
+ font-size: 90%;
+}
+H1 {
+ text-align: center;
+ font-size: 160%;
+}
+H2 {
+ font-size: 120%;
+}
+H3 {
+ font-size: 100%;
+}
+CAPTION { font-weight: bold }
+DIV.qindex {
+ width: 100%;
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ padding: 2px;
+ line-height: 140%;
+}
+DIV.nav {
+ width: 100%;
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ padding: 2px;
+ line-height: 140%;
+}
+DIV.navtab {
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ margin-right: 15px;
+ padding: 2px;
+}
+TD.navtab {
+ font-size: 70%;
+}
+A.qindex {
+ text-decoration: none;
+ font-weight: bold;
+ color: #1A419D;
+}
+A.qindex:visited {
+ text-decoration: none;
+ font-weight: bold;
+ color: #1A419D
+}
+A.qindex:hover {
+ text-decoration: none;
+ background-color: #ddddff;
+}
+A.qindexHL {
+ text-decoration: none;
+ font-weight: bold;
+ background-color: #6666cc;
+ color: #ffffff;
+ border: 1px double #9295C2;
+}
+A.qindexHL:hover {
+ text-decoration: none;
+ background-color: #6666cc;
+ color: #ffffff;
+}
+A.qindexHL:visited { text-decoration: none; background-color: #6666cc; color: #ffffff }
+A.el { text-decoration: none; font-weight: bold }
+A.elRef { font-weight: bold }
+A.code:link { text-decoration: none; font-weight: normal; color: #0000FF}
+A.code:visited { text-decoration: none; font-weight: normal; color: #0000FF}
+A.codeRef:link { font-weight: normal; color: #0000FF}
+A.codeRef:visited { font-weight: normal; color: #0000FF}
+A:hover { text-decoration: none; background-color: #f2f2ff }
+DL.el { margin-left: -1cm }
+.fragment {
+ font-family: monospace, fixed;
+ font-size: 95%;
+}
+PRE.fragment {
+ border: 1px solid #CCCCCC;
+ background-color: #f5f5f5;
+ margin-top: 4px;
+ margin-bottom: 4px;
+ margin-left: 2px;
+ margin-right: 8px;
+ padding-left: 6px;
+ padding-right: 6px;
+ padding-top: 4px;
+ padding-bottom: 4px;
+}
+DIV.ah { background-color: black; font-weight: bold; color: #ffffff; margin-bottom: 3px; margin-top: 3px }
+
+DIV.groupHeader {
+ margin-left: 16px;
+ margin-top: 12px;
+ margin-bottom: 6px;
+ font-weight: bold;
+}
+DIV.groupText { margin-left: 16px; font-style: italic; font-size: 90% }
+BODY {
+ background: white;
+ color: black;
+ margin-right: 20px;
+ margin-left: 20px;
+}
+TD.indexkey {
+ background-color: #e8eef2;
+ font-weight: bold;
+ padding-right : 10px;
+ padding-top : 2px;
+ padding-left : 10px;
+ padding-bottom : 2px;
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 2px;
+ margin-bottom : 2px;
+ border: 1px solid #CCCCCC;
+}
+TD.indexvalue {
+ background-color: #e8eef2;
+ font-style: italic;
+ padding-right : 10px;
+ padding-top : 2px;
+ padding-left : 10px;
+ padding-bottom : 2px;
+ margin-left : 0px;
+ margin-right : 0px;
+ margin-top : 2px;
+ margin-bottom : 2px;
+ border: 1px solid #CCCCCC;
+}
+TR.memlist {
+ background-color: #f0f0f0;
+}
+P.formulaDsp { text-align: center; }
+IMG.formulaDsp { }
+IMG.formulaInl { vertical-align: middle; }
+SPAN.keyword { color: #008000 }
+SPAN.keywordtype { color: #604020 }
+SPAN.keywordflow { color: #e08000 }
+SPAN.comment { color: #800000 }
+SPAN.preprocessor { color: #806020 }
+SPAN.stringliteral { color: #002080 }
+SPAN.charliteral { color: #008080 }
+.mdescLeft {
+ padding: 0px 8px 4px 8px;
+ font-size: 80%;
+ font-style: italic;
+ background-color: #FAFAFA;
+ border-top: 1px none #E0E0E0;
+ border-right: 1px none #E0E0E0;
+ border-bottom: 1px none #E0E0E0;
+ border-left: 1px none #E0E0E0;
+ margin: 0px;
+}
+.mdescRight {
+ padding: 0px 8px 4px 8px;
+ font-size: 80%;
+ font-style: italic;
+ background-color: #FAFAFA;
+ border-top: 1px none #E0E0E0;
+ border-right: 1px none #E0E0E0;
+ border-bottom: 1px none #E0E0E0;
+ border-left: 1px none #E0E0E0;
+ margin: 0px;
+}
+.memItemLeft {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memItemRight {
+ padding: 1px 8px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplItemLeft {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: none;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplItemRight {
+ padding: 1px 8px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: none;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.memTemplParams {
+ padding: 1px 0px 0px 8px;
+ margin: 4px;
+ border-top-width: 1px;
+ border-right-width: 1px;
+ border-bottom-width: 1px;
+ border-left-width: 1px;
+ border-top-color: #E0E0E0;
+ border-right-color: #E0E0E0;
+ border-bottom-color: #E0E0E0;
+ border-left-color: #E0E0E0;
+ border-top-style: solid;
+ border-right-style: none;
+ border-bottom-style: none;
+ border-left-style: none;
+ color: #606060;
+ background-color: #FAFAFA;
+ font-size: 80%;
+}
+.search { color: #003399;
+ font-weight: bold;
+}
+FORM.search {
+ margin-bottom: 0px;
+ margin-top: 0px;
+}
+INPUT.search { font-size: 75%;
+ color: #000080;
+ font-weight: normal;
+ background-color: #e8eef2;
+}
+TD.tiny { font-size: 75%;
+}
+a {
+ color: #1A41A8;
+}
+a:visited {
+ color: #2A3798;
+}
+.dirtab { padding: 4px;
+ border-collapse: collapse;
+ border: 1px solid #84b0c7;
+}
+TH.dirtab { background: #e8eef2;
+ font-weight: bold;
+}
+HR { height: 1px;
+ border: none;
+ border-top: 1px solid black;
+}
+
+/* Style for detailed member documentation */
+.memtemplate {
+ font-size: 80%;
+ color: #606060;
+ font-weight: normal;
+}
+.memnav {
+ background-color: #e8eef2;
+ border: 1px solid #84b0c7;
+ text-align: center;
+ margin: 2px;
+ margin-right: 15px;
+ padding: 2px;
+}
+.memitem {
+ padding: 4px;
+ background-color: #eef3f5;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #dedeee;
+ -moz-border-radius: 8px 8px 8px 8px;
+}
+.memname {
+ white-space: nowrap;
+ font-weight: bold;
+}
+.memdoc{
+ padding-left: 10px;
+}
+.memproto {
+ background-color: #d5e1e8;
+ width: 100%;
+ border-width: 1px;
+ border-style: solid;
+ border-color: #84b0c7;
+ font-weight: bold;
+ -moz-border-radius: 8px 8px 8px 8px;
+}
+.paramkey {
+ text-align: right;
+}
+.paramtype {
+ white-space: nowrap;
+}
+.paramname {
+ color: #602020;
+ font-style: italic;
+ white-space: nowrap;
+}
+/* End Styling for detailed member documentation */
+
+/* for the tree view */
+.ftvtree {
+ font-family: sans-serif;
+ margin:0.5em;
+}
+.directory { font-size: 9pt; font-weight: bold; }
+.directory h3 { margin: 0px; margin-top: 1em; font-size: 11pt; }
+.directory > h3 { margin-top: 0; }
+.directory p { margin: 0px; white-space: nowrap; }
+.directory div { display: none; margin: 0px; }
+.directory img { vertical-align: -30%; }
diff --git a/main/minimime/mm-docs/html/files.html b/main/minimime/mm-docs/html/files.html
new file mode 100644
index 000000000..df53367c9
--- /dev/null
+++ b/main/minimime/mm-docs/html/files.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: File Index</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li id="current"><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>MiniMIME File List</h1>Here is a list of all documented files with brief descriptions:<table>
+ <tr><td class="indexkey"><b>mimeparser.h</b> <a href="mimeparser_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><b>mimeparser.tab.h</b> <a href="mimeparser_8tab_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><b>mm.h</b> <a href="mm_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><a class="el" href="mm__codecs_8c.html">mm_codecs.c</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><a class="el" href="mm__contenttype_8c.html">mm_contenttype.c</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><a class="el" href="mm__context_8c.html">mm_context.c</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><a class="el" href="mm__envelope_8c.html">mm_envelope.c</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><a class="el" href="mm__error_8c.html">mm_error.c</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><a class="el" href="mm__header_8c.html">mm_header.c</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><a class="el" href="mm__internal_8h.html">mm_internal.h</a> <a href="mm__internal_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><b>mm_mem.h</b> <a href="mm__mem_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><a class="el" href="mm__mimepart_8c.html">mm_mimepart.c</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><a class="el" href="mm__mimeutil_8c.html">mm_mimeutil.c</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><a class="el" href="mm__param_8c.html">mm_param.c</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><a class="el" href="mm__parse_8c.html">mm_parse.c</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><b>mm_queue.h</b> <a href="mm__queue_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><a class="el" href="mm__util_8c.html">mm_util.c</a></td><td class="indexvalue"></td></tr>
+ <tr><td class="indexkey"><b>mm_util.h</b> <a href="mm__util_8h-source.html">[code]</a></td><td class="indexvalue"></td></tr>
+</table>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:09 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/globals.html b/main/minimime/mm-docs/html/globals.html
new file mode 100644
index 000000000..b8a90462c
--- /dev/null
+++ b/main/minimime/mm-docs/html/globals.html
@@ -0,0 +1,198 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: Data Fields</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li id="current"><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li id="current"><a href="globals.html"><span>All</span></a></li>
+ <li><a href="globals_func.html"><span>Functions</span></a></li>
+ </ul>
+</div>
+<div class="tabs">
+ <ul>
+ <li><a href="#index_m"><span>m</span></a></li>
+ <li><a href="#index_x"><span>x</span></a></li>
+ </ul>
+</div>
+
+<p>
+Here is a list of all documented functions, variables, defines, enums, and typedefs with links to the documentation:
+<p>
+<h3><a class="anchor" name="index_m">- m -</a></h3><ul>
+<li>mm_addchars()
+: <a class="el" href="group__util.html#g0747d4b4e33644263e6d73d2d8d4818b">mm_util.c</a>
+<li>mm_codec_hasdecoder()
+: <a class="el" href="group__codecs.html#g6ccb0f7a1d7c870dc3dae04f31d6ccca">mm_codecs.c</a>
+<li>mm_codec_hasencoder()
+: <a class="el" href="group__codecs.html#g50ff257b794ceaec7aedf9ae18bfcc57">mm_codecs.c</a>
+<li>mm_codec_isregistered()
+: <a class="el" href="group__codecs.html#g9e19f6343128fd7e4ec57c3d55049b55">mm_codecs.c</a>
+<li>mm_codec_register()
+: <a class="el" href="group__codecs.html#gf97a7311c909888ed9f6f14d6f1bf397">mm_codecs.c</a>
+<li>mm_codec_registerdefaultcodecs()
+: <a class="el" href="group__codecs.html#gf39e72460fb85f5ca41f6e270a68aacc">mm_codecs.c</a>
+<li>mm_codec_unregister()
+: <a class="el" href="group__codecs.html#g0c71696bc70f834386193e3c7a0e2ca4">mm_codecs.c</a>
+<li>mm_codec_unregisterall()
+: <a class="el" href="group__codecs.html#g7c9e6538f84c368be2b56a3c9ba702be">mm_codecs.c</a>
+<li>mm_content_attachparam()
+: <a class="el" href="group__contenttype.html#g080b7ed798ed497dcd635a6bab86962f">mm_contenttype.c</a>
+<li>mm_content_free()
+: <a class="el" href="group__contenttype.html#g404314481125849bce869ee4b0f647af">mm_contenttype.c</a>
+<li>mm_content_getencoding()
+: <a class="el" href="group__contenttype.html#gbff87e581cd04db16e91245e9e9de67d">mm_contenttype.c</a>
+<li>mm_content_getmaintype()
+: <a class="el" href="group__contenttype.html#gb213081017abf6bc7e601c6bf4214924">mm_contenttype.c</a>
+<li>mm_content_getparambyname()
+: <a class="el" href="group__contenttype.html#g451441ee557ab5ef29477f3dc8330bf6">mm_contenttype.c</a>
+<li>mm_content_getsubtype()
+: <a class="el" href="group__contenttype.html#g97f77ef40c14cd0fb397bad358ee5d49">mm_contenttype.c</a>
+<li>mm_content_iscomposite()
+: <a class="el" href="group__contenttype.html#ga7fa479f27e73dea57257421d8fc9fc5">mm_contenttype.c</a>
+<li>mm_content_isvalidencoding()
+: <a class="el" href="group__contenttype.html#gb724b5979182fa272fe4fd1b72b395d5">mm_contenttype.c</a>
+<li>mm_content_new()
+: <a class="el" href="group__contenttype.html#g3880ac74a20b4a9f610a4159568e1801">mm_contenttype.c</a>
+<li>mm_content_paramstostring()
+: <a class="el" href="group__contenttype.html#g792e7d33fbb30e0123408bcef9d3204c">mm_contenttype.c</a>
+<li>mm_content_setencoding()
+: <a class="el" href="group__contenttype.html#gea945e48ac5cca846715543634b9afe4">mm_contenttype.c</a>
+<li>mm_content_setmaintype()
+: <a class="el" href="group__contenttype.html#g7bab273d117c6c0cacad20361d8fb1c8">mm_contenttype.c</a>
+<li>mm_content_setsubtype()
+: <a class="el" href="group__contenttype.html#g14b0738410d566ad2312405946f22212">mm_contenttype.c</a>
+<li>mm_content_tostring()
+: <a class="el" href="group__contenttype.html#g18a99c95e35a76f13a77a83c4231e738">mm_contenttype.c</a>
+<li>mm_context_attachpart()
+: <a class="el" href="group__context.html#gec3ca486a61b392ff68774242086768e">mm_context.c</a>
+<li>mm_context_attachpart_after()
+: <a class="el" href="group__context.html#g73a3dd187053aeabca4836dc28a6c468">mm_context.c</a>
+<li>mm_context_countparts()
+: <a class="el" href="group__context.html#gf5bb032ad1c481d31d7b1b0710939712">mm_context.c</a>
+<li>mm_context_deletepart()
+: <a class="el" href="group__context.html#g53d20c33a401539ef1ffa45f3dddb983">mm_context.c</a>
+<li>mm_context_flatten()
+: <a class="el" href="group__context.html#g5288136ab923605f6508c09359ae5772">mm_context.c</a>
+<li>mm_context_free()
+: <a class="el" href="group__context.html#g76392d5269e9ef340c2f5f8336f7193b">mm_context.c</a>
+<li>mm_context_generateboundary()
+: <a class="el" href="group__context.html#g9710e485f51167099d90f0d659979068">mm_context.c</a>
+<li>mm_context_getpart()
+: <a class="el" href="group__context.html#g57fea229675f3e56a77eb40bb8193ee3">mm_context.c</a>
+<li>mm_context_haswarnings()
+: <a class="el" href="group__context.html#g8733dee7d83d3205349a7ee4ee5b2750">mm_context.c</a>
+<li>mm_context_iscomposite()
+: <a class="el" href="group__context.html#g1e73cadba4acd3ef9dd148dd0c2c3e70">mm_context.c</a>
+<li>mm_context_new()
+: <a class="el" href="group__context.html#g919fd41f85534d9c87c256857faa2610">mm_context.c</a>
+<li>mm_context_setpreamble()
+: <a class="el" href="group__context.html#gc0e7cc297516618d4773830a1988fc8d">mm_context.c</a>
+<li>mm_envelope_getheaders()
+: <a class="el" href="group__envelope.html#g38f1164142cedfc3253b068a81f85563">mm_envelope.c</a>
+<li>mm_envelope_getrecipients()
+: <a class="el" href="group__envelope.html#ge63da17c56867ca2406a4eaf73230baf">mm_envelope.c</a>
+<li>mm_envelope_setheader()
+: <a class="el" href="group__envelope.html#gb2c43c1645e42ae0860c902ce1dda788">mm_envelope.c</a>
+<li>mm_error_init()
+: <a class="el" href="group__error.html#g69de7c9bee1d535593a55807590de543">mm_error.c</a>
+<li>mm_error_setmsg()
+: <a class="el" href="group__error.html#g92006c97728639d8f32f5bc4c6e2a47f">mm_error.c</a>
+<li>mm_error_string()
+: <a class="el" href="group__error.html#g8654857a3ac349b87d798902912371a3">mm_error.c</a>
+<li>mm_mimeheader_free()
+: <a class="el" href="mm__header_8c.html#61e3e62728f720ac381196ec59303064">mm_header.c</a>
+<li>mm_mimeheader_generate()
+: <a class="el" href="mm__header_8c.html#07a7f7dcebc91aa86f5478e1d84341a1">mm_header.c</a>
+<li>mm_mimeheader_new()
+: <a class="el" href="mm__header_8c.html#2f2c5f2f640111caf3096ed46b5986a4">mm_header.c</a>
+<li>mm_mimepart_attachcontenttype()
+: <a class="el" href="group__mimepart.html#g01822bc93b4741af75b5379384354e37">mm_mimepart.c</a>
+<li>mm_mimepart_attachheader()
+: <a class="el" href="group__mimepart.html#g46a674ff6b9873c0c45fa4eb5d94fd62">mm_mimepart.c</a>
+<li>mm_mimepart_countheaderbyname()
+: <a class="el" href="group__mimepart.html#gf89da502ac54306994bdb452448a8026">mm_mimepart.c</a>
+<li>mm_mimepart_countheaders()
+: <a class="el" href="group__mimepart.html#g44c78abfb0535312bcb427a2cd220026">mm_mimepart.c</a>
+<li>mm_mimepart_decode()
+: <a class="el" href="group__mimepart.html#g4551bf4460e5d165bbcd9f32d4f625de">mm_mimepart.c</a>
+<li>mm_mimepart_flatten()
+: <a class="el" href="group__mimepart.html#gf19d3ace5ae174b3eaa35f9ddbe6e216">mm_mimepart.c</a>
+<li>mm_mimepart_free()
+: <a class="el" href="group__mimepart.html#gbf47790a0bb96b22bc5e236bc40cb32e">mm_mimepart.c</a>
+<li>mm_mimepart_fromfile()
+: <a class="el" href="group__mimepart.html#ged8112012a337371ae8093adb1ab6d27">mm_mimepart.c</a>
+<li>mm_mimepart_getbody()
+: <a class="el" href="group__mimepart.html#g52dc9f27a2801e4f6abb1effd2ed838d">mm_mimepart.c</a>
+<li>mm_mimepart_getheaderbyname()
+: <a class="el" href="group__mimepart.html#ga3ca298eaa82f4ef3ea731511ac84e53">mm_mimepart.c</a>
+<li>mm_mimepart_getheadervalue()
+: <a class="el" href="group__mimepart.html#g779f11f7a6a54f83763b5ef6ff87e48f">mm_mimepart.c</a>
+<li>mm_mimepart_getlength()
+: <a class="el" href="group__mimepart.html#gf8ccae1737dc4b9b91958fe448da677f">mm_mimepart.c</a>
+<li>mm_mimepart_gettype()
+: <a class="el" href="group__mimepart.html#g210e2ceee56f8349f6778006da87d080">mm_mimepart.c</a>
+<li>mm_mimepart_headers_next()
+: <a class="el" href="group__mimepart.html#g8e9064736efdeebf4b257cc45f8a6adf">mm_mimepart.c</a>
+<li>mm_mimepart_headers_start()
+: <a class="el" href="group__mimepart.html#g4440bdcfddf88eb642b6a834a0557176">mm_mimepart.c</a>
+<li>mm_mimepart_new()
+: <a class="el" href="group__mimepart.html#g417e5dd361e30cddb91e1d9a5e30b223">mm_mimepart.c</a>
+<li>mm_mimepart_setbody()
+: <a class="el" href="group__mimepart.html#gd1def098c00edc546b03e98e9ff8b27a">mm_mimepart.c</a>
+<li>mm_mimepart_setdefaultcontenttype()
+: <a class="el" href="group__mimepart.html#g164bb39a266559574c252f11266809ff">mm_mimepart.c</a>
+<li>mm_mimeutil_gendate()
+: <a class="el" href="mm__mimeutil_8c.html#a7b7f63b42dfa7a7f907b615aa4cd057">mm_mimeutil.c</a>
+<li>mm_param_free()
+: <a class="el" href="group__param.html#g46339038e995799e6a3e37512f442fc9">mm_param.c</a>
+<li>mm_param_generate()
+: <a class="el" href="group__param.html#gd3970def45b8bede334f4b89a41dec15">mm_param.c</a>
+<li>mm_param_getname()
+: <a class="el" href="group__param.html#g0e0ddccf47a2b1e0ad5bcc52c7b39753">mm_param.c</a>
+<li>mm_param_getvalue()
+: <a class="el" href="group__param.html#g3c6f8cddd409de3000c31584e140561e">mm_param.c</a>
+<li>mm_param_new()
+: <a class="el" href="group__param.html#gd3ac756551bf5a29a07d5992bfdbde09">mm_param.c</a>
+<li>mm_param_setname()
+: <a class="el" href="group__param.html#g2a266c63c7e89cf829b2af8e995e55e8">mm_param.c</a>
+<li>mm_param_setvalue()
+: <a class="el" href="group__param.html#gca3e636ab5700462eb32ca5bc19e4cc6">mm_param.c</a>
+<li>mm_parse_file()
+: <a class="el" href="mm__parse_8c.html#cc9f623682b05f330c46e72e4e9d66cc">mm_parse.c</a>
+<li>mm_parse_mem()
+: <a class="el" href="mm__parse_8c.html#58c960b6017f13d4e4ec5f09b3c38495">mm_parse.c</a>
+<li>mm_stripchars()
+: <a class="el" href="group__util.html#gf62be7dd21e545f8db72f3c9e3b6a3c3">mm_util.c</a>
+<li>mm_uncomment()
+: <a class="el" href="group__util.html#g49c016ff4cfd02f1b019c4dce5aac357">mm_util.c</a>
+<li>mm_unquote()
+: <a class="el" href="group__util.html#gf0f89a29a634f6f1f833abb1e214a6b1">mm_util.c</a>
+</ul>
+<h3><a class="anchor" name="index_x">- x -</a></h3><ul>
+<li>xmalloc()
+: <a class="el" href="group__util.html#g2ff4ef58da7e543466e75f20f2a2d8b7">mm_util.c</a>
+<li>xrealloc()
+: <a class="el" href="group__util.html#ge14637b4672461f1f0bee822406d68dc">mm_util.c</a>
+<li>xstrsep()
+: <a class="el" href="group__util.html#g3ae25483c8a42f6562f2a916a511228f">mm_util.c</a>
+</ul>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:09 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/globals_func.html b/main/minimime/mm-docs/html/globals_func.html
new file mode 100644
index 000000000..7794fda65
--- /dev/null
+++ b/main/minimime/mm-docs/html/globals_func.html
@@ -0,0 +1,198 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: Data Fields</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li id="current"><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="globals.html"><span>All</span></a></li>
+ <li id="current"><a href="globals_func.html"><span>Functions</span></a></li>
+ </ul>
+</div>
+<div class="tabs">
+ <ul>
+ <li><a href="#index_m"><span>m</span></a></li>
+ <li><a href="#index_x"><span>x</span></a></li>
+ </ul>
+</div>
+
+<p>
+&nbsp;
+<p>
+<h3><a class="anchor" name="index_m">- m -</a></h3><ul>
+<li>mm_addchars()
+: <a class="el" href="group__util.html#g0747d4b4e33644263e6d73d2d8d4818b">mm_util.c</a>
+<li>mm_codec_hasdecoder()
+: <a class="el" href="group__codecs.html#g6ccb0f7a1d7c870dc3dae04f31d6ccca">mm_codecs.c</a>
+<li>mm_codec_hasencoder()
+: <a class="el" href="group__codecs.html#g50ff257b794ceaec7aedf9ae18bfcc57">mm_codecs.c</a>
+<li>mm_codec_isregistered()
+: <a class="el" href="group__codecs.html#g9e19f6343128fd7e4ec57c3d55049b55">mm_codecs.c</a>
+<li>mm_codec_register()
+: <a class="el" href="group__codecs.html#gf97a7311c909888ed9f6f14d6f1bf397">mm_codecs.c</a>
+<li>mm_codec_registerdefaultcodecs()
+: <a class="el" href="group__codecs.html#gf39e72460fb85f5ca41f6e270a68aacc">mm_codecs.c</a>
+<li>mm_codec_unregister()
+: <a class="el" href="group__codecs.html#g0c71696bc70f834386193e3c7a0e2ca4">mm_codecs.c</a>
+<li>mm_codec_unregisterall()
+: <a class="el" href="group__codecs.html#g7c9e6538f84c368be2b56a3c9ba702be">mm_codecs.c</a>
+<li>mm_content_attachparam()
+: <a class="el" href="group__contenttype.html#g080b7ed798ed497dcd635a6bab86962f">mm_contenttype.c</a>
+<li>mm_content_free()
+: <a class="el" href="group__contenttype.html#g404314481125849bce869ee4b0f647af">mm_contenttype.c</a>
+<li>mm_content_getencoding()
+: <a class="el" href="group__contenttype.html#gbff87e581cd04db16e91245e9e9de67d">mm_contenttype.c</a>
+<li>mm_content_getmaintype()
+: <a class="el" href="group__contenttype.html#gb213081017abf6bc7e601c6bf4214924">mm_contenttype.c</a>
+<li>mm_content_getparambyname()
+: <a class="el" href="group__contenttype.html#g451441ee557ab5ef29477f3dc8330bf6">mm_contenttype.c</a>
+<li>mm_content_getsubtype()
+: <a class="el" href="group__contenttype.html#g97f77ef40c14cd0fb397bad358ee5d49">mm_contenttype.c</a>
+<li>mm_content_iscomposite()
+: <a class="el" href="group__contenttype.html#ga7fa479f27e73dea57257421d8fc9fc5">mm_contenttype.c</a>
+<li>mm_content_isvalidencoding()
+: <a class="el" href="group__contenttype.html#gb724b5979182fa272fe4fd1b72b395d5">mm_contenttype.c</a>
+<li>mm_content_new()
+: <a class="el" href="group__contenttype.html#g3880ac74a20b4a9f610a4159568e1801">mm_contenttype.c</a>
+<li>mm_content_paramstostring()
+: <a class="el" href="group__contenttype.html#g792e7d33fbb30e0123408bcef9d3204c">mm_contenttype.c</a>
+<li>mm_content_setencoding()
+: <a class="el" href="group__contenttype.html#gea945e48ac5cca846715543634b9afe4">mm_contenttype.c</a>
+<li>mm_content_setmaintype()
+: <a class="el" href="group__contenttype.html#g7bab273d117c6c0cacad20361d8fb1c8">mm_contenttype.c</a>
+<li>mm_content_setsubtype()
+: <a class="el" href="group__contenttype.html#g14b0738410d566ad2312405946f22212">mm_contenttype.c</a>
+<li>mm_content_tostring()
+: <a class="el" href="group__contenttype.html#g18a99c95e35a76f13a77a83c4231e738">mm_contenttype.c</a>
+<li>mm_context_attachpart()
+: <a class="el" href="group__context.html#gec3ca486a61b392ff68774242086768e">mm_context.c</a>
+<li>mm_context_attachpart_after()
+: <a class="el" href="group__context.html#g73a3dd187053aeabca4836dc28a6c468">mm_context.c</a>
+<li>mm_context_countparts()
+: <a class="el" href="group__context.html#gf5bb032ad1c481d31d7b1b0710939712">mm_context.c</a>
+<li>mm_context_deletepart()
+: <a class="el" href="group__context.html#g53d20c33a401539ef1ffa45f3dddb983">mm_context.c</a>
+<li>mm_context_flatten()
+: <a class="el" href="group__context.html#g5288136ab923605f6508c09359ae5772">mm_context.c</a>
+<li>mm_context_free()
+: <a class="el" href="group__context.html#g76392d5269e9ef340c2f5f8336f7193b">mm_context.c</a>
+<li>mm_context_generateboundary()
+: <a class="el" href="group__context.html#g9710e485f51167099d90f0d659979068">mm_context.c</a>
+<li>mm_context_getpart()
+: <a class="el" href="group__context.html#g57fea229675f3e56a77eb40bb8193ee3">mm_context.c</a>
+<li>mm_context_haswarnings()
+: <a class="el" href="group__context.html#g8733dee7d83d3205349a7ee4ee5b2750">mm_context.c</a>
+<li>mm_context_iscomposite()
+: <a class="el" href="group__context.html#g1e73cadba4acd3ef9dd148dd0c2c3e70">mm_context.c</a>
+<li>mm_context_new()
+: <a class="el" href="group__context.html#g919fd41f85534d9c87c256857faa2610">mm_context.c</a>
+<li>mm_context_setpreamble()
+: <a class="el" href="group__context.html#gc0e7cc297516618d4773830a1988fc8d">mm_context.c</a>
+<li>mm_envelope_getheaders()
+: <a class="el" href="group__envelope.html#g38f1164142cedfc3253b068a81f85563">mm_envelope.c</a>
+<li>mm_envelope_getrecipients()
+: <a class="el" href="group__envelope.html#ge63da17c56867ca2406a4eaf73230baf">mm_envelope.c</a>
+<li>mm_envelope_setheader()
+: <a class="el" href="group__envelope.html#gb2c43c1645e42ae0860c902ce1dda788">mm_envelope.c</a>
+<li>mm_error_init()
+: <a class="el" href="group__error.html#g69de7c9bee1d535593a55807590de543">mm_error.c</a>
+<li>mm_error_setmsg()
+: <a class="el" href="group__error.html#g92006c97728639d8f32f5bc4c6e2a47f">mm_error.c</a>
+<li>mm_error_string()
+: <a class="el" href="group__error.html#g8654857a3ac349b87d798902912371a3">mm_error.c</a>
+<li>mm_mimeheader_free()
+: <a class="el" href="mm__header_8c.html#61e3e62728f720ac381196ec59303064">mm_header.c</a>
+<li>mm_mimeheader_generate()
+: <a class="el" href="mm__header_8c.html#07a7f7dcebc91aa86f5478e1d84341a1">mm_header.c</a>
+<li>mm_mimeheader_new()
+: <a class="el" href="mm__header_8c.html#2f2c5f2f640111caf3096ed46b5986a4">mm_header.c</a>
+<li>mm_mimepart_attachcontenttype()
+: <a class="el" href="group__mimepart.html#g01822bc93b4741af75b5379384354e37">mm_mimepart.c</a>
+<li>mm_mimepart_attachheader()
+: <a class="el" href="group__mimepart.html#g46a674ff6b9873c0c45fa4eb5d94fd62">mm_mimepart.c</a>
+<li>mm_mimepart_countheaderbyname()
+: <a class="el" href="group__mimepart.html#gf89da502ac54306994bdb452448a8026">mm_mimepart.c</a>
+<li>mm_mimepart_countheaders()
+: <a class="el" href="group__mimepart.html#g44c78abfb0535312bcb427a2cd220026">mm_mimepart.c</a>
+<li>mm_mimepart_decode()
+: <a class="el" href="group__mimepart.html#g4551bf4460e5d165bbcd9f32d4f625de">mm_mimepart.c</a>
+<li>mm_mimepart_flatten()
+: <a class="el" href="group__mimepart.html#gf19d3ace5ae174b3eaa35f9ddbe6e216">mm_mimepart.c</a>
+<li>mm_mimepart_free()
+: <a class="el" href="group__mimepart.html#gbf47790a0bb96b22bc5e236bc40cb32e">mm_mimepart.c</a>
+<li>mm_mimepart_fromfile()
+: <a class="el" href="group__mimepart.html#ged8112012a337371ae8093adb1ab6d27">mm_mimepart.c</a>
+<li>mm_mimepart_getbody()
+: <a class="el" href="group__mimepart.html#g52dc9f27a2801e4f6abb1effd2ed838d">mm_mimepart.c</a>
+<li>mm_mimepart_getheaderbyname()
+: <a class="el" href="group__mimepart.html#ga3ca298eaa82f4ef3ea731511ac84e53">mm_mimepart.c</a>
+<li>mm_mimepart_getheadervalue()
+: <a class="el" href="group__mimepart.html#g779f11f7a6a54f83763b5ef6ff87e48f">mm_mimepart.c</a>
+<li>mm_mimepart_getlength()
+: <a class="el" href="group__mimepart.html#gf8ccae1737dc4b9b91958fe448da677f">mm_mimepart.c</a>
+<li>mm_mimepart_gettype()
+: <a class="el" href="group__mimepart.html#g210e2ceee56f8349f6778006da87d080">mm_mimepart.c</a>
+<li>mm_mimepart_headers_next()
+: <a class="el" href="group__mimepart.html#g8e9064736efdeebf4b257cc45f8a6adf">mm_mimepart.c</a>
+<li>mm_mimepart_headers_start()
+: <a class="el" href="group__mimepart.html#g4440bdcfddf88eb642b6a834a0557176">mm_mimepart.c</a>
+<li>mm_mimepart_new()
+: <a class="el" href="group__mimepart.html#g417e5dd361e30cddb91e1d9a5e30b223">mm_mimepart.c</a>
+<li>mm_mimepart_setbody()
+: <a class="el" href="group__mimepart.html#gd1def098c00edc546b03e98e9ff8b27a">mm_mimepart.c</a>
+<li>mm_mimepart_setdefaultcontenttype()
+: <a class="el" href="group__mimepart.html#g164bb39a266559574c252f11266809ff">mm_mimepart.c</a>
+<li>mm_mimeutil_gendate()
+: <a class="el" href="mm__mimeutil_8c.html#a7b7f63b42dfa7a7f907b615aa4cd057">mm_mimeutil.c</a>
+<li>mm_param_free()
+: <a class="el" href="group__param.html#g46339038e995799e6a3e37512f442fc9">mm_param.c</a>
+<li>mm_param_generate()
+: <a class="el" href="group__param.html#gd3970def45b8bede334f4b89a41dec15">mm_param.c</a>
+<li>mm_param_getname()
+: <a class="el" href="group__param.html#g0e0ddccf47a2b1e0ad5bcc52c7b39753">mm_param.c</a>
+<li>mm_param_getvalue()
+: <a class="el" href="group__param.html#g3c6f8cddd409de3000c31584e140561e">mm_param.c</a>
+<li>mm_param_new()
+: <a class="el" href="group__param.html#gd3ac756551bf5a29a07d5992bfdbde09">mm_param.c</a>
+<li>mm_param_setname()
+: <a class="el" href="group__param.html#g2a266c63c7e89cf829b2af8e995e55e8">mm_param.c</a>
+<li>mm_param_setvalue()
+: <a class="el" href="group__param.html#gca3e636ab5700462eb32ca5bc19e4cc6">mm_param.c</a>
+<li>mm_parse_file()
+: <a class="el" href="mm__parse_8c.html#cc9f623682b05f330c46e72e4e9d66cc">mm_parse.c</a>
+<li>mm_parse_mem()
+: <a class="el" href="mm__parse_8c.html#58c960b6017f13d4e4ec5f09b3c38495">mm_parse.c</a>
+<li>mm_stripchars()
+: <a class="el" href="group__util.html#gf62be7dd21e545f8db72f3c9e3b6a3c3">mm_util.c</a>
+<li>mm_uncomment()
+: <a class="el" href="group__util.html#g49c016ff4cfd02f1b019c4dce5aac357">mm_util.c</a>
+<li>mm_unquote()
+: <a class="el" href="group__util.html#gf0f89a29a634f6f1f833abb1e214a6b1">mm_util.c</a>
+</ul>
+<h3><a class="anchor" name="index_x">- x -</a></h3><ul>
+<li>xmalloc()
+: <a class="el" href="group__util.html#g2ff4ef58da7e543466e75f20f2a2d8b7">mm_util.c</a>
+<li>xrealloc()
+: <a class="el" href="group__util.html#ge14637b4672461f1f0bee822406d68dc">mm_util.c</a>
+<li>xstrsep()
+: <a class="el" href="group__util.html#g3ae25483c8a42f6562f2a916a511228f">mm_util.c</a>
+</ul>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:09 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/group__codecs.html b/main/minimime/mm-docs/html/group__codecs.html
new file mode 100644
index 000000000..a803cd67c
--- /dev/null
+++ b/main/minimime/mm-docs/html/group__codecs.html
@@ -0,0 +1,243 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: Manipulating MiniMIME codecs</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<h1>Manipulating MiniMIME codecs</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Codec manipulation</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__codecs.html#g6ccb0f7a1d7c870dc3dae04f31d6ccca">mm_codec_hasdecoder</a> (const char *encoding)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__codecs.html#g50ff257b794ceaec7aedf9ae18bfcc57">mm_codec_hasencoder</a> (const char *encoding)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__codecs.html#g9e19f6343128fd7e4ec57c3d55049b55">mm_codec_isregistered</a> (const char *encoding)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__codecs.html#gf97a7311c909888ed9f6f14d6f1bf397">mm_codec_register</a> (const char *encoding, char *(*encoder)(char *data, u_int32_t i), char *(*decoder)(char *data))</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__codecs.html#g0c71696bc70f834386193e3c7a0e2ca4">mm_codec_unregister</a> (const char *encoding)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__codecs.html#g7c9e6538f84c368be2b56a3c9ba702be">mm_codec_unregisterall</a> (void)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__codecs.html#gf39e72460fb85f5ca41f6e270a68aacc">mm_codec_registerdefaultcodecs</a> (void)</td></tr>
+
+</table>
+<hr><h2>Function Documentation</h2>
+<a class="anchor" name="g6ccb0f7a1d7c870dc3dae04f31d6ccca"></a><!-- doxytag: member="mm_codecs.c::mm_codec_hasdecoder" ref="g6ccb0f7a1d7c870dc3dae04f31d6ccca" args="(const char *encoding)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_codec_hasdecoder </td>
+ <td>(</td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>encoding</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Looks up whether a context has an decoder installed for a given encoding<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>encoding</em>&nbsp;</td><td>The encoding specifier to look up </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>1 if a decoder is installed or 0 if not </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g50ff257b794ceaec7aedf9ae18bfcc57"></a><!-- doxytag: member="mm_codecs.c::mm_codec_hasencoder" ref="g50ff257b794ceaec7aedf9ae18bfcc57" args="(const char *encoding)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_codec_hasencoder </td>
+ <td>(</td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>encoding</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Looks up whether a context has an encoder installed for a given encoding<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ctx</em>&nbsp;</td><td>A valid MIME context </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>encoding</em>&nbsp;</td><td>The encoding specifier to look up </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>1 if an encoder is installed or 0 if not </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g9e19f6343128fd7e4ec57c3d55049b55"></a><!-- doxytag: member="mm_codecs.c::mm_codec_isregistered" ref="g9e19f6343128fd7e4ec57c3d55049b55" args="(const char *encoding)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_codec_isregistered </td>
+ <td>(</td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>encoding</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Looks up whether a codec for a given encoding is installed to a context<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>encoding</em>&nbsp;</td><td>The encoding specifier to look up </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>1 if a codec was found or 0 if not </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gf97a7311c909888ed9f6f14d6f1bf397"></a><!-- doxytag: member="mm_codecs.c::mm_codec_register" ref="gf97a7311c909888ed9f6f14d6f1bf397" args="(const char *encoding, char *(*encoder)(char *data, u_int32_t i), char *(*decoder)(char *data))" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_codec_register </td>
+ <td>(</td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>encoding</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">char *(*)(char *data, u_int32_t i)&nbsp;</td>
+ <td class="paramname"> <em>encoder</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">char *(*)(char *data)&nbsp;</td>
+ <td class="paramname"> <em>decoder</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Registers a codec with the MiniMIME library<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>encoding</em>&nbsp;</td><td>The encoding specifier for which to register the codec </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>encoder</em>&nbsp;</td><td>The encoder function for this encoding </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>decoder</em>&nbsp;</td><td>The decoder function for this encoding </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>1 if successfull or 0 if not</dd></dl>
+This function registers a codec for a given MiniMIME context. The codec may provide an decoder, an encoder or both (but not none). If there is a codec already installed for this encoding, the function will puke.
+</div>
+</div><p>
+<a class="anchor" name="gf39e72460fb85f5ca41f6e270a68aacc"></a><!-- doxytag: member="mm_codecs.c::mm_codec_registerdefaultcodecs" ref="gf39e72460fb85f5ca41f6e270a68aacc" args="(void)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void mm_codec_registerdefaultcodecs </td>
+ <td>(</td>
+ <td class="paramtype">void&nbsp;</td>
+ <td class="paramname"> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Registers the default codecs to a MiniMIME context<p>
+This functions registers the codecs for the following encodings to a MiniMIME context:<p>
+<ul>
+<li>Base64</li><li>(TODO:) Quoted-Printable </li></ul>
+
+</div>
+</div><p>
+<a class="anchor" name="g0c71696bc70f834386193e3c7a0e2ca4"></a><!-- doxytag: member="mm_codecs.c::mm_codec_unregister" ref="g0c71696bc70f834386193e3c7a0e2ca4" args="(const char *encoding)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_codec_unregister </td>
+ <td>(</td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>encoding</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Unregisters a MiniMIME codec<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>encoding</em>&nbsp;</td><td>The encoding specifier which to unregister </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 if unregistered successfully, or -1 if there was no such codec </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g7c9e6538f84c368be2b56a3c9ba702be"></a><!-- doxytag: member="mm_codecs.c::mm_codec_unregisterall" ref="g7c9e6538f84c368be2b56a3c9ba702be" args="(void)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_codec_unregisterall </td>
+ <td>(</td>
+ <td class="paramtype">void&nbsp;</td>
+ <td class="paramname"> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Unregisters all codecs within a context<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ctx</em>&nbsp;</td><td>A valid MiniMIME context </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 if all codecs were unregistered successfully or -1 if an error occured. </dd></dl>
+<dl class="note" compact><dt><b>Note:</b></dt><dd>Foobar </dd></dl>
+
+</div>
+</div><p>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/group__contenttype.html b/main/minimime/mm-docs/html/group__contenttype.html
new file mode 100644
index 000000000..973f98a8d
--- /dev/null
+++ b/main/minimime/mm-docs/html/group__contenttype.html
@@ -0,0 +1,516 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: Accessing and manipulating Content-Type objects</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<h1>Accessing and manipulating Content-Type objects</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions for manipulating Content-Type objects</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_content *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#g3880ac74a20b4a9f610a4159568e1801">mm_content_new</a> (void)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#g404314481125849bce869ee4b0f647af">mm_content_free</a> (struct mm_content *ct)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#g080b7ed798ed497dcd635a6bab86962f">mm_content_attachparam</a> (struct mm_content *ct, struct mm_param *param)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#g451441ee557ab5ef29477f3dc8330bf6">mm_content_getparambyname</a> (struct mm_content *ct, const char *name)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g1ba63e679d2b49aceb6cfec8a6752581"></a><!-- doxytag: member="contenttype::mm_content_getparamobjbyname" ref="g1ba63e679d2b49aceb6cfec8a6752581" args="(struct mm_content *ct, const char *name)" -->
+mm_param *&nbsp;</td><td class="memItemRight" valign="bottom"><b>mm_content_getparamobjbyname</b> (struct mm_content *ct, const char *name)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#g7bab273d117c6c0cacad20361d8fb1c8">mm_content_setmaintype</a> (struct mm_content *ct, char *value, int copy)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#gb213081017abf6bc7e601c6bf4214924">mm_content_getmaintype</a> (struct mm_content *ct)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#g97f77ef40c14cd0fb397bad358ee5d49">mm_content_getsubtype</a> (struct mm_content *ct)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="ga6d8453eb35bd695c4944e53b7040b65"></a><!-- doxytag: member="contenttype::mm_content_gettype" ref="ga6d8453eb35bd695c4944e53b7040b65" args="(struct mm_content *ct)" -->
+char *&nbsp;</td><td class="memItemRight" valign="bottom"><b>mm_content_gettype</b> (struct mm_content *ct)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#g14b0738410d566ad2312405946f22212">mm_content_setsubtype</a> (struct mm_content *ct, char *value, int copy)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g878686678ea2ba97aa8edb1206a564d8"></a><!-- doxytag: member="contenttype::mm_content_settype" ref="g878686678ea2ba97aa8edb1206a564d8" args="(struct mm_content *ct, const char *fmt,...)" -->
+int&nbsp;</td><td class="memItemRight" valign="bottom"><b>mm_content_settype</b> (struct mm_content *ct, const char *fmt,...)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#ga7fa479f27e73dea57257421d8fc9fc5">mm_content_iscomposite</a> (struct mm_content *ct)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#gb724b5979182fa272fe4fd1b72b395d5">mm_content_isvalidencoding</a> (const char *encoding)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#gea945e48ac5cca846715543634b9afe4">mm_content_setencoding</a> (struct mm_content *ct, const char *encoding)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#gbff87e581cd04db16e91245e9e9de67d">mm_content_getencoding</a> (struct mm_content *ct, const char *encoding)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#g792e7d33fbb30e0123408bcef9d3204c">mm_content_paramstostring</a> (struct mm_content *ct)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#g18a99c95e35a76f13a77a83c4231e738">mm_content_tostring</a> (struct mm_content *ct)</td></tr>
+
+<tr><td colspan="2"><br><h2>Variables</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g6c458a8611981109bf0519b5ae21e12e"></a><!-- doxytag: member="contenttype::type" ref="g6c458a8611981109bf0519b5ae21e12e" args="" -->
+int&nbsp;</td><td class="memItemRight" valign="bottom"><b>mm_encoding_mappings::type</b></td></tr>
+
+</table>
+<hr><h2>Function Documentation</h2>
+<a class="anchor" name="g080b7ed798ed497dcd635a6bab86962f"></a><!-- doxytag: member="mm_contenttype.c::mm_content_attachparam" ref="g080b7ed798ed497dcd635a6bab86962f" args="(struct mm_content *ct, struct mm_param *param)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_content_attachparam </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_content *&nbsp;</td>
+ <td class="paramname"> <em>ct</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">struct mm_param *&nbsp;</td>
+ <td class="paramname"> <em>param</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Attaches a parameter to a Content-Type object<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ct</em>&nbsp;</td><td>The target Content-Type object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>param</em>&nbsp;</td><td>The Content-Type parameter which to attach </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 on success and -1 on failure </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g404314481125849bce869ee4b0f647af"></a><!-- doxytag: member="mm_contenttype.c::mm_content_free" ref="g404314481125849bce869ee4b0f647af" args="(struct mm_content *ct)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void mm_content_free </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_content *&nbsp;</td>
+ <td class="paramname"> <em>ct</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Releases all memory associated with an Content-Type object<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ct</em>&nbsp;</td><td>A Content-Type object </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>Nothing </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gbff87e581cd04db16e91245e9e9de67d"></a><!-- doxytag: member="mm_contenttype.c::mm_content_getencoding" ref="gbff87e581cd04db16e91245e9e9de67d" args="(struct mm_content *ct, const char *encoding)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_content_getencoding </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_content *&nbsp;</td>
+ <td class="paramname"> <em>ct</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>encoding</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Gets the numerical ID of a content encoding identifier<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ct</em>&nbsp;</td><td>A valid Content Type object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>encoding</em>&nbsp;</td><td>A string representing the content encoding identifier </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>The numerical ID of the content encoding </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gb213081017abf6bc7e601c6bf4214924"></a><!-- doxytag: member="mm_contenttype.c::mm_content_getmaintype" ref="gb213081017abf6bc7e601c6bf4214924" args="(struct mm_content *ct)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">char* mm_content_getmaintype </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_content *&nbsp;</td>
+ <td class="paramname"> <em>ct</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Retrieves the main MIME type stored in a Content-Type object<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ct</em>&nbsp;</td><td>A valid Content-Type object </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A pointer to the string representing the main type </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g451441ee557ab5ef29477f3dc8330bf6"></a><!-- doxytag: member="mm_contenttype.c::mm_content_getparambyname" ref="g451441ee557ab5ef29477f3dc8330bf6" args="(struct mm_content *ct, const char *name)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">char* mm_content_getparambyname </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_content *&nbsp;</td>
+ <td class="paramname"> <em>ct</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>name</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Gets a parameter value from a Content-Type object.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ct</em>&nbsp;</td><td>the Content-Type object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>name</em>&nbsp;</td><td>the name of the parameter to retrieve </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>The value of the parameter on success or a NULL pointer on failure </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g97f77ef40c14cd0fb397bad358ee5d49"></a><!-- doxytag: member="mm_contenttype.c::mm_content_getsubtype" ref="g97f77ef40c14cd0fb397bad358ee5d49" args="(struct mm_content *ct)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">char* mm_content_getsubtype </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_content *&nbsp;</td>
+ <td class="paramname"> <em>ct</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Retrieves the sub MIME type stored in a Content-Type object<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ct</em>&nbsp;</td><td>A valid Content-Type object </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A pointer to the string holding the current sub MIME type </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ga7fa479f27e73dea57257421d8fc9fc5"></a><!-- doxytag: member="mm_contenttype.c::mm_content_iscomposite" ref="ga7fa479f27e73dea57257421d8fc9fc5" args="(struct mm_content *ct)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_content_iscomposite </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_content *&nbsp;</td>
+ <td class="paramname"> <em>ct</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Checks whether the Content-Type represents a composite message or not<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ct</em>&nbsp;</td><td>A valid Content-Type object </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>1 if the Content-Type object represents a composite message or 0 if not. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gb724b5979182fa272fe4fd1b72b395d5"></a><!-- doxytag: member="mm_contenttype.c::mm_content_isvalidencoding" ref="gb724b5979182fa272fe4fd1b72b395d5" args="(const char *encoding)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_content_isvalidencoding </td>
+ <td>(</td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>encoding</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Verifies whether a string represents a valid encoding or not.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>encoding</em>&nbsp;</td><td>The string to verify </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>1 if the encoding string is valid or 0 if not </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g3880ac74a20b4a9f610a4159568e1801"></a><!-- doxytag: member="mm_contenttype.c::mm_content_new" ref="g3880ac74a20b4a9f610a4159568e1801" args="(void)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">struct mm_content* mm_content_new </td>
+ <td>(</td>
+ <td class="paramtype">void&nbsp;</td>
+ <td class="paramname"> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Creates a new object to hold a Content-Type representation. The allocated memory must later be freed using <a class="el" href="group__contenttype.html#g404314481125849bce869ee4b0f647af">mm_content_free()</a><p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>An object representing a MIME Content-Type </dd></dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__contenttype.html#g404314481125849bce869ee4b0f647af">mm_content_free</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g792e7d33fbb30e0123408bcef9d3204c"></a><!-- doxytag: member="mm_contenttype.c::mm_content_paramstostring" ref="g792e7d33fbb30e0123408bcef9d3204c" args="(struct mm_content *ct)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">char* mm_content_paramstostring </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_content *&nbsp;</td>
+ <td class="paramname"> <em>ct</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Constructs a MIME conform string of Content-Type parameters.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ct</em>&nbsp;</td><td>A valid Content Type object </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A pointer to a string representing the Content-Type parameters in MIME terminology, or NULL if either the Content-Type object is invalid, has no parameters or no memory could be allocated.</dd></dl>
+This function constructs a MIME conform string including all the parameters associated with the given Content-Type object. It should NOT be used if you need an opaque copy of the current MIME part (e.g. for PGP purposes).
+</div>
+</div><p>
+<a class="anchor" name="gea945e48ac5cca846715543634b9afe4"></a><!-- doxytag: member="mm_contenttype.c::mm_content_setencoding" ref="gea945e48ac5cca846715543634b9afe4" args="(struct mm_content *ct, const char *encoding)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_content_setencoding </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_content *&nbsp;</td>
+ <td class="paramname"> <em>ct</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>encoding</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Set the encoding of a MIME entitity according to a mapping table<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ct</em>&nbsp;</td><td>A valid content type object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>encoding</em>&nbsp;</td><td>A string representing the content encoding </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 if successfull or -1 if not (i.e. unknown content encoding) </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g7bab273d117c6c0cacad20361d8fb1c8"></a><!-- doxytag: member="mm_contenttype.c::mm_content_setmaintype" ref="g7bab273d117c6c0cacad20361d8fb1c8" args="(struct mm_content *ct, char *value, int copy)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_content_setmaintype </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_content *&nbsp;</td>
+ <td class="paramname"> <em>ct</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">char *&nbsp;</td>
+ <td class="paramname"> <em>value</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>copy</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Sets the MIME main type for a MIME Content-Type object<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ct</em>&nbsp;</td><td>The MIME Content-Type object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>value</em>&nbsp;</td><td>The value which to set the main type to </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>copy</em>&nbsp;</td><td>Whether to make a copy of the value (original value must be freed afterwards to prevent memory leaks). </td></tr>
+ </table>
+</dl>
+
+<p>
+<dl compact><dt><b><a class="el" href="bug.html#_bug000001">Bug:</a></b></dt><dd>The xfree() call could lead to undesirable results. Do we really need it? </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g14b0738410d566ad2312405946f22212"></a><!-- doxytag: member="mm_contenttype.c::mm_content_setsubtype" ref="g14b0738410d566ad2312405946f22212" args="(struct mm_content *ct, char *value, int copy)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_content_setsubtype </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_content *&nbsp;</td>
+ <td class="paramname"> <em>ct</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">char *&nbsp;</td>
+ <td class="paramname"> <em>value</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>copy</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Sets the MIME sub type for a MIME Content-Type object<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ct</em>&nbsp;</td><td>The MIME Content-Type object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>value</em>&nbsp;</td><td>The value which to set the sub type to </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>copy</em>&nbsp;</td><td>Whether to make a copy of the value (original value must be freed afterwards to prevent memory leaks). </td></tr>
+ </table>
+</dl>
+
+<p>
+<dl compact><dt><b><a class="el" href="bug.html#_bug000002">Bug:</a></b></dt><dd>The xfree() call could lead to undesirable results. Do we really need it? </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g18a99c95e35a76f13a77a83c4231e738"></a><!-- doxytag: member="mm_contenttype.c::mm_content_tostring" ref="g18a99c95e35a76f13a77a83c4231e738" args="(struct mm_content *ct)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">char* mm_content_tostring </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_content *&nbsp;</td>
+ <td class="paramname"> <em>ct</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Creates a Content-Type header according to the object given<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ct</em>&nbsp;</td><td>A valid Content-Type object </td></tr>
+ </table>
+</dl>
+
+</div>
+</div><p>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/group__context.html b/main/minimime/mm-docs/html/group__context.html
new file mode 100644
index 000000000..832151ea1
--- /dev/null
+++ b/main/minimime/mm-docs/html/group__context.html
@@ -0,0 +1,465 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: Accessing and manipulating MIME contexts</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<h1>Accessing and manipulating MIME contexts</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Manipulating MiniMIME contexts</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">MM_CTX *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#g919fd41f85534d9c87c256857faa2610">mm_context_new</a> (void)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#g76392d5269e9ef340c2f5f8336f7193b">mm_context_free</a> (MM_CTX *ctx)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#gec3ca486a61b392ff68774242086768e">mm_context_attachpart</a> (MM_CTX *ctx, struct mm_mimepart *part)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#g73a3dd187053aeabca4836dc28a6c468">mm_context_attachpart_after</a> (MM_CTX *ctx, struct mm_mimepart *part, int pos)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#g53d20c33a401539ef1ffa45f3dddb983">mm_context_deletepart</a> (MM_CTX *ctx, int which, int freemem)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#gf5bb032ad1c481d31d7b1b0710939712">mm_context_countparts</a> (MM_CTX *ctx)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_mimepart *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#g57fea229675f3e56a77eb40bb8193ee3">mm_context_getpart</a> (MM_CTX *ctx, int which)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#g1e73cadba4acd3ef9dd148dd0c2c3e70">mm_context_iscomposite</a> (MM_CTX *ctx)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#g8733dee7d83d3205349a7ee4ee5b2750">mm_context_haswarnings</a> (MM_CTX *ctx)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#g9710e485f51167099d90f0d659979068">mm_context_generateboundary</a> (MM_CTX *ctx)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#gc0e7cc297516618d4773830a1988fc8d">mm_context_setpreamble</a> (MM_CTX *ctx, char *preamble)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g1ebbdd51106ccdee77ca421f9692bde7"></a><!-- doxytag: member="context::mm_context_getpreamble" ref="g1ebbdd51106ccdee77ca421f9692bde7" args="(MM_CTX *ctx)" -->
+char *&nbsp;</td><td class="memItemRight" valign="bottom"><b>mm_context_getpreamble</b> (MM_CTX *ctx)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#g5288136ab923605f6508c09359ae5772">mm_context_flatten</a> (MM_CTX *ctx, char **flat, size_t *length, int flags)</td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Each message in MiniMIME is represented by a so called ``context''. A context holds all necessary information given about a MIME message, such as the envelope, all MIME parts etc. <hr><h2>Function Documentation</h2>
+<a class="anchor" name="gec3ca486a61b392ff68774242086768e"></a><!-- doxytag: member="mm_context.c::mm_context_attachpart" ref="gec3ca486a61b392ff68774242086768e" args="(MM_CTX *ctx, struct mm_mimepart *part)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_context_attachpart </td>
+ <td>(</td>
+ <td class="paramtype">MM_CTX *&nbsp;</td>
+ <td class="paramname"> <em>ctx</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">struct mm_mimepart *&nbsp;</td>
+ <td class="paramname"> <em>part</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Attaches a MIME part object to a MiniMIME context.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ctx</em>&nbsp;</td><td>the MiniMIME context </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>part</em>&nbsp;</td><td>the MIME part object to attach </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 on success or -1 on failure. Sets mm_errno on failure.</dd></dl>
+This function attaches a MIME part to a context, appending it to the end of the message.<p>
+The MIME part should be initialized before attaching it using <a class="el" href="group__mimepart.html#g417e5dd361e30cddb91e1d9a5e30b223">mm_mimepart_new()</a>.
+</div>
+</div><p>
+<a class="anchor" name="g73a3dd187053aeabca4836dc28a6c468"></a><!-- doxytag: member="mm_context.c::mm_context_attachpart_after" ref="g73a3dd187053aeabca4836dc28a6c468" args="(MM_CTX *ctx, struct mm_mimepart *part, int pos)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_context_attachpart_after </td>
+ <td>(</td>
+ <td class="paramtype">MM_CTX *&nbsp;</td>
+ <td class="paramname"> <em>ctx</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">struct mm_mimepart *&nbsp;</td>
+ <td class="paramname"> <em>part</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>pos</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Attaches a MIME part object to a MiniMIME context at a given position<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ctx</em>&nbsp;</td><td>A valid MiniMIME context </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>part</em>&nbsp;</td><td>The MIME part object to attach </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>pos</em>&nbsp;</td><td>After which part to attach the object </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 on success or -1 if the given position is invalid </dd></dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__context.html#gec3ca486a61b392ff68774242086768e">mm_context_attachpart</a></dd></dl>
+This function attaches a MIME part object after a given position in the specified context. If the position is invalid (out of range), the part will not get attached to the message and the function returns -1. If the index was in range, the MIME part will get attached after the MIME part at the given position, moving any possible following MIME parts one down the hierarchy.
+</div>
+</div><p>
+<a class="anchor" name="gf5bb032ad1c481d31d7b1b0710939712"></a><!-- doxytag: member="mm_context.c::mm_context_countparts" ref="gf5bb032ad1c481d31d7b1b0710939712" args="(MM_CTX *ctx)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_context_countparts </td>
+ <td>(</td>
+ <td class="paramtype">MM_CTX *&nbsp;</td>
+ <td class="paramname"> <em>ctx</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Counts the number of attached MIME part objects in a given MiniMIME context<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ctx</em>&nbsp;</td><td>The MiniMIME context </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>The number of attached MIME part objects </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g53d20c33a401539ef1ffa45f3dddb983"></a><!-- doxytag: member="mm_context.c::mm_context_deletepart" ref="g53d20c33a401539ef1ffa45f3dddb983" args="(MM_CTX *ctx, int which, int freemem)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_context_deletepart </td>
+ <td>(</td>
+ <td class="paramtype">MM_CTX *&nbsp;</td>
+ <td class="paramname"> <em>ctx</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>which</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>freemem</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Deletes a MIME part object from a MiniMIME context<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ctx</em>&nbsp;</td><td>A valid MiniMIME context object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>which</em>&nbsp;</td><td>The number of the MIME part object to delete </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>freemem</em>&nbsp;</td><td>Whether to free the memory associated with the MIME part object </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 on success or -1 on failure. Sets mm_errno on failure.</dd></dl>
+This function deletes a MIME part from a given context. The MIME part to delete is specified as numerical index by the parameter ``which''. If the parameter ``freemem'' is set to anything greater than 0, the memory that is associated will be free'd by using <a class="el" href="group__mimepart.html#gbf47790a0bb96b22bc5e236bc40cb32e">mm_mimepart_free()</a>, otherwise the memory is left untouched (if you still have a pointer to the MIME part around).
+</div>
+</div><p>
+<a class="anchor" name="g5288136ab923605f6508c09359ae5772"></a><!-- doxytag: member="mm_context.c::mm_context_flatten" ref="g5288136ab923605f6508c09359ae5772" args="(MM_CTX *ctx, char **flat, size_t *length, int flags)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_context_flatten </td>
+ <td>(</td>
+ <td class="paramtype">MM_CTX *&nbsp;</td>
+ <td class="paramname"> <em>ctx</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">char **&nbsp;</td>
+ <td class="paramname"> <em>flat</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t *&nbsp;</td>
+ <td class="paramname"> <em>length</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>flags</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Creates an ASCII message of the specified context<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ctx</em>&nbsp;</td><td>A valid MiniMIME context object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>flat</em>&nbsp;</td><td>Where to store the message </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>flags</em>&nbsp;</td><td>Flags that affect the flattening process</td></tr>
+ </table>
+</dl>
+This function ``flattens'' a MiniMIME context, that is, it creates an ASCII represantation of the message the context contains. The flags can be a bitwise combination of the following constants:<p>
+<ul>
+<li>MM_FLATTEN_OPAQUE : use opaque MIME parts when flattening</li><li>MM_FLATTEN_SKIPENVELOPE : do not flatten the envelope part</li></ul>
+<p>
+Great care is taken to not produce invalid MIME output.
+</div>
+</div><p>
+<a class="anchor" name="g76392d5269e9ef340c2f5f8336f7193b"></a><!-- doxytag: member="mm_context.c::mm_context_free" ref="g76392d5269e9ef340c2f5f8336f7193b" args="(MM_CTX *ctx)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void mm_context_free </td>
+ <td>(</td>
+ <td class="paramtype">MM_CTX *&nbsp;</td>
+ <td class="paramname"> <em>ctx</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Releases a MiniMIME context object<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ctx</em>&nbsp;</td><td>A valid MiniMIME context </td></tr>
+ </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__context.html#g919fd41f85534d9c87c256857faa2610">mm_context_new</a></dd></dl>
+This function releases all memory associated with MiniMIME context object that was created using <a class="el" href="group__context.html#g919fd41f85534d9c87c256857faa2610">mm_context_new()</a>. It will also release all memory used for the MIME parts attached, and their specific properties (such as Content-Type information, headers, and the body data).
+</div>
+</div><p>
+<a class="anchor" name="g9710e485f51167099d90f0d659979068"></a><!-- doxytag: member="mm_context.c::mm_context_generateboundary" ref="g9710e485f51167099d90f0d659979068" args="(MM_CTX *ctx)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_context_generateboundary </td>
+ <td>(</td>
+ <td class="paramtype">MM_CTX *&nbsp;</td>
+ <td class="paramname"> <em>ctx</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Generates a generic boundary string for a given context<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ctx</em>&nbsp;</td><td>A valid MiniMIME context </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 on success or -1 on failure</dd></dl>
+This function generates a default boundary string for the given context. If there is already a boundary for the context, the memory will be free()'d.
+</div>
+</div><p>
+<a class="anchor" name="g57fea229675f3e56a77eb40bb8193ee3"></a><!-- doxytag: member="mm_context.c::mm_context_getpart" ref="g57fea229675f3e56a77eb40bb8193ee3" args="(MM_CTX *ctx, int which)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">struct mm_mimepart* mm_context_getpart </td>
+ <td>(</td>
+ <td class="paramtype">MM_CTX *&nbsp;</td>
+ <td class="paramname"> <em>ctx</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>which</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Gets a specified MIME part object from a MimeMIME context<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ctx</em>&nbsp;</td><td>The MiniMIME context </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>which</em>&nbsp;</td><td>The number of the MIME part object to retrieve </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>The requested MIME part object on success or a NULL pointer if there is no such part. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g8733dee7d83d3205349a7ee4ee5b2750"></a><!-- doxytag: member="mm_context.c::mm_context_haswarnings" ref="g8733dee7d83d3205349a7ee4ee5b2750" args="(MM_CTX *ctx)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_context_haswarnings </td>
+ <td>(</td>
+ <td class="paramtype">MM_CTX *&nbsp;</td>
+ <td class="paramname"> <em>ctx</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Checks whether there are any warnings associated with a given context<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ctx</em>&nbsp;</td><td>A valid MiniMIME context </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>1 if there are warnings associated with the context, otherwise 0 </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g1e73cadba4acd3ef9dd148dd0c2c3e70"></a><!-- doxytag: member="mm_context.c::mm_context_iscomposite" ref="g1e73cadba4acd3ef9dd148dd0c2c3e70" args="(MM_CTX *ctx)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_context_iscomposite </td>
+ <td>(</td>
+ <td class="paramtype">MM_CTX *&nbsp;</td>
+ <td class="paramname"> <em>ctx</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Checks whether a given context represents a composite (multipart) message<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ctx</em>&nbsp;</td><td>A valid MiniMIME context object </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>1 if the context is a composite message or 0 if it's flat </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g919fd41f85534d9c87c256857faa2610"></a><!-- doxytag: member="mm_context.c::mm_context_new" ref="g919fd41f85534d9c87c256857faa2610" args="(void)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">MM_CTX* mm_context_new </td>
+ <td>(</td>
+ <td class="paramtype">void&nbsp;</td>
+ <td class="paramname"> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Creates a new MiniMIME context object.<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>a new MiniMIME context object </dd></dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__context.html#g76392d5269e9ef340c2f5f8336f7193b">mm_context_free</a></dd></dl>
+This function creates a new MiniMIME context, which will hold a message. The memory needed is allocated dynamically and should later be free'd using <a class="el" href="group__context.html#g76392d5269e9ef340c2f5f8336f7193b">mm_context_free()</a>.<p>
+Before a context can be created, the MiniMIME library needs to be initialized properly using mm_library_init().
+</div>
+</div><p>
+<a class="anchor" name="gc0e7cc297516618d4773830a1988fc8d"></a><!-- doxytag: member="mm_context.c::mm_context_setpreamble" ref="gc0e7cc297516618d4773830a1988fc8d" args="(MM_CTX *ctx, char *preamble)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_context_setpreamble </td>
+ <td>(</td>
+ <td class="paramtype">MM_CTX *&nbsp;</td>
+ <td class="paramname"> <em>ctx</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">char *&nbsp;</td>
+ <td class="paramname"> <em>preamble</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Sets a preamble for the given MiniMIME context<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ctx</em>&nbsp;</td><td>A valid MiniMIME context </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>preamble</em>&nbsp;</td><td>The preamble to set </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 on success or -1 on failure</dd></dl>
+This function sets the MIME preamble (the text between the end of envelope headers and the beginning of the first MIME part) for a given context object. If preamble is a NULL-pointer then the preamble will be deleted, and the currently associated memory will be free automagically.
+</div>
+</div><p>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/group__envelope.html b/main/minimime/mm-docs/html/group__envelope.html
new file mode 100644
index 000000000..9f19e734f
--- /dev/null
+++ b/main/minimime/mm-docs/html/group__envelope.html
@@ -0,0 +1,172 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: Accessing and manipulating a message&apos;s envelope</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<h1>Accessing and manipulating a message's envelope</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Accessing and manipulating a message's envelope</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__envelope.html#g38f1164142cedfc3253b068a81f85563">mm_envelope_getheaders</a> (MM_CTX *ctx, char **result, size_t *length)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__envelope.html#gb2c43c1645e42ae0860c902ce1dda788">mm_envelope_setheader</a> (MM_CTX *ctx, const char *name, const char *fmt,...)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__envelope.html#ge63da17c56867ca2406a4eaf73230baf">mm_envelope_getrecipients</a> (MM_CTX *ctx, char **result, size_t *length)</td></tr>
+
+</table>
+<hr><h2>Function Documentation</h2>
+<a class="anchor" name="g38f1164142cedfc3253b068a81f85563"></a><!-- doxytag: member="mm_envelope.c::mm_envelope_getheaders" ref="g38f1164142cedfc3253b068a81f85563" args="(MM_CTX *ctx, char **result, size_t *length)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_envelope_getheaders </td>
+ <td>(</td>
+ <td class="paramtype">MM_CTX *&nbsp;</td>
+ <td class="paramname"> <em>ctx</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">char **&nbsp;</td>
+ <td class="paramname"> <em>result</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t *&nbsp;</td>
+ <td class="paramname"> <em>length</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Gets an ASCII representation of all envelope headers<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ctx</em>&nbsp;</td><td>A valid MiniMIME context </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>result</em>&nbsp;</td><td>Where to store the resulting ASCII headers </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>length</em>&nbsp;</td><td>Where to store the length of the result </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 on success or -1 on failure. </dd></dl>
+<dl class="note" compact><dt><b>Note:</b></dt><dd>Sets mm_errno on failure</dd></dl>
+This is mainly a convinience function. It constructs an ASCII representation from all of the message's envelope headers and stores the result in headers. Memory is allocated dynamically, and the total length of the result is stored in length. This function takes care that the output is MIME conform, and folds long lines according to the MIME standard at position 78 of the string. It also nicely formats all MIME related header fields, such as the Content-Type header.<p>
+Since the memory needed to store the result is allocated dynamically, one should take care of freeing it again when it's not needed anymore. If an error occurs, *result will be set to NULL, *length will be set to zero and mm_errno will be set to a reasonable value.
+</div>
+</div><p>
+<a class="anchor" name="ge63da17c56867ca2406a4eaf73230baf"></a><!-- doxytag: member="mm_envelope.c::mm_envelope_getrecipients" ref="ge63da17c56867ca2406a4eaf73230baf" args="(MM_CTX *ctx, char **result, size_t *length)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_envelope_getrecipients </td>
+ <td>(</td>
+ <td class="paramtype">MM_CTX *&nbsp;</td>
+ <td class="paramname"> <em>ctx</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">char **&nbsp;</td>
+ <td class="paramname"> <em>result</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t *&nbsp;</td>
+ <td class="paramname"> <em>length</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Gets the list of recipients for a MIME message<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ctx</em>&nbsp;</td><td>A valid MiniMIME context </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>result</em>&nbsp;</td><td>Where to store the result </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>length</em>&nbsp;</td><td>Where to store the length of the result </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 on success or -1 on error </dd></dl>
+<dl class="note" compact><dt><b>Note:</b></dt><dd>Sets mm_errno on error</dd></dl>
+This functions gets the list of recipients for a given MIME message. It does so by concatenating the "From" and "Cc" header fields, and storing the results in recipients. The memory needed to store the result is allocated dynamically, and the total length of the result is stored in length.<p>
+One should take care to free() the result once it's not needed anymore.
+</div>
+</div><p>
+<a class="anchor" name="gb2c43c1645e42ae0860c902ce1dda788"></a><!-- doxytag: member="mm_envelope.c::mm_envelope_setheader" ref="gb2c43c1645e42ae0860c902ce1dda788" args="(MM_CTX *ctx, const char *name, const char *fmt,...)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_envelope_setheader </td>
+ <td>(</td>
+ <td class="paramtype">MM_CTX *&nbsp;</td>
+ <td class="paramname"> <em>ctx</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>name</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>fmt</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">&nbsp;</td>
+ <td class="paramname"> <em>...</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Sets a header field in the envelope<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ctx</em>&nbsp;</td><td>A valid MiniMIME context </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>name</em>&nbsp;</td><td>The name of the header field to set </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>fmt</em>&nbsp;</td><td>A format string specifying the value of the header field </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 on success or -1 on failure</dd></dl>
+This function generates a new MIME header and attaches it to the first MIME part (the envelope) found in the given context. If no part is attached already, the function will return an error. The function will store a copy of ``name'' as the header's name field, and dynamically allocate the memory needed to build the format string.
+</div>
+</div><p>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/group__error.html b/main/minimime/mm-docs/html/group__error.html
new file mode 100644
index 000000000..739ea03e8
--- /dev/null
+++ b/main/minimime/mm-docs/html/group__error.html
@@ -0,0 +1,108 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: MiniMIME error functions</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<h1>MiniMIME error functions</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__error.html#g69de7c9bee1d535593a55807590de543">mm_error_init</a> (void)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__error.html#g92006c97728639d8f32f5bc4c6e2a47f">mm_error_setmsg</a> (const char *fmt,...)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__error.html#g8654857a3ac349b87d798902912371a3">mm_error_string</a> (void)</td></tr>
+
+</table>
+<hr><h2>Function Documentation</h2>
+<a class="anchor" name="g69de7c9bee1d535593a55807590de543"></a><!-- doxytag: member="mm_error.c::mm_error_init" ref="g69de7c9bee1d535593a55807590de543" args="(void)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void mm_error_init </td>
+ <td>(</td>
+ <td class="paramtype">void&nbsp;</td>
+ <td class="paramname"> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Initializes the global error object<p>
+This function initializes the global error object mm_error. This must be done when the library is initialized, and is automatically called from mm_init_library().
+</div>
+</div><p>
+<a class="anchor" name="g92006c97728639d8f32f5bc4c6e2a47f"></a><!-- doxytag: member="mm_error.c::mm_error_setmsg" ref="g92006c97728639d8f32f5bc4c6e2a47f" args="(const char *fmt,...)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void mm_error_setmsg </td>
+ <td>(</td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>fmt</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">&nbsp;</td>
+ <td class="paramname"> <em>...</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Sets a descriptive error message<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>fmt</em>&nbsp;</td><td>The error message as format string</td></tr>
+ </table>
+</dl>
+This function is called from the various MiniMIME modules in case an error occured. Should never be called by the user.
+</div>
+</div><p>
+<a class="anchor" name="g8654857a3ac349b87d798902912371a3"></a><!-- doxytag: member="mm_error.c::mm_error_string" ref="g8654857a3ac349b87d798902912371a3" args="(void)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">char* mm_error_string </td>
+ <td>(</td>
+ <td class="paramtype">void&nbsp;</td>
+ <td class="paramname"> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Retrieves the current error message<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>The currently set error message</dd></dl>
+This function can be used to retrieve a descriptive error message for the current error, much like strerror() function of libc. When this function is called without an error being set, it returns the string "No error". The string returned does not need to be freed, since it is not dynamically allocated by the library.
+</div>
+</div><p>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/group__mimepart.html b/main/minimime/mm-docs/html/group__mimepart.html
new file mode 100644
index 000000000..84806c80d
--- /dev/null
+++ b/main/minimime/mm-docs/html/group__mimepart.html
@@ -0,0 +1,705 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: Accessing and manipulating MIME parts</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<h1>Accessing and manipulating MIME parts</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Creating and destroying MIME parts</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_mimepart *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g417e5dd361e30cddb91e1d9a5e30b223">mm_mimepart_new</a> (void)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_mimepart *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#ged8112012a337371ae8093adb1ab6d27">mm_mimepart_fromfile</a> (const char *filename)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#gbf47790a0bb96b22bc5e236bc40cb32e">mm_mimepart_free</a> (struct mm_mimepart *part)</td></tr>
+
+<tr><td colspan="2"><br><h2>Accessing the MIME part's mail header</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g46a674ff6b9873c0c45fa4eb5d94fd62">mm_mimepart_attachheader</a> (struct mm_mimepart *part, struct mm_mimeheader *header)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g44c78abfb0535312bcb427a2cd220026">mm_mimepart_countheaders</a> (struct mm_mimepart *part)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#gf89da502ac54306994bdb452448a8026">mm_mimepart_countheaderbyname</a> (struct mm_mimepart *part, const char *name)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_mimeheader *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#ga3ca298eaa82f4ef3ea731511ac84e53">mm_mimepart_getheaderbyname</a> (struct mm_mimepart *part, const char *name, int idx)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">const char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g779f11f7a6a54f83763b5ef6ff87e48f">mm_mimepart_getheadervalue</a> (struct mm_mimepart *part, const char *name, int idx)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g4440bdcfddf88eb642b6a834a0557176">mm_mimepart_headers_start</a> (struct mm_mimepart *part, struct mm_mimeheader **id)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_mimeheader *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g8e9064736efdeebf4b257cc45f8a6adf">mm_mimepart_headers_next</a> (struct mm_mimepart *part, struct mm_mimeheader **id)</td></tr>
+
+<tr><td colspan="2"><br><h2>Accessing and manipulating the MIME part's body</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g52dc9f27a2801e4f6abb1effd2ed838d">mm_mimepart_getbody</a> (struct mm_mimepart *part, int opaque)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#gd1def098c00edc546b03e98e9ff8b27a">mm_mimepart_setbody</a> (struct mm_mimepart *part, const char *data, int opaque)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">size_t&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#gf8ccae1737dc4b9b91958fe448da677f">mm_mimepart_getlength</a> (struct mm_mimepart *part)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g4551bf4460e5d165bbcd9f32d4f625de">mm_mimepart_decode</a> (struct mm_mimepart *part)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#gf19d3ace5ae174b3eaa35f9ddbe6e216">mm_mimepart_flatten</a> (struct mm_mimepart *part, char **result, size_t *length, int opaque)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g164bb39a266559574c252f11266809ff">mm_mimepart_setdefaultcontenttype</a> (struct mm_mimepart *part, int composite)</td></tr>
+
+<tr><td colspan="2"><br><h2>Accessing the MIME part's Content-Type information</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g01822bc93b4741af75b5379384354e37">mm_mimepart_attachcontenttype</a> (struct mm_mimepart *part, struct mm_content *ct)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_content *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g210e2ceee56f8349f6778006da87d080">mm_mimepart_gettype</a> (struct mm_mimepart *part)</td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+MIME parts, also called entities, represent the structure of a MIME message. ``Normal'' internet messages have only a single part, and are called ``flat'' messages. Multipart messages have more then one part, and each MIME part can have it's own subset of headers.<p>
+Provided here are functions to easily access all informations from a MIME part, including their specific headers and bodies. <hr><h2>Function Documentation</h2>
+<a class="anchor" name="g01822bc93b4741af75b5379384354e37"></a><!-- doxytag: member="mm_mimepart.c::mm_mimepart_attachcontenttype" ref="g01822bc93b4741af75b5379384354e37" args="(struct mm_mimepart *part, struct mm_content *ct)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void mm_mimepart_attachcontenttype </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_mimepart *&nbsp;</td>
+ <td class="paramname"> <em>part</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">struct mm_content *&nbsp;</td>
+ <td class="paramname"> <em>ct</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Attaches a context type object to a MIME part<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>part</em>&nbsp;</td><td>A valid MIME part object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>ct</em>&nbsp;</td><td>The content type object to attach </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>Nothing</dd></dl>
+This function attaches a Content-Type object to a MIME part. It does not care whether the Content-Type suites the actual content in the MIME part, so the programmer should take care of that.
+</div>
+</div><p>
+<a class="anchor" name="g46a674ff6b9873c0c45fa4eb5d94fd62"></a><!-- doxytag: member="mm_mimepart.c::mm_mimepart_attachheader" ref="g46a674ff6b9873c0c45fa4eb5d94fd62" args="(struct mm_mimepart *part, struct mm_mimeheader *header)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_mimepart_attachheader </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_mimepart *&nbsp;</td>
+ <td class="paramname"> <em>part</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">struct mm_mimeheader *&nbsp;</td>
+ <td class="paramname"> <em>header</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Attaches a mm_mimeheader object to a MIME part<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>part</em>&nbsp;</td><td>A valid MIME part object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>header</em>&nbsp;</td><td>A valid MIME header object </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 if successfull or -1 if the header could not be attached </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gf89da502ac54306994bdb452448a8026"></a><!-- doxytag: member="mm_mimepart.c::mm_mimepart_countheaderbyname" ref="gf89da502ac54306994bdb452448a8026" args="(struct mm_mimepart *part, const char *name)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_mimepart_countheaderbyname </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_mimepart *&nbsp;</td>
+ <td class="paramname"> <em>part</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>name</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Retrieves the number of MIME headers with a given name in a MIME part<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>part</em>&nbsp;</td><td>A valid MIME part object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>name</em>&nbsp;</td><td>The name of the MIME header which to count for </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>The number of MIME headers within the MIME part </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g44c78abfb0535312bcb427a2cd220026"></a><!-- doxytag: member="mm_mimepart.c::mm_mimepart_countheaders" ref="g44c78abfb0535312bcb427a2cd220026" args="(struct mm_mimepart *part)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_mimepart_countheaders </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_mimepart *&nbsp;</td>
+ <td class="paramname"> <em>part</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Retrieves the number of MIME headers available in a MIME part<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>part</em>&nbsp;</td><td>A valid MIME part object </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>The number of MIME headers within the MIME part </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g4551bf4460e5d165bbcd9f32d4f625de"></a><!-- doxytag: member="mm_mimepart.c::mm_mimepart_decode" ref="g4551bf4460e5d165bbcd9f32d4f625de" args="(struct mm_mimepart *part)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">char* mm_mimepart_decode </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_mimepart *&nbsp;</td>
+ <td class="paramname"> <em>part</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Decodes a MIME part according to it's encoding using MiniMIME codecs<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>A</em>&nbsp;</td><td>valid MIME part object </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 if the MIME part could be successfully decoded or -1 if not </dd></dl>
+<dl class="note" compact><dt><b>Note:</b></dt><dd>Sets mm_errno on error</dd></dl>
+This function decodes the body of a MIME part with a registered decoder according to it's Content-Transfer-Encoding header field.
+</div>
+</div><p>
+<a class="anchor" name="gf19d3ace5ae174b3eaa35f9ddbe6e216"></a><!-- doxytag: member="mm_mimepart.c::mm_mimepart_flatten" ref="gf19d3ace5ae174b3eaa35f9ddbe6e216" args="(struct mm_mimepart *part, char **result, size_t *length, int opaque)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_mimepart_flatten </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_mimepart *&nbsp;</td>
+ <td class="paramname"> <em>part</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">char **&nbsp;</td>
+ <td class="paramname"> <em>result</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t *&nbsp;</td>
+ <td class="paramname"> <em>length</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>opaque</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Creates an ASCII representation of the given MIME part<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>part</em>&nbsp;</td><td>A valid MIME part object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>result</em>&nbsp;</td><td>Where to store the result </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>length</em>&nbsp;</td><td>Where to store the length of the result </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>opaque</em>&nbsp;</td><td>Whether to use the opaque MIME part 0 on success or -1 on error. </td></tr>
+ </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__context.html#g5288136ab923605f6508c09359ae5772">mm_context_flatten</a></dd></dl>
+This function creates an ASCII representation of a given MIME part. It will dynamically allocate the memory needed and stores the result in the memory region pointed to by result. The length of the result will be stored in length. If opaque is set to 1, mm_mimepart_flatten will store an opaque version of the MIME part in result, which means no headers will be created or sanitized. This is particulary useful if the part is digitally signed by e.g. PGP, and the signature spans the header fields of the part in question.
+</div>
+</div><p>
+<a class="anchor" name="gbf47790a0bb96b22bc5e236bc40cb32e"></a><!-- doxytag: member="mm_mimepart.c::mm_mimepart_free" ref="gbf47790a0bb96b22bc5e236bc40cb32e" args="(struct mm_mimepart *part)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void mm_mimepart_free </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_mimepart *&nbsp;</td>
+ <td class="paramname"> <em>part</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Frees all memory allocated by a mm_mimepart object.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>part</em>&nbsp;</td><td>A pointer to an allocated mm_mimepart object </td></tr>
+ </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__mimepart.html#g417e5dd361e30cddb91e1d9a5e30b223">mm_mimepart_new</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ged8112012a337371ae8093adb1ab6d27"></a><!-- doxytag: member="mm_mimepart.c::mm_mimepart_fromfile" ref="ged8112012a337371ae8093adb1ab6d27" args="(const char *filename)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">struct mm_mimepart* mm_mimepart_fromfile </td>
+ <td>(</td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>filename</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Creates a MIME part from a file<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>filename</em>&nbsp;</td><td>The name of the file to create the MIME part from </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A pointer to a new MIME part object</dd></dl>
+This function creates a new MIME part object from a file. The object should be freed using <a class="el" href="group__mimepart.html#gbf47790a0bb96b22bc5e236bc40cb32e">mm_mimepart_free()</a> later on. This function does NOT set the Content-Type and neither does any encoding work.
+</div>
+</div><p>
+<a class="anchor" name="g52dc9f27a2801e4f6abb1effd2ed838d"></a><!-- doxytag: member="mm_mimepart.c::mm_mimepart_getbody" ref="g52dc9f27a2801e4f6abb1effd2ed838d" args="(struct mm_mimepart *part, int opaque)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">char* mm_mimepart_getbody </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_mimepart *&nbsp;</td>
+ <td class="paramname"> <em>part</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>opaque</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Gets the pointer to the MIME part's body data<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>part</em>&nbsp;</td><td>A valid MIME part object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>opaque</em>&nbsp;</td><td>Whether to get the opaque part or not </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A pointer to the MIME part's body </dd></dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__mimepart.html#gd1def098c00edc546b03e98e9ff8b27a">mm_mimepart_setbody</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="ga3ca298eaa82f4ef3ea731511ac84e53"></a><!-- doxytag: member="mm_mimepart.c::mm_mimepart_getheaderbyname" ref="ga3ca298eaa82f4ef3ea731511ac84e53" args="(struct mm_mimepart *part, const char *name, int idx)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">struct mm_mimeheader* mm_mimepart_getheaderbyname </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_mimepart *&nbsp;</td>
+ <td class="paramname"> <em>part</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>name</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>idx</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Get a MIME header object from a MIME part<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>part</em>&nbsp;</td><td>A valid MIME part object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>name</em>&nbsp;</td><td>The name of the MIME header which to retrieve </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>idx</em>&nbsp;</td><td>Which header field to get (in case of multiple headers of the same name). </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A pointer to the requested MIME header on success, or NULL if there either isn't a header with the requested name or idx is out of range. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g779f11f7a6a54f83763b5ef6ff87e48f"></a><!-- doxytag: member="mm_mimepart.c::mm_mimepart_getheadervalue" ref="g779f11f7a6a54f83763b5ef6ff87e48f" args="(struct mm_mimepart *part, const char *name, int idx)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">const char* mm_mimepart_getheadervalue </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_mimepart *&nbsp;</td>
+ <td class="paramname"> <em>part</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>name</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>idx</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Gets the value of a MIME header object<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>part</em>&nbsp;</td><td>A valid MIME part object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>name</em>&nbsp;</td><td>The name of the header field to get the value from </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>idx</em>&nbsp;</td><td>The index of the header field to get, in case there are multiple headers with the same name. </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A pointer to the requested value on success, or NULL if there either isn't a header with the requested name or idx is out of range. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gf8ccae1737dc4b9b91958fe448da677f"></a><!-- doxytag: member="mm_mimepart.c::mm_mimepart_getlength" ref="gf8ccae1737dc4b9b91958fe448da677f" args="(struct mm_mimepart *part)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">size_t mm_mimepart_getlength </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_mimepart *&nbsp;</td>
+ <td class="paramname"> <em>part</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Gets the length of a given MIME part object<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>part</em>&nbsp;</td><td>A valid MIME part object </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>The size of the part's body in byte.</dd></dl>
+This function returns the total length of the given MIME part's body. The length does not include the headers of the MIME parts. If the function returns 0, no body part is set currently.
+</div>
+</div><p>
+<a class="anchor" name="g210e2ceee56f8349f6778006da87d080"></a><!-- doxytag: member="mm_mimepart.c::mm_mimepart_gettype" ref="g210e2ceee56f8349f6778006da87d080" args="(struct mm_mimepart *part)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">struct mm_content* mm_mimepart_gettype </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_mimepart *&nbsp;</td>
+ <td class="paramname"> <em>part</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Gets the Content-Type of a given MIME part object<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>part</em>&nbsp;</td><td>A valid MIME part object </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>The Content-Type object of the specified MIME part</dd></dl>
+This function returns a pointer to the Content-Type object of the given MIME part. This pointer might be set to NULL, indicating that there is no Content-Type object for the given MIME part currently.
+</div>
+</div><p>
+<a class="anchor" name="g8e9064736efdeebf4b257cc45f8a6adf"></a><!-- doxytag: member="mm_mimepart.c::mm_mimepart_headers_next" ref="g8e9064736efdeebf4b257cc45f8a6adf" args="(struct mm_mimepart *part, struct mm_mimeheader **id)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">struct mm_mimeheader* mm_mimepart_headers_next </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_mimepart *&nbsp;</td>
+ <td class="paramname"> <em>part</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">struct mm_mimeheader **&nbsp;</td>
+ <td class="paramname"> <em>id</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Returns the next MIME header of a given MIME part object<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>part</em>&nbsp;</td><td>A valid MIME part object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>id</em>&nbsp;</td><td>A previously initialized MIME header object </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A pointer to the MIME header object or NULL if end of headers was reached. </dd></dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__mimepart.html#g4440bdcfddf88eb642b6a834a0557176">mm_mimepart_headers_start</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g4440bdcfddf88eb642b6a834a0557176"></a><!-- doxytag: member="mm_mimepart.c::mm_mimepart_headers_start" ref="g4440bdcfddf88eb642b6a834a0557176" args="(struct mm_mimepart *part, struct mm_mimeheader **id)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_mimepart_headers_start </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_mimepart *&nbsp;</td>
+ <td class="paramname"> <em>part</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">struct mm_mimeheader **&nbsp;</td>
+ <td class="paramname"> <em>id</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Initializes a header loop for a given MIME part<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>part</em>&nbsp;</td><td>A valid MIME part object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>id</em>&nbsp;</td><td>The address of a MIME header object (to allow reentrance) </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 on success or -1 on failure </dd></dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__mimepart.html#g8e9064736efdeebf4b257cc45f8a6adf">mm_mimepart_headers_next</a></dd></dl>
+Looping through headers can be done in the following way:<p>
+<div class="fragment"><pre class="fragment"> <span class="keyword">struct </span>mm_mimeheader *header, *lheader;
+
+ <a class="code" href="group__mimepart.html#g4440bdcfddf88eb642b6a834a0557176">mm_mimepart_headers_start</a>(part, &amp;lheader);
+
+ <span class="keywordflow">while</span> ((header = <a class="code" href="group__mimepart.html#g8e9064736efdeebf4b257cc45f8a6adf">mm_mimepart_headers_next</a>(part, &amp;lheader)) != NULL) {
+ printf(<span class="stringliteral">"%s: %s\n"</span>, header-&gt;name, header-&gt;value);
+ }
+</pre></div><p>
+For convienience, the macro mm_mimepart_headers_foreach() can be used to loop through headers in a one-shot manner.
+</div>
+</div><p>
+<a class="anchor" name="g417e5dd361e30cddb91e1d9a5e30b223"></a><!-- doxytag: member="mm_mimepart.c::mm_mimepart_new" ref="g417e5dd361e30cddb91e1d9a5e30b223" args="(void)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">struct mm_mimepart* mm_mimepart_new </td>
+ <td>(</td>
+ <td class="paramtype">void&nbsp;</td>
+ <td class="paramname"> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Allocates memory for a new mm_mimepart structure and initializes it.<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A pointer to a struct of type mm_mimeheader or NULL on failure </dd></dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__mimepart.html#gbf47790a0bb96b22bc5e236bc40cb32e">mm_mimepart_free</a> </dd></dl>
+<dl class="note" compact><dt><b>Note:</b></dt><dd>The memory must be freed by using <a class="el" href="group__mimepart.html#gbf47790a0bb96b22bc5e236bc40cb32e">mm_mimepart_free()</a> later on. </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gd1def098c00edc546b03e98e9ff8b27a"></a><!-- doxytag: member="mm_mimepart.c::mm_mimepart_setbody" ref="gd1def098c00edc546b03e98e9ff8b27a" args="(struct mm_mimepart *part, const char *data, int opaque)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void mm_mimepart_setbody </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_mimepart *&nbsp;</td>
+ <td class="paramname"> <em>part</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>data</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>opaque</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Sets the MIME part's body data<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>part</em>&nbsp;</td><td>A valid MIME part object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>data</em>&nbsp;</td><td>A pointer to the data which to set </td></tr>
+ </table>
+</dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__mimepart.html#g52dc9f27a2801e4f6abb1effd2ed838d">mm_mimepart_getbody</a></dd></dl>
+This functions sets the body data for a given MIME part. The string pointed to by data must be NUL-terminated. The data is copied into the MIME part's body, and thus, the memory pointed to by data can be freed after the operation.
+</div>
+</div><p>
+<a class="anchor" name="g164bb39a266559574c252f11266809ff"></a><!-- doxytag: member="mm_mimepart.c::mm_mimepart_setdefaultcontenttype" ref="g164bb39a266559574c252f11266809ff" args="(struct mm_mimepart *part, int composite)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_mimepart_setdefaultcontenttype </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_mimepart *&nbsp;</td>
+ <td class="paramname"> <em>part</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>composite</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Sets the default Content-Type for a given MIME part<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>part</em>&nbsp;</td><td>A valid MIME part object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>part</em>&nbsp;</td><td>Whether the Content-Type should be for composite or not </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 on success or -1 on failure</dd></dl>
+This function sets a default Content-Type according to RFC 2045 with a value of "text/plain; charset="us-ascii"". This function should only be used if the MIME part in question does not have a valid Content-Type specification.
+</div>
+</div><p>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:09 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/group__mimeutil.html b/main/minimime/mm-docs/html/group__mimeutil.html
new file mode 100644
index 000000000..a2b128434
--- /dev/null
+++ b/main/minimime/mm-docs/html/group__mimeutil.html
@@ -0,0 +1,22 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: MIME related utility functions</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<h1>MIME related utility functions</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+</table>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:09 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/group__param.html b/main/minimime/mm-docs/html/group__param.html
new file mode 100644
index 000000000..93e821960
--- /dev/null
+++ b/main/minimime/mm-docs/html/group__param.html
@@ -0,0 +1,273 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: Accessing and manipulating MIME parameters</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<h1>Accessing and manipulating MIME parameters</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions for manipulating MIME parameters</h2></td></tr>
+<tr><td colspan="2">MIME parameters are properties attached to certain MIME headers, such as Content-Type and Content-Disposition. MIME parameters have a textual representations as in <em>name=value</em>. They contain important information about the MIME structure of a message, such as the boundary string used, which charset was used to encode the message and so on. This module provides simple to use functions to query or set MIME parameters.<p>
+Each MIME header may hold an arbitrary amount of such parameters, which are delimeted by each other with a semicolon. <br><br></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_param *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__param.html#gd3ac756551bf5a29a07d5992bfdbde09">mm_param_new</a> (void)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__param.html#g46339038e995799e6a3e37512f442fc9">mm_param_free</a> (struct mm_param *param)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_param *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__param.html#gd3970def45b8bede334f4b89a41dec15">mm_param_generate</a> (const char *name, const char *value)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__param.html#g2a266c63c7e89cf829b2af8e995e55e8">mm_param_setname</a> (struct mm_param *param, const char *name, int copy)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__param.html#gca3e636ab5700462eb32ca5bc19e4cc6">mm_param_setvalue</a> (struct mm_param *param, const char *value, int copy)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">const char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__param.html#g0e0ddccf47a2b1e0ad5bcc52c7b39753">mm_param_getname</a> (struct mm_param *param)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">const char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__param.html#g3c6f8cddd409de3000c31584e140561e">mm_param_getvalue</a> (struct mm_param *param)</td></tr>
+
+</table>
+<hr><h2>Function Documentation</h2>
+<a class="anchor" name="g46339038e995799e6a3e37512f442fc9"></a><!-- doxytag: member="mm_param.c::mm_param_free" ref="g46339038e995799e6a3e37512f442fc9" args="(struct mm_param *param)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void mm_param_free </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_param *&nbsp;</td>
+ <td class="paramname"> <em>param</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Releases all memory associated with a MIME parameter object.<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>param</em>&nbsp;</td><td>A valid MIME parameter object to be freed </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>Nothing </dd></dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__param.html#gd3ac756551bf5a29a07d5992bfdbde09">mm_param_new</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gd3970def45b8bede334f4b89a41dec15"></a><!-- doxytag: member="mm_param.c::mm_param_generate" ref="gd3970def45b8bede334f4b89a41dec15" args="(const char *name, const char *value)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">struct mm_param* mm_param_generate </td>
+ <td>(</td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>name</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>value</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Generates a new Content-Type parameter with the given name and value<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>name</em>&nbsp;</td><td>The name of the MIME parameter </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>value</em>&nbsp;</td><td>The value of the MIME parameter </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A new MIME parameter object </dd></dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__param.html#g46339038e995799e6a3e37512f442fc9">mm_param_free</a> <p>
+<a class="el" href="group__param.html#gd3ac756551bf5a29a07d5992bfdbde09">mm_param_new</a></dd></dl>
+This function generates a new MIME parameter, with the name and value given as the arguments. The needed memory for the operation is allocated dynamically. It stores a copy of name and value in the actual object, so the memory holding the arguments can safely be freed after successfull return of this function.
+</div>
+</div><p>
+<a class="anchor" name="g0e0ddccf47a2b1e0ad5bcc52c7b39753"></a><!-- doxytag: member="mm_param.c::mm_param_getname" ref="g0e0ddccf47a2b1e0ad5bcc52c7b39753" args="(struct mm_param *param)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">const char* mm_param_getname </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_param *&nbsp;</td>
+ <td class="paramname"> <em>param</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Gets the name of a MIME parameter object<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>param</em>&nbsp;</td><td>A valid MIME parameter object </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>The name of the MIME parameter </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g3c6f8cddd409de3000c31584e140561e"></a><!-- doxytag: member="mm_param.c::mm_param_getvalue" ref="g3c6f8cddd409de3000c31584e140561e" args="(struct mm_param *param)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">const char* mm_param_getvalue </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_param *&nbsp;</td>
+ <td class="paramname"> <em>param</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Gets the value of a MIME parameter object<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>param</em>&nbsp;</td><td>A valid MIME parameter object </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>The value of the MIME parameter </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gd3ac756551bf5a29a07d5992bfdbde09"></a><!-- doxytag: member="mm_param.c::mm_param_new" ref="gd3ac756551bf5a29a07d5992bfdbde09" args="(void)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">struct mm_param* mm_param_new </td>
+ <td>(</td>
+ <td class="paramtype">void&nbsp;</td>
+ <td class="paramname"> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Creates a new object to hold a MIME parameter.<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>An object representing a MIME parameter </dd></dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="group__param.html#g46339038e995799e6a3e37512f442fc9">mm_param_free</a> </dd></dl>
+<dl class="note" compact><dt><b>Note:</b></dt><dd>The allocated memory must later be freed using <a class="el" href="group__param.html#g46339038e995799e6a3e37512f442fc9">mm_param_free()</a> </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g2a266c63c7e89cf829b2af8e995e55e8"></a><!-- doxytag: member="mm_param.c::mm_param_setname" ref="g2a266c63c7e89cf829b2af8e995e55e8" args="(struct mm_param *param, const char *name, int copy)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">char* mm_param_setname </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_param *&nbsp;</td>
+ <td class="paramname"> <em>param</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>name</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>copy</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Sets the name of the given MIME parameter<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>param</em>&nbsp;</td><td>A valid MIME parameter object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>name</em>&nbsp;</td><td>The new name of the parameter </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>copy</em>&nbsp;</td><td>If set to &gt; 0, copy the value stored in name </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>The address of the previous name for passing to free() </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="gca3e636ab5700462eb32ca5bc19e4cc6"></a><!-- doxytag: member="mm_param.c::mm_param_setvalue" ref="gca3e636ab5700462eb32ca5bc19e4cc6" args="(struct mm_param *param, const char *value, int copy)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">char* mm_param_setvalue </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_param *&nbsp;</td>
+ <td class="paramname"> <em>param</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>value</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>copy</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Sets the value of the given MIME parameter<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>param</em>&nbsp;</td><td>A valid MIME parameter object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>name</em>&nbsp;</td><td>The new value for the parameter </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>copy</em>&nbsp;</td><td>If set to &gt; 0, copy the value stored in value </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>The address of the previous value for passing to free() </dd></dl>
+
+</div>
+</div><p>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:09 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/group__util.html b/main/minimime/mm-docs/html/group__util.html
new file mode 100644
index 000000000..4ea219224
--- /dev/null
+++ b/main/minimime/mm-docs/html/group__util.html
@@ -0,0 +1,280 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: General purpose utility functions</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<h1>General purpose utility functions</h1><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Utility functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g35c4383ff0dee2de18985e6edfed1ae6"></a><!-- doxytag: member="util::xfree" ref="g35c4383ff0dee2de18985e6edfed1ae6" args="(void *)" -->
+void&nbsp;</td><td class="memItemRight" valign="bottom"><b>xfree</b> (void *)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g2961ae74e91b0b28acdf9822438a581c"></a><!-- doxytag: member="util::xstrdup" ref="g2961ae74e91b0b28acdf9822438a581c" args="(const char *)" -->
+char *&nbsp;</td><td class="memItemRight" valign="bottom"><b>xstrdup</b> (const char *)</td></tr>
+
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__util.html#g2ff4ef58da7e543466e75f20f2a2d8b7">xmalloc</a> (size_t size)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__util.html#ge14637b4672461f1f0bee822406d68dc">xrealloc</a> (void *p, size_t size)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__util.html#gf0f89a29a634f6f1f833abb1e214a6b1">mm_unquote</a> (const char *string)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__util.html#g49c016ff4cfd02f1b019c4dce5aac357">mm_uncomment</a> (const char *string)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__util.html#g3ae25483c8a42f6562f2a916a511228f">xstrsep</a> (char **stringp, const char *delim)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__util.html#gf62be7dd21e545f8db72f3c9e3b6a3c3">mm_stripchars</a> (char *input, char *strip)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__util.html#g0747d4b4e33644263e6d73d2d8d4818b">mm_addchars</a> (char *input, char *add, u_int16_t linelength)</td></tr>
+
+</table>
+<hr><h2>Function Documentation</h2>
+<a class="anchor" name="g0747d4b4e33644263e6d73d2d8d4818b"></a><!-- doxytag: member="mm_util.c::mm_addchars" ref="g0747d4b4e33644263e6d73d2d8d4818b" args="(char *input, char *add, u_int16_t linelength)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">char* mm_addchars </td>
+ <td>(</td>
+ <td class="paramtype">char *&nbsp;</td>
+ <td class="paramname"> <em>input</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">char *&nbsp;</td>
+ <td class="paramname"> <em>add</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">u_int16_t&nbsp;</td>
+ <td class="paramname"> <em>linelength</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Adds characters to a string at given positions<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>input</em>&nbsp;</td><td>The string to which to add characters </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>add</em>&nbsp;</td><td>The character string to add </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>linelength</em>&nbsp;</td><td>The position where to add the character </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A copy of the string with characters added</dd></dl>
+This function adds the characters add at each linelength positions and returns this new string.
+</div>
+</div><p>
+<a class="anchor" name="gf62be7dd21e545f8db72f3c9e3b6a3c3"></a><!-- doxytag: member="mm_util.c::mm_stripchars" ref="gf62be7dd21e545f8db72f3c9e3b6a3c3" args="(char *input, char *strip)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">char* mm_stripchars </td>
+ <td>(</td>
+ <td class="paramtype">char *&nbsp;</td>
+ <td class="paramname"> <em>input</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">char *&nbsp;</td>
+ <td class="paramname"> <em>strip</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Strips a given character set from a string<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>input</em>&nbsp;</td><td>The string which to strip </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>strip</em>&nbsp;</td><td>The character set to strip off </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A copy of the original string with all chars stripped </dd></dl>
+
+</div>
+</div><p>
+<a class="anchor" name="g49c016ff4cfd02f1b019c4dce5aac357"></a><!-- doxytag: member="mm_util.c::mm_uncomment" ref="g49c016ff4cfd02f1b019c4dce5aac357" args="(const char *string)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">char* mm_uncomment </td>
+ <td>(</td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>string</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Removes MIME comments from a string<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>string</em>&nbsp;</td><td>The string to uncomment </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A pointer to the uncommented string or NULL on error. Sets mm_errno.</dd></dl>
+This function removes MIME comments from a string (included in parantheses). It returns a pointer to a newly allocated memory region in which the uncommented string is stored. The returned string needs to be freed when it's not used anymore.
+</div>
+</div><p>
+<a class="anchor" name="gf0f89a29a634f6f1f833abb1e214a6b1"></a><!-- doxytag: member="mm_util.c::mm_unquote" ref="gf0f89a29a634f6f1f833abb1e214a6b1" args="(const char *string)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">char* mm_unquote </td>
+ <td>(</td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>string</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Unquotes a string<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>string</em>&nbsp;</td><td>The quoted string to unquote </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A pointer to the unquoted string</dd></dl>
+This function unquotes a string. That is, it returns a pointer to a newly allocated memory region in which the unquoted string is stored. Only leading and trailing double-qoutes are removed. The string needs to be freed when it is not needed anymore.
+</div>
+</div><p>
+<a class="anchor" name="g2ff4ef58da7e543466e75f20f2a2d8b7"></a><!-- doxytag: member="mm_util.c::xmalloc" ref="g2ff4ef58da7e543466e75f20f2a2d8b7" args="(size_t size)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void* xmalloc </td>
+ <td>(</td>
+ <td class="paramtype">size_t&nbsp;</td>
+ <td class="paramname"> <em>size</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Allocates a block of memory<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>size</em>&nbsp;</td><td>The size of the memory region to allocate </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A pointer to the allocated memory region</dd></dl>
+<a class="el" href="group__util.html#g2ff4ef58da7e543466e75f20f2a2d8b7">xmalloc()</a> calls abort() if either the size argument is negative or the requested memory amount could not be allocated via an assert() call.
+</div>
+</div><p>
+<a class="anchor" name="ge14637b4672461f1f0bee822406d68dc"></a><!-- doxytag: member="mm_util.c::xrealloc" ref="ge14637b4672461f1f0bee822406d68dc" args="(void *p, size_t size)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void* xrealloc </td>
+ <td>(</td>
+ <td class="paramtype">void *&nbsp;</td>
+ <td class="paramname"> <em>p</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">size_t&nbsp;</td>
+ <td class="paramname"> <em>size</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+realloc() wrapper<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>p</em>&nbsp;</td><td>Pointer to a memory region which should be reallocated </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>size</em>&nbsp;</td><td>The new size of the memory region </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A pointer to the reallocated memory region</dd></dl>
+<a class="el" href="group__util.html#ge14637b4672461f1f0bee822406d68dc">xrealloc()</a> is a wrapper around realloc() which calls abort() if either the size argument is negative or the requested memory amount could not be allocated.
+</div>
+</div><p>
+<a class="anchor" name="g3ae25483c8a42f6562f2a916a511228f"></a><!-- doxytag: member="mm_util.c::xstrsep" ref="g3ae25483c8a42f6562f2a916a511228f" args="(char **stringp, const char *delim)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">char* xstrsep </td>
+ <td>(</td>
+ <td class="paramtype">char **&nbsp;</td>
+ <td class="paramname"> <em>stringp</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>delim</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+separate strings<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>stringp</em>&nbsp;</td><td>A pointer to the string being splitted </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>delim</em>&nbsp;</td><td>The delimeter string</td></tr>
+ </table>
+</dl>
+This function works similar to strsep(), with the difference that delim is treated as a whole.
+</div>
+</div><p>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:09 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/index.html b/main/minimime/mm-docs/html/index.html
new file mode 100644
index 000000000..8acc2a634
--- /dev/null
+++ b/main/minimime/mm-docs/html/index.html
@@ -0,0 +1,21 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: Main Page</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li id="current"><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<h1>MiniMIME Documentation</h1>
+<p>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/mimeparser_8h-source.html b/main/minimime/mm-docs/html/mimeparser_8h-source.html
new file mode 100644
index 000000000..035000642
--- /dev/null
+++ b/main/minimime/mm-docs/html/mimeparser_8h-source.html
@@ -0,0 +1,42 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: mimeparser.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>mimeparser.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="preprocessor">#ifndef _MIMEPARSER_H_INCLUDED</span>
+<a name="l00002"></a>00002 <span class="preprocessor"></span><span class="preprocessor">#define _MIMEPARSER_H_INCLUDED</span>
+<a name="l00003"></a>00003 <span class="preprocessor"></span>
+<a name="l00007"></a>00007 <span class="keywordtype">int</span> count_lines(<span class="keywordtype">char</span> *);
+<a name="l00008"></a>00008 <span class="keywordtype">void</span> mimieparser_yyerror(<span class="keyword">const</span> <span class="keywordtype">char</span> *);
+<a name="l00009"></a>00009 <span class="keywordtype">int</span> dprintf2(<span class="keyword">const</span> <span class="keywordtype">char</span> *, ...);
+<a name="l00010"></a>00010 <span class="keywordtype">int</span> mimeparser_yyparse(<span class="keywordtype">void</span>);
+<a name="l00011"></a>00011 <span class="keywordtype">int</span> mimeparser_yylex(<span class="keywordtype">void</span>);
+<a name="l00012"></a>00012 <span class="keywordtype">int</span> mimeparser_yyerror(<span class="keyword">const</span> <span class="keywordtype">char</span> *);
+<a name="l00013"></a>00013
+<a name="l00014"></a>00014 <span class="keyword">struct </span>s_position
+<a name="l00015"></a>00015 {
+<a name="l00016"></a>00016 size_t opaque_start;
+<a name="l00017"></a>00017 size_t start;
+<a name="l00018"></a>00018 size_t end;
+<a name="l00019"></a>00019 };
+<a name="l00020"></a>00020
+<a name="l00021"></a>00021 <span class="preprocessor">#endif </span><span class="comment">/* ! _MIMEPARSER_H_INCLUDED */</span>
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/mimeparser_8tab_8h-source.html b/main/minimime/mm-docs/html/mimeparser_8tab_8h-source.html
new file mode 100644
index 000000000..81f10816c
--- /dev/null
+++ b/main/minimime/mm-docs/html/mimeparser_8tab_8h-source.html
@@ -0,0 +1,136 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: mimeparser.tab.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>mimeparser.tab.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/* A Bison parser, made by GNU Bison 2.3. */</span>
+<a name="l00002"></a>00002
+<a name="l00003"></a>00003 <span class="comment">/* Skeleton interface for Bison's Yacc-like parsers in C</span>
+<a name="l00004"></a>00004 <span class="comment"></span>
+<a name="l00005"></a>00005 <span class="comment"> Copyright (C) 1984, 1989, 1990, 2000, 2001, 2002, 2003, 2004, 2005, 2006</span>
+<a name="l00006"></a>00006 <span class="comment"> Free Software Foundation, Inc.</span>
+<a name="l00007"></a>00007 <span class="comment"></span>
+<a name="l00008"></a>00008 <span class="comment"> This program is free software; you can redistribute it and/or modify</span>
+<a name="l00009"></a>00009 <span class="comment"> it under the terms of the GNU General Public License as published by</span>
+<a name="l00010"></a>00010 <span class="comment"> the Free Software Foundation; either version 2, or (at your option)</span>
+<a name="l00011"></a>00011 <span class="comment"> any later version.</span>
+<a name="l00012"></a>00012 <span class="comment"></span>
+<a name="l00013"></a>00013 <span class="comment"> This program is distributed in the hope that it will be useful,</span>
+<a name="l00014"></a>00014 <span class="comment"> but WITHOUT ANY WARRANTY; without even the implied warranty of</span>
+<a name="l00015"></a>00015 <span class="comment"> MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the</span>
+<a name="l00016"></a>00016 <span class="comment"> GNU General Public License for more details.</span>
+<a name="l00017"></a>00017 <span class="comment"></span>
+<a name="l00018"></a>00018 <span class="comment"> You should have received a copy of the GNU General Public License</span>
+<a name="l00019"></a>00019 <span class="comment"> along with this program; if not, write to the Free Software</span>
+<a name="l00020"></a>00020 <span class="comment"> Foundation, Inc., 51 Franklin Street, Fifth Floor,</span>
+<a name="l00021"></a>00021 <span class="comment"> Boston, MA 02110-1301, USA. */</span>
+<a name="l00022"></a>00022
+<a name="l00023"></a>00023 <span class="comment">/* As a special exception, you may create a larger work that contains</span>
+<a name="l00024"></a>00024 <span class="comment"> part or all of the Bison parser skeleton and distribute that work</span>
+<a name="l00025"></a>00025 <span class="comment"> under terms of your choice, so long as that work isn't itself a</span>
+<a name="l00026"></a>00026 <span class="comment"> parser generator using the skeleton or a modified version thereof</span>
+<a name="l00027"></a>00027 <span class="comment"> as a parser skeleton. Alternatively, if you modify or redistribute</span>
+<a name="l00028"></a>00028 <span class="comment"> the parser skeleton itself, you may (at your option) remove this</span>
+<a name="l00029"></a>00029 <span class="comment"> special exception, which will cause the skeleton and the resulting</span>
+<a name="l00030"></a>00030 <span class="comment"> Bison output files to be licensed under the GNU General Public</span>
+<a name="l00031"></a>00031 <span class="comment"> License without this special exception.</span>
+<a name="l00032"></a>00032 <span class="comment"></span>
+<a name="l00033"></a>00033 <span class="comment"> This special exception was added by the Free Software Foundation in</span>
+<a name="l00034"></a>00034 <span class="comment"> version 2.2 of Bison. */</span>
+<a name="l00035"></a>00035
+<a name="l00036"></a>00036 <span class="comment">/* Tokens. */</span>
+<a name="l00037"></a>00037 <span class="preprocessor">#ifndef YYTOKENTYPE</span>
+<a name="l00038"></a>00038 <span class="preprocessor"></span><span class="preprocessor"># define YYTOKENTYPE</span>
+<a name="l00039"></a>00039 <span class="preprocessor"></span> <span class="comment">/* Put the tokens into the symbol table, so that GDB and other debuggers</span>
+<a name="l00040"></a>00040 <span class="comment"> know about them. */</span>
+<a name="l00041"></a>00041 <span class="keyword">enum</span> yytokentype {
+<a name="l00042"></a>00042 ANY = 258,
+<a name="l00043"></a>00043 COLON = 259,
+<a name="l00044"></a>00044 DASH = 260,
+<a name="l00045"></a>00045 DQUOTE = 261,
+<a name="l00046"></a>00046 ENDOFHEADERS = 262,
+<a name="l00047"></a>00047 EOL = 263,
+<a name="l00048"></a>00048 EOM = 264,
+<a name="l00049"></a>00049 EQUAL = 265,
+<a name="l00050"></a>00050 MIMEVERSION_HEADER = 266,
+<a name="l00051"></a>00051 SEMICOLON = 267,
+<a name="l00052"></a>00052 CONTENTDISPOSITION_HEADER = 268,
+<a name="l00053"></a>00053 CONTENTENCODING_HEADER = 269,
+<a name="l00054"></a>00054 CONTENTTYPE_HEADER = 270,
+<a name="l00055"></a>00055 MAIL_HEADER = 271,
+<a name="l00056"></a>00056 HEADERVALUE = 272,
+<a name="l00057"></a>00057 BOUNDARY = 273,
+<a name="l00058"></a>00058 ENDBOUNDARY = 274,
+<a name="l00059"></a>00059 CONTENTTYPE_VALUE = 275,
+<a name="l00060"></a>00060 TSPECIAL = 276,
+<a name="l00061"></a>00061 WORD = 277,
+<a name="l00062"></a>00062 BODY = 278,
+<a name="l00063"></a>00063 PREAMBLE = 279,
+<a name="l00064"></a>00064 POSTAMBLE = 280
+<a name="l00065"></a>00065 };
+<a name="l00066"></a>00066 <span class="preprocessor">#endif</span>
+<a name="l00067"></a>00067 <span class="preprocessor"></span><span class="comment">/* Tokens. */</span>
+<a name="l00068"></a>00068 <span class="preprocessor">#define ANY 258</span>
+<a name="l00069"></a>00069 <span class="preprocessor"></span><span class="preprocessor">#define COLON 259</span>
+<a name="l00070"></a>00070 <span class="preprocessor"></span><span class="preprocessor">#define DASH 260</span>
+<a name="l00071"></a>00071 <span class="preprocessor"></span><span class="preprocessor">#define DQUOTE 261</span>
+<a name="l00072"></a>00072 <span class="preprocessor"></span><span class="preprocessor">#define ENDOFHEADERS 262</span>
+<a name="l00073"></a>00073 <span class="preprocessor"></span><span class="preprocessor">#define EOL 263</span>
+<a name="l00074"></a>00074 <span class="preprocessor"></span><span class="preprocessor">#define EOM 264</span>
+<a name="l00075"></a>00075 <span class="preprocessor"></span><span class="preprocessor">#define EQUAL 265</span>
+<a name="l00076"></a>00076 <span class="preprocessor"></span><span class="preprocessor">#define MIMEVERSION_HEADER 266</span>
+<a name="l00077"></a>00077 <span class="preprocessor"></span><span class="preprocessor">#define SEMICOLON 267</span>
+<a name="l00078"></a>00078 <span class="preprocessor"></span><span class="preprocessor">#define CONTENTDISPOSITION_HEADER 268</span>
+<a name="l00079"></a>00079 <span class="preprocessor"></span><span class="preprocessor">#define CONTENTENCODING_HEADER 269</span>
+<a name="l00080"></a>00080 <span class="preprocessor"></span><span class="preprocessor">#define CONTENTTYPE_HEADER 270</span>
+<a name="l00081"></a>00081 <span class="preprocessor"></span><span class="preprocessor">#define MAIL_HEADER 271</span>
+<a name="l00082"></a>00082 <span class="preprocessor"></span><span class="preprocessor">#define HEADERVALUE 272</span>
+<a name="l00083"></a>00083 <span class="preprocessor"></span><span class="preprocessor">#define BOUNDARY 273</span>
+<a name="l00084"></a>00084 <span class="preprocessor"></span><span class="preprocessor">#define ENDBOUNDARY 274</span>
+<a name="l00085"></a>00085 <span class="preprocessor"></span><span class="preprocessor">#define CONTENTTYPE_VALUE 275</span>
+<a name="l00086"></a>00086 <span class="preprocessor"></span><span class="preprocessor">#define TSPECIAL 276</span>
+<a name="l00087"></a>00087 <span class="preprocessor"></span><span class="preprocessor">#define WORD 277</span>
+<a name="l00088"></a>00088 <span class="preprocessor"></span><span class="preprocessor">#define BODY 278</span>
+<a name="l00089"></a>00089 <span class="preprocessor"></span><span class="preprocessor">#define PREAMBLE 279</span>
+<a name="l00090"></a>00090 <span class="preprocessor"></span><span class="preprocessor">#define POSTAMBLE 280</span>
+<a name="l00091"></a>00091 <span class="preprocessor"></span>
+<a name="l00092"></a>00092
+<a name="l00093"></a>00093
+<a name="l00094"></a>00094
+<a name="l00095"></a>00095 <span class="preprocessor">#if ! defined YYSTYPE &amp;&amp; ! defined YYSTYPE_IS_DECLARED</span>
+<a name="l00096"></a>00096 <span class="preprocessor"></span><span class="keyword">typedef</span> <span class="keyword">union </span>YYSTYPE
+<a name="l00097"></a>00097 #line 84 "mimeparser.y"
+<a name="l00098"></a>00098 {
+<a name="l00099"></a>00099 <span class="keywordtype">int</span> number;
+<a name="l00100"></a>00100 <span class="keywordtype">char</span> *string;
+<a name="l00101"></a>00101 <span class="keyword">struct </span>s_position position;
+<a name="l00102"></a>00102 }
+<a name="l00103"></a>00103 <span class="comment">/* Line 1489 of yacc.c. */</span>
+<a name="l00104"></a>00104 <span class="preprocessor">#line 105 "mimeparser.tab.h"</span>
+<a name="l00105"></a>00105 <span class="preprocessor"></span> YYSTYPE;
+<a name="l00106"></a>00106 <span class="preprocessor"># define yystype YYSTYPE </span><span class="comment">/* obsolescent; will be withdrawn */</span>
+<a name="l00107"></a>00107 <span class="preprocessor"># define YYSTYPE_IS_DECLARED 1</span>
+<a name="l00108"></a>00108 <span class="preprocessor"></span><span class="preprocessor"># define YYSTYPE_IS_TRIVIAL 1</span>
+<a name="l00109"></a>00109 <span class="preprocessor"></span><span class="preprocessor">#endif</span>
+<a name="l00110"></a>00110 <span class="preprocessor"></span>
+<a name="l00111"></a>00111 <span class="keyword">extern</span> YYSTYPE mimeparser_yylval;
+<a name="l00112"></a>00112
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/mm_8h-source.html b/main/minimime/mm-docs/html/mm_8h-source.html
new file mode 100644
index 000000000..cc5285c21
--- /dev/null
+++ b/main/minimime/mm-docs/html/mm_8h-source.html
@@ -0,0 +1,382 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: mm.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>mm.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*</span>
+<a name="l00002"></a>00002 <span class="comment"> * $Id$</span>
+<a name="l00003"></a>00003 <span class="comment"> *</span>
+<a name="l00004"></a>00004 <span class="comment"> * MiniMIME - a library for handling MIME messages</span>
+<a name="l00005"></a>00005 <span class="comment"> *</span>
+<a name="l00006"></a>00006 <span class="comment"> * Copyright (C) 2003 Jann Fischer &lt;rezine@mistrust.net&gt;</span>
+<a name="l00007"></a>00007 <span class="comment"> * All rights reserved.</span>
+<a name="l00008"></a>00008 <span class="comment"> *</span>
+<a name="l00009"></a>00009 <span class="comment"> * Redistribution and use in source and binary forms, with or without</span>
+<a name="l00010"></a>00010 <span class="comment"> * modification, are permitted provided that the following conditions</span>
+<a name="l00011"></a>00011 <span class="comment"> * are met:</span>
+<a name="l00012"></a>00012 <span class="comment"> *</span>
+<a name="l00013"></a>00013 <span class="comment"> * 1. Redistributions of source code must retain the above copyright</span>
+<a name="l00014"></a>00014 <span class="comment"> * notice, this list of conditions and the following disclaimer.</span>
+<a name="l00015"></a>00015 <span class="comment"> * 2. Redistributions in binary form must reproduce the above copyright</span>
+<a name="l00016"></a>00016 <span class="comment"> * notice, this list of conditions and the following disclaimer in the</span>
+<a name="l00017"></a>00017 <span class="comment"> * documentation and/or other materials provided with the distribution.</span>
+<a name="l00018"></a>00018 <span class="comment"> * 3. Neither the name of the author nor the names of the contributors</span>
+<a name="l00019"></a>00019 <span class="comment"> * may be used to endorse or promote products derived from this software</span>
+<a name="l00020"></a>00020 <span class="comment"> * without specific prior written permission.</span>
+<a name="l00021"></a>00021 <span class="comment"> *</span>
+<a name="l00022"></a>00022 <span class="comment"> * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND</span>
+<a name="l00023"></a>00023 <span class="comment"> * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE</span>
+<a name="l00024"></a>00024 <span class="comment"> * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE</span>
+<a name="l00025"></a>00025 <span class="comment"> * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD</span>
+<a name="l00026"></a>00026 <span class="comment"> * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR</span>
+<a name="l00027"></a>00027 <span class="comment"> * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF</span>
+<a name="l00028"></a>00028 <span class="comment"> * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS</span>
+<a name="l00029"></a>00029 <span class="comment"> * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN</span>
+<a name="l00030"></a>00030 <span class="comment"> * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)</span>
+<a name="l00031"></a>00031 <span class="comment"> * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF</span>
+<a name="l00032"></a>00032 <span class="comment"> * THE POSSIBILITY OF SUCH DAMAGE.</span>
+<a name="l00033"></a>00033 <span class="comment"> */</span>
+<a name="l00034"></a>00034
+<a name="l00035"></a>00035 <span class="preprocessor">#ifndef _MM_H_INCLUDED</span>
+<a name="l00036"></a>00036 <span class="preprocessor"></span><span class="preprocessor">#define _MM_H_INCLUDED</span>
+<a name="l00037"></a>00037 <span class="preprocessor"></span>
+<a name="l00038"></a>00038 <span class="preprocessor">#include &lt;sys/types.h&gt;</span>
+<a name="l00039"></a>00039 <span class="preprocessor">#include &lt;assert.h&gt;</span>
+<a name="l00040"></a>00040 <span class="preprocessor">#include "mm_queue.h"</span>
+<a name="l00041"></a>00041 <span class="preprocessor">#include "mm_mem.h"</span>
+<a name="l00042"></a>00042
+<a name="l00043"></a>00043 <span class="preprocessor">#define MM_MIME_LINELEN 998</span>
+<a name="l00044"></a>00044 <span class="preprocessor"></span><span class="preprocessor">#define MM_BASE64_LINELEN 76</span>
+<a name="l00045"></a>00045 <span class="preprocessor"></span>
+<a name="l00046"></a>00046 TAILQ_HEAD(mm_mimeheaders, mm_mimeheader);
+<a name="l00047"></a>00047 TAILQ_HEAD(mm_mimeparts, mm_mimepart);
+<a name="l00048"></a>00048 TAILQ_HEAD(mm_params, mm_param);
+<a name="l00049"></a>00049 SLIST_HEAD(mm_codecs, mm_codec);
+<a name="l00050"></a>00050 SLIST_HEAD(mm_warnings, mm_warning);
+<a name="l00051"></a>00051
+<a name="l00052"></a>00052 <span class="comment">/*</span>
+<a name="l00053"></a>00053 <span class="comment"> * Parser modes</span>
+<a name="l00054"></a>00054 <span class="comment"> */</span>
+<a name="l00055"></a>00055 <span class="keyword">enum</span> mm_parsemodes
+<a name="l00056"></a>00056 {
+<a name="l00058"></a>00058 MM_PARSE_LOOSE = 0,
+<a name="l00060"></a>00060 MM_PARSE_STRICT
+<a name="l00061"></a>00061 };
+<a name="l00062"></a>00062
+<a name="l00063"></a>00063 <span class="comment">/*</span>
+<a name="l00064"></a>00064 <span class="comment"> * Available parser flags</span>
+<a name="l00065"></a>00065 <span class="comment"> */</span>
+<a name="l00066"></a>00066 <span class="keyword">enum</span> mm_parseflags
+<a name="l00067"></a>00067 {
+<a name="l00068"></a>00068 MM_PARSE_NONE = (1L &lt;&lt; 0),
+<a name="l00069"></a>00069 MM_PARSE_STRIPCOMMENTS = (1L &lt;&lt; 1)
+<a name="l00070"></a>00070 };
+<a name="l00071"></a>00071
+<a name="l00072"></a>00072 <span class="comment">/*</span>
+<a name="l00073"></a>00073 <span class="comment"> * Enumeration of MIME encodings</span>
+<a name="l00074"></a>00074 <span class="comment"> */</span>
+<a name="l00075"></a>00075 <span class="keyword">enum</span> mm_encoding
+<a name="l00076"></a>00076 {
+<a name="l00077"></a>00077 MM_ENCODING_NONE = 0,
+<a name="l00078"></a>00078 MM_ENCODING_BASE64,
+<a name="l00079"></a>00079 MM_ENCODING_QUOTEDPRINTABLE,
+<a name="l00080"></a>00080 MM_ENCODING_UNKNOWN
+<a name="l00081"></a>00081 };
+<a name="l00082"></a>00082
+<a name="l00083"></a>00083 <span class="comment">/*</span>
+<a name="l00084"></a>00084 <span class="comment"> * Message type</span>
+<a name="l00085"></a>00085 <span class="comment"> */</span>
+<a name="l00086"></a>00086 <span class="keyword">enum</span> mm_messagetype
+<a name="l00087"></a>00087 {
+<a name="l00089"></a>00089 MM_MSGTYPE_FLAT = 0,
+<a name="l00091"></a>00091 MM_MSGTYPE_MULTIPART
+<a name="l00092"></a>00092 };
+<a name="l00093"></a>00093
+<a name="l00094"></a>00094 <span class="comment">/*</span>
+<a name="l00095"></a>00095 <span class="comment"> * Enumeration of error categories</span>
+<a name="l00096"></a>00096 <span class="comment"> */</span>
+<a name="l00097"></a>00097 <span class="keyword">enum</span> mm_errors
+<a name="l00098"></a>00098 {
+<a name="l00099"></a>00099 MM_ERROR_NONE = 0,
+<a name="l00100"></a>00100 MM_ERROR_UNDEF,
+<a name="l00101"></a>00101 MM_ERROR_ERRNO,
+<a name="l00102"></a>00102 MM_ERROR_PARSE,
+<a name="l00103"></a>00103 MM_ERROR_MIME,
+<a name="l00104"></a>00104 MM_ERROR_CODEC,
+<a name="l00105"></a>00105 MM_ERROR_PROGRAM
+<a name="l00106"></a>00106 };
+<a name="l00107"></a>00107
+<a name="l00108"></a>00108 <span class="keyword">enum</span> mm_warning_ids
+<a name="l00109"></a>00109 {
+<a name="l00110"></a>00110 MM_WARN_NONE = 0,
+<a name="l00111"></a>00111 MM_WARN_PARSE,
+<a name="l00112"></a>00112 MM_WARN_MIME,
+<a name="l00113"></a>00113 MM_WARN_CODEC
+<a name="l00114"></a>00114 };
+<a name="l00115"></a>00115
+<a name="l00116"></a>00116 <span class="keyword">enum</span> mm_addressfields {
+<a name="l00117"></a>00117 MM_ADDR_TO = 0,
+<a name="l00118"></a>00118 MM_ADDR_CC,
+<a name="l00119"></a>00119 MM_ADDR_BCC,
+<a name="l00120"></a>00120 MM_ADDR_FROM,
+<a name="l00121"></a>00121 MM_ADDR_SENDER,
+<a name="l00122"></a>00122 MM_ADDR_REPLY_TO
+<a name="l00123"></a>00123 };
+<a name="l00124"></a>00124
+<a name="l00125"></a>00125 <span class="keyword">enum</span> mm_flatten_flags {
+<a name="l00126"></a>00126 MM_FLATTEN_NONE = 0,
+<a name="l00127"></a>00127 MM_FLATTEN_SKIPENVELOPE = (1L &lt;&lt; 1),
+<a name="l00128"></a>00128 MM_FLATTEN_OPAQUE = (1L &lt;&lt; 2),
+<a name="l00129"></a>00129 MM_FLATTEN_NOPREAMBLE = (1L &lt;&lt; 3)
+<a name="l00130"></a>00130 };
+<a name="l00131"></a>00131
+<a name="l00132"></a>00132 <span class="comment">/*</span>
+<a name="l00133"></a>00133 <span class="comment"> * More information about an error</span>
+<a name="l00134"></a>00134 <span class="comment"> */</span>
+<a name="l00135"></a>00135 <span class="keyword">struct </span>mm_error_data
+<a name="l00136"></a>00136 {
+<a name="l00137"></a>00137 <span class="keywordtype">int</span> error_id;
+<a name="l00138"></a>00138 <span class="keywordtype">int</span> error_where;
+<a name="l00139"></a>00139 <span class="keywordtype">int</span> lineno;
+<a name="l00140"></a>00140 <span class="keywordtype">char</span> error_msg[128];
+<a name="l00141"></a>00141 };
+<a name="l00142"></a>00142
+<a name="l00143"></a>00143 <span class="keyword">extern</span> <span class="keywordtype">int</span> mm_errno;
+<a name="l00144"></a>00144 <span class="keyword">extern</span> <span class="keyword">struct </span>mm_error_data mm_error;
+<a name="l00145"></a>00145
+<a name="l00146"></a>00146 <span class="keyword">enum</span> mm_warning_code
+<a name="l00147"></a>00147 {
+<a name="l00148"></a>00148 MM_WARNING_NONE = 0,
+<a name="l00149"></a>00149 MM_WARNING_INVHDR,
+<a name="l00150"></a>00150 };
+<a name="l00151"></a>00151
+<a name="l00152"></a>00152 <span class="comment">/*</span>
+<a name="l00153"></a>00153 <span class="comment"> * A parser warning</span>
+<a name="l00154"></a>00154 <span class="comment"> */</span>
+<a name="l00155"></a>00155 <span class="keyword">struct </span>mm_warning
+<a name="l00156"></a>00156 {
+<a name="l00157"></a>00157 <span class="keyword">enum</span> mm_warning_code warning;
+<a name="l00158"></a>00158 u_int32_t lineno;
+<a name="l00159"></a>00159 SLIST_ENTRY(mm_warning) next;
+<a name="l00160"></a>00160 };
+<a name="l00161"></a>00161
+<a name="l00162"></a>00162 <span class="comment">/*</span>
+<a name="l00163"></a>00163 <span class="comment"> * Representation of a MiniMIME codec object</span>
+<a name="l00164"></a>00164 <span class="comment"> */</span>
+<a name="l00165"></a>00165 struct mm_codec
+<a name="l00166"></a>00166 {
+<a name="l00167"></a>00167 <span class="keyword">enum</span> mm_encoding id;
+<a name="l00168"></a>00168 <span class="keywordtype">char</span> *encoding;
+<a name="l00169"></a>00169
+<a name="l00170"></a>00170 <span class="keywordtype">char</span> *(*encoder)(<span class="keywordtype">char</span> *, u_int32_t);
+<a name="l00171"></a>00171 <span class="keywordtype">char</span> *(*decoder)(<span class="keywordtype">char</span> *);
+<a name="l00172"></a>00172
+<a name="l00173"></a>00173 SLIST_ENTRY(mm_codec) next;
+<a name="l00174"></a>00174 };
+<a name="l00175"></a>00175
+<a name="l00176"></a>00176 <span class="comment">/*</span>
+<a name="l00177"></a>00177 <span class="comment"> * Representation of a mail or MIME header field</span>
+<a name="l00178"></a>00178 <span class="comment"> */</span>
+<a name="l00179"></a>00179 struct mm_mimeheader
+<a name="l00180"></a>00180 {
+<a name="l00181"></a>00181 <span class="keywordtype">char</span> *name;
+<a name="l00182"></a>00182 <span class="keywordtype">char</span> *value;
+<a name="l00183"></a>00183
+<a name="l00184"></a>00184 TAILQ_ENTRY(mm_mimeheader) next;
+<a name="l00185"></a>00185 };
+<a name="l00186"></a>00186
+<a name="l00187"></a>00187 <span class="comment">/*</span>
+<a name="l00188"></a>00188 <span class="comment"> * Representation of a MIME Content-Type parameter</span>
+<a name="l00189"></a>00189 <span class="comment"> */</span>
+<a name="l00190"></a>00190 struct mm_param
+<a name="l00191"></a>00191 {
+<a name="l00192"></a>00192 <span class="keywordtype">char</span> *name;
+<a name="l00193"></a>00193 <span class="keywordtype">char</span> *value;
+<a name="l00194"></a>00194
+<a name="l00195"></a>00195 TAILQ_ENTRY(mm_param) next;
+<a name="l00196"></a>00196 };
+<a name="l00197"></a>00197
+<a name="l00198"></a>00198 <span class="comment">/*</span>
+<a name="l00199"></a>00199 <span class="comment"> * Representation of a MIME Content-Type object</span>
+<a name="l00200"></a>00200 <span class="comment"> */</span>
+<a name="l00201"></a>00201 struct mm_content
+<a name="l00202"></a>00202 {
+<a name="l00203"></a>00203 <span class="keywordtype">char</span> *maintype;
+<a name="l00204"></a>00204 <span class="keywordtype">char</span> *subtype;
+<a name="l00205"></a>00205
+<a name="l00206"></a>00206 <span class="keyword">struct </span>mm_params params;
+<a name="l00207"></a>00207
+<a name="l00208"></a>00208 <span class="keywordtype">char</span> *encstring;
+<a name="l00209"></a>00209 <span class="keyword">enum</span> mm_encoding encoding;
+<a name="l00210"></a>00210 };
+<a name="l00211"></a>00211
+<a name="l00212"></a>00212 <span class="comment">/*</span>
+<a name="l00213"></a>00213 <span class="comment"> * Representation of a MIME part </span>
+<a name="l00214"></a>00214 <span class="comment"> */</span>
+<a name="l00215"></a>00215 <span class="keyword">struct </span>mm_mimepart
+<a name="l00216"></a>00216 {
+<a name="l00217"></a>00217 <span class="keyword">struct </span>mm_mimeheaders headers;
+<a name="l00218"></a>00218
+<a name="l00219"></a>00219 size_t opaque_length;
+<a name="l00220"></a>00220 <span class="keywordtype">char</span> *opaque_body;
+<a name="l00221"></a>00221
+<a name="l00222"></a>00222 size_t length;
+<a name="l00223"></a>00223 <span class="keywordtype">char</span> *body;
+<a name="l00224"></a>00224
+<a name="l00225"></a>00225 <span class="keyword">struct </span>mm_content *type;
+<a name="l00226"></a>00226
+<a name="l00227"></a>00227 <span class="keywordtype">char</span> *disposition_type;
+<a name="l00228"></a>00228 <span class="keywordtype">char</span> *filename;
+<a name="l00229"></a>00229 <span class="keywordtype">char</span> *creation_date;
+<a name="l00230"></a>00230 <span class="keywordtype">char</span> *modification_date;
+<a name="l00231"></a>00231 <span class="keywordtype">char</span> *read_date;
+<a name="l00232"></a>00232 <span class="keywordtype">char</span> *disposition_size;
+<a name="l00233"></a>00233
+<a name="l00234"></a>00234 TAILQ_ENTRY(mm_mimepart) next;
+<a name="l00235"></a>00235 };
+<a name="l00236"></a>00236
+<a name="l00237"></a>00237 <span class="comment">/*</span>
+<a name="l00238"></a>00238 <span class="comment"> * Represantation of a MiniMIME context</span>
+<a name="l00239"></a>00239 <span class="comment"> */</span>
+<a name="l00240"></a>00240 struct mm_context
+<a name="l00241"></a>00241 {
+<a name="l00242"></a>00242 <span class="keyword">struct </span>mm_mimeparts parts;
+<a name="l00243"></a>00243 <span class="keyword">enum</span> mm_messagetype messagetype;
+<a name="l00244"></a>00244 <span class="keyword">struct </span>mm_warnings warnings;
+<a name="l00245"></a>00245 <span class="keyword">struct </span>mm_codecs codecs;
+<a name="l00246"></a>00246 <span class="keywordtype">char</span> *boundary;
+<a name="l00247"></a>00247 <span class="keywordtype">char</span> *preamble;
+<a name="l00248"></a>00248 size_t max_message_size;
+<a name="l00249"></a>00249 };
+<a name="l00250"></a>00250
+<a name="l00251"></a>00251 <span class="keyword">typedef</span> <span class="keyword">struct </span>mm_context MM_CTX;
+<a name="l00252"></a>00252 <span class="keyword">typedef</span> <span class="keyword">struct </span>mm_context mm_ctx_t;
+<a name="l00253"></a>00253
+<a name="l00254"></a>00254 <span class="keywordtype">char</span> *<a class="code" href="group__util.html#gf0f89a29a634f6f1f833abb1e214a6b1">mm_unquote</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *);
+<a name="l00255"></a>00255 <span class="keywordtype">char</span> *<a class="code" href="group__util.html#g49c016ff4cfd02f1b019c4dce5aac357">mm_uncomment</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *);
+<a name="l00256"></a>00256 <span class="keywordtype">char</span> *<a class="code" href="group__util.html#gf62be7dd21e545f8db72f3c9e3b6a3c3">mm_stripchars</a>(<span class="keywordtype">char</span> *, <span class="keywordtype">char</span> *);
+<a name="l00257"></a>00257 <span class="keywordtype">char</span> *<a class="code" href="group__util.html#g0747d4b4e33644263e6d73d2d8d4818b">mm_addchars</a>(<span class="keywordtype">char</span> *, <span class="keywordtype">char</span> *, u_int16_t);
+<a name="l00258"></a>00258 <span class="keywordtype">int</span> mm_gendate(<span class="keywordtype">char</span> **);
+<a name="l00259"></a>00259 <span class="keywordtype">void</span> mm_striptrailing(<span class="keywordtype">char</span> **, <span class="keyword">const</span> <span class="keywordtype">char</span> *);
+<a name="l00260"></a>00260 <span class="keywordtype">int</span> mm_mimeutil_genboundary(<span class="keywordtype">char</span> *, size_t, <span class="keywordtype">char</span> **);
+<a name="l00261"></a>00261
+<a name="l00262"></a>00262 <span class="keywordtype">int</span> mm_library_init(<span class="keywordtype">void</span>);
+<a name="l00263"></a>00263 <span class="keywordtype">int</span> mm_library_isinitialized(<span class="keywordtype">void</span>);
+<a name="l00264"></a>00264
+<a name="l00265"></a>00265 <span class="keywordtype">int</span> <a class="code" href="mm__parse_8c.html#58c960b6017f13d4e4ec5f09b3c38495">mm_parse_mem</a>(MM_CTX *, <span class="keyword">const</span> <span class="keywordtype">char</span> *, <span class="keywordtype">int</span>, <span class="keywordtype">int</span>);
+<a name="l00266"></a>00266 <span class="keywordtype">int</span> <a class="code" href="mm__parse_8c.html#cc9f623682b05f330c46e72e4e9d66cc">mm_parse_file</a>(MM_CTX *, <span class="keyword">const</span> <span class="keywordtype">char</span> *, <span class="keywordtype">int</span>, <span class="keywordtype">int</span>);
+<a name="l00267"></a>00267
+<a name="l00268"></a>00268 MM_CTX *<a class="code" href="group__context.html#g919fd41f85534d9c87c256857faa2610">mm_context_new</a>(<span class="keywordtype">void</span>);
+<a name="l00269"></a>00269 <span class="keywordtype">void</span> <a class="code" href="group__context.html#g76392d5269e9ef340c2f5f8336f7193b">mm_context_free</a>(MM_CTX *);
+<a name="l00270"></a>00270 <span class="keywordtype">int</span> <a class="code" href="group__context.html#gec3ca486a61b392ff68774242086768e">mm_context_attachpart</a>(MM_CTX *, <span class="keyword">struct</span> mm_mimepart *);
+<a name="l00271"></a>00271 <span class="keywordtype">int</span> <a class="code" href="group__context.html#g53d20c33a401539ef1ffa45f3dddb983">mm_context_deletepart</a>(MM_CTX *, <span class="keywordtype">int</span>, <span class="keywordtype">int</span>);
+<a name="l00272"></a>00272 <span class="keywordtype">int</span> <a class="code" href="group__context.html#gf5bb032ad1c481d31d7b1b0710939712">mm_context_countparts</a>(MM_CTX *);
+<a name="l00273"></a>00273 <span class="keyword">struct </span>mm_mimepart *<a class="code" href="group__context.html#g57fea229675f3e56a77eb40bb8193ee3">mm_context_getpart</a>(MM_CTX *, <span class="keywordtype">int</span>);
+<a name="l00274"></a>00274 <span class="keywordtype">int</span> <a class="code" href="group__context.html#g1e73cadba4acd3ef9dd148dd0c2c3e70">mm_context_iscomposite</a>(MM_CTX *);
+<a name="l00275"></a>00275 <span class="keywordtype">int</span> <a class="code" href="group__context.html#g8733dee7d83d3205349a7ee4ee5b2750">mm_context_haswarnings</a>(MM_CTX *);
+<a name="l00276"></a>00276 <span class="keywordtype">int</span> <a class="code" href="group__context.html#g5288136ab923605f6508c09359ae5772">mm_context_flatten</a>(MM_CTX *, <span class="keywordtype">char</span> **, size_t *, <span class="keywordtype">int</span>);
+<a name="l00277"></a>00277
+<a name="l00278"></a>00278 <span class="keywordtype">int</span> <a class="code" href="group__envelope.html#g38f1164142cedfc3253b068a81f85563">mm_envelope_getheaders</a>(MM_CTX *, <span class="keywordtype">char</span> **, size_t *);
+<a name="l00279"></a>00279 <span class="keywordtype">int</span> <a class="code" href="group__envelope.html#gb2c43c1645e42ae0860c902ce1dda788">mm_envelope_setheader</a>(MM_CTX *, <span class="keyword">const</span> <span class="keywordtype">char</span> *, <span class="keyword">const</span> <span class="keywordtype">char</span> *, ...);
+<a name="l00280"></a>00280
+<a name="l00281"></a>00281 <span class="keyword">struct </span>mm_mimeheader *<a class="code" href="mm__header_8c.html#2f2c5f2f640111caf3096ed46b5986a4">mm_mimeheader_new</a>(<span class="keywordtype">void</span>);
+<a name="l00282"></a>00282 <span class="keywordtype">void</span> <a class="code" href="mm__header_8c.html#61e3e62728f720ac381196ec59303064">mm_mimeheader_free</a>(<span class="keyword">struct</span> mm_mimeheader *);
+<a name="l00283"></a>00283 <span class="keyword">struct </span>mm_mimeheader *<a class="code" href="mm__header_8c.html#07a7f7dcebc91aa86f5478e1d84341a1">mm_mimeheader_generate</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *, <span class="keyword">const</span> <span class="keywordtype">char</span> *);
+<a name="l00284"></a>00284 <span class="keywordtype">int</span> mm_mimeheader_uncomment(<span class="keyword">struct</span> mm_mimeheader *);
+<a name="l00285"></a>00285 <span class="keywordtype">int</span> mm_mimeheader_uncommentbyname(<span class="keyword">struct</span> mm_mimepart *, <span class="keyword">const</span> <span class="keywordtype">char</span> *);
+<a name="l00286"></a>00286 <span class="keywordtype">int</span> mm_mimeheader_uncommentall(<span class="keyword">struct</span> mm_mimepart *);
+<a name="l00287"></a>00287 <span class="keywordtype">int</span> mm_mimeheader_tostring(<span class="keyword">struct</span> mm_mimeheader *);
+<a name="l00288"></a>00288
+<a name="l00289"></a>00289 <span class="keyword">struct </span>mm_mimepart *<a class="code" href="group__mimepart.html#g417e5dd361e30cddb91e1d9a5e30b223">mm_mimepart_new</a>(<span class="keywordtype">void</span>);
+<a name="l00290"></a>00290 <span class="keywordtype">void</span> <a class="code" href="group__mimepart.html#gbf47790a0bb96b22bc5e236bc40cb32e">mm_mimepart_free</a>(<span class="keyword">struct</span> mm_mimepart *);
+<a name="l00291"></a>00291 <span class="keywordtype">int</span> <a class="code" href="group__mimepart.html#g46a674ff6b9873c0c45fa4eb5d94fd62">mm_mimepart_attachheader</a>(<span class="keyword">struct</span> mm_mimepart *, <span class="keyword">struct</span> mm_mimeheader *);
+<a name="l00292"></a>00292 <span class="keywordtype">int</span> <a class="code" href="group__mimepart.html#g44c78abfb0535312bcb427a2cd220026">mm_mimepart_countheaders</a>(<span class="keyword">struct</span> mm_mimepart *part);
+<a name="l00293"></a>00293 <span class="keywordtype">int</span> <a class="code" href="group__mimepart.html#gf89da502ac54306994bdb452448a8026">mm_mimepart_countheaderbyname</a>(<span class="keyword">struct</span> mm_mimepart *, <span class="keyword">const</span> <span class="keywordtype">char</span> *);
+<a name="l00294"></a>00294 <span class="keyword">struct </span>mm_mimeheader *<a class="code" href="group__mimepart.html#ga3ca298eaa82f4ef3ea731511ac84e53">mm_mimepart_getheaderbyname</a>(<span class="keyword">struct</span> mm_mimepart *, <span class="keyword">const</span> <span class="keywordtype">char</span> *, <span class="keywordtype">int</span>);
+<a name="l00295"></a>00295 <span class="keyword">const</span> <span class="keywordtype">char</span> *<a class="code" href="group__mimepart.html#g779f11f7a6a54f83763b5ef6ff87e48f">mm_mimepart_getheadervalue</a>(<span class="keyword">struct</span> mm_mimepart *, <span class="keyword">const</span> <span class="keywordtype">char</span> *, <span class="keywordtype">int</span>);
+<a name="l00296"></a>00296 <span class="keywordtype">int</span> <a class="code" href="group__mimepart.html#g4440bdcfddf88eb642b6a834a0557176">mm_mimepart_headers_start</a>(<span class="keyword">struct</span> mm_mimepart *, <span class="keyword">struct</span> mm_mimeheader **);
+<a name="l00297"></a>00297 <span class="keyword">struct </span>mm_mimeheader *<a class="code" href="group__mimepart.html#g8e9064736efdeebf4b257cc45f8a6adf">mm_mimepart_headers_next</a>(<span class="keyword">struct</span> mm_mimepart *, <span class="keyword">struct</span> mm_mimeheader **);
+<a name="l00298"></a>00298 <span class="keywordtype">char</span> *<a class="code" href="group__mimepart.html#g4551bf4460e5d165bbcd9f32d4f625de">mm_mimepart_decode</a>(<span class="keyword">struct</span> mm_mimepart *);
+<a name="l00299"></a>00299 <span class="keyword">struct </span>mm_content *<a class="code" href="group__mimepart.html#g210e2ceee56f8349f6778006da87d080">mm_mimepart_gettype</a>(<span class="keyword">struct</span> mm_mimepart *);
+<a name="l00300"></a>00300 size_t <a class="code" href="group__mimepart.html#gf8ccae1737dc4b9b91958fe448da677f">mm_mimepart_getlength</a>(<span class="keyword">struct</span> mm_mimepart *);
+<a name="l00301"></a>00301 <span class="keywordtype">char</span> *<a class="code" href="group__mimepart.html#g52dc9f27a2801e4f6abb1effd2ed838d">mm_mimepart_getbody</a>(<span class="keyword">struct</span> mm_mimepart *, <span class="keywordtype">int</span>);
+<a name="l00302"></a>00302 <span class="keywordtype">void</span> <a class="code" href="group__mimepart.html#g01822bc93b4741af75b5379384354e37">mm_mimepart_attachcontenttype</a>(<span class="keyword">struct</span> mm_mimepart *, <span class="keyword">struct</span> mm_content *);
+<a name="l00303"></a>00303 <span class="keywordtype">int</span> <a class="code" href="group__mimepart.html#g164bb39a266559574c252f11266809ff">mm_mimepart_setdefaultcontenttype</a>(<span class="keyword">struct</span> mm_mimepart *, <span class="keywordtype">int</span>);
+<a name="l00304"></a>00304 <span class="keywordtype">int</span> <a class="code" href="group__mimepart.html#gf19d3ace5ae174b3eaa35f9ddbe6e216">mm_mimepart_flatten</a>(<span class="keyword">struct</span> mm_mimepart *, <span class="keywordtype">char</span> **, size_t *, <span class="keywordtype">int</span>);
+<a name="l00305"></a>00305 <span class="keyword">struct </span>mm_mimepart *<a class="code" href="group__mimepart.html#ged8112012a337371ae8093adb1ab6d27">mm_mimepart_fromfile</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *);
+<a name="l00306"></a>00306
+<a name="l00307"></a>00307 <span class="keyword">struct </span>mm_content *<a class="code" href="group__contenttype.html#g3880ac74a20b4a9f610a4159568e1801">mm_content_new</a>(<span class="keywordtype">void</span>);
+<a name="l00308"></a>00308 <span class="keywordtype">void</span> <a class="code" href="group__contenttype.html#g404314481125849bce869ee4b0f647af">mm_content_free</a>(<span class="keyword">struct</span> mm_content *);
+<a name="l00309"></a>00309 <span class="keywordtype">int</span> <a class="code" href="group__contenttype.html#g080b7ed798ed497dcd635a6bab86962f">mm_content_attachparam</a>(<span class="keyword">struct</span> mm_content *, <span class="keyword">struct</span> mm_param *);
+<a name="l00310"></a>00310 <span class="keyword">struct </span>mm_content *mm_content_parse(<span class="keyword">const</span> <span class="keywordtype">char</span> *, <span class="keywordtype">int</span>);
+<a name="l00311"></a>00311 <span class="keywordtype">char</span> *<a class="code" href="group__contenttype.html#g451441ee557ab5ef29477f3dc8330bf6">mm_content_getparambyname</a>(<span class="keyword">struct</span> mm_content *, <span class="keyword">const</span> <span class="keywordtype">char</span> *);
+<a name="l00312"></a>00312 <span class="keyword">struct </span>mm_param *mm_content_getparamobjbyname(<span class="keyword">struct</span> mm_content *, <span class="keyword">const</span> <span class="keywordtype">char</span> *);
+<a name="l00313"></a>00313 <span class="keywordtype">int</span> <a class="code" href="group__contenttype.html#g7bab273d117c6c0cacad20361d8fb1c8">mm_content_setmaintype</a>(<span class="keyword">struct</span> mm_content *, <span class="keywordtype">char</span> *, <span class="keywordtype">int</span>);
+<a name="l00314"></a>00314 <span class="keywordtype">int</span> <a class="code" href="group__contenttype.html#g14b0738410d566ad2312405946f22212">mm_content_setsubtype</a>(<span class="keyword">struct</span> mm_content *, <span class="keywordtype">char</span> *, <span class="keywordtype">int</span>);
+<a name="l00315"></a>00315 <span class="keywordtype">int</span> mm_content_settype(<span class="keyword">struct</span> mm_content *, <span class="keyword">const</span> <span class="keywordtype">char</span> *, ...);
+<a name="l00316"></a>00316 <span class="keywordtype">char</span> *<a class="code" href="group__contenttype.html#gb213081017abf6bc7e601c6bf4214924">mm_content_getmaintype</a>(<span class="keyword">struct</span> mm_content *);
+<a name="l00317"></a>00317 <span class="keywordtype">char</span> *<a class="code" href="group__contenttype.html#g97f77ef40c14cd0fb397bad358ee5d49">mm_content_getsubtype</a>(<span class="keyword">struct</span> mm_content *);
+<a name="l00318"></a>00318 <span class="keywordtype">char</span> *mm_content_gettype(<span class="keyword">struct</span> mm_content *);
+<a name="l00319"></a>00319 <span class="keywordtype">int</span> <a class="code" href="group__contenttype.html#ga7fa479f27e73dea57257421d8fc9fc5">mm_content_iscomposite</a>(<span class="keyword">struct</span> mm_content *);
+<a name="l00320"></a>00320 <span class="keywordtype">int</span> <a class="code" href="group__contenttype.html#gb724b5979182fa272fe4fd1b72b395d5">mm_content_isvalidencoding</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *);
+<a name="l00321"></a>00321 <span class="keywordtype">int</span> <a class="code" href="group__contenttype.html#gea945e48ac5cca846715543634b9afe4">mm_content_setencoding</a>(<span class="keyword">struct</span> mm_content *, <span class="keyword">const</span> <span class="keywordtype">char</span> *);
+<a name="l00322"></a>00322 <span class="keywordtype">char</span> *<a class="code" href="group__contenttype.html#g792e7d33fbb30e0123408bcef9d3204c">mm_content_paramstostring</a>(<span class="keyword">struct</span> mm_content *);
+<a name="l00323"></a>00323 <span class="keywordtype">char</span> *<a class="code" href="group__contenttype.html#g18a99c95e35a76f13a77a83c4231e738">mm_content_tostring</a>(<span class="keyword">struct</span> mm_content *);
+<a name="l00324"></a>00324
+<a name="l00325"></a>00325 <span class="keyword">struct </span>mm_param *<a class="code" href="group__param.html#gd3ac756551bf5a29a07d5992bfdbde09">mm_param_new</a>(<span class="keywordtype">void</span>);
+<a name="l00326"></a>00326 <span class="keywordtype">void</span> <a class="code" href="group__param.html#g46339038e995799e6a3e37512f442fc9">mm_param_free</a>(<span class="keyword">struct</span> mm_param *);
+<a name="l00327"></a>00327
+<a name="l00328"></a>00328 <span class="keywordtype">char</span> *mm_flatten_mimepart(<span class="keyword">struct</span> mm_mimepart *);
+<a name="l00329"></a>00329 <span class="keywordtype">char</span> *mm_flatten_context(MM_CTX *);
+<a name="l00330"></a>00330
+<a name="l00331"></a>00331 <span class="keywordtype">int</span> <a class="code" href="group__codecs.html#g9e19f6343128fd7e4ec57c3d55049b55">mm_codec_isregistered</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *);
+<a name="l00332"></a>00332 <span class="keywordtype">int</span> <a class="code" href="group__codecs.html#g6ccb0f7a1d7c870dc3dae04f31d6ccca">mm_codec_hasdecoder</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *);
+<a name="l00333"></a>00333 <span class="keywordtype">int</span> <a class="code" href="group__codecs.html#g50ff257b794ceaec7aedf9ae18bfcc57">mm_codec_hasencoder</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *);
+<a name="l00334"></a>00334 <span class="keywordtype">int</span> <a class="code" href="group__codecs.html#gf97a7311c909888ed9f6f14d6f1bf397">mm_codec_register</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *, <span class="keywordtype">char</span> *(*encoder)(<span class="keywordtype">char</span> *, u_int32_t), <span class="keywordtype">char</span> *(*decoder)(<span class="keywordtype">char</span> *));
+<a name="l00335"></a>00335 <span class="keywordtype">int</span> <a class="code" href="group__codecs.html#g0c71696bc70f834386193e3c7a0e2ca4">mm_codec_unregister</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *);
+<a name="l00336"></a>00336 <span class="keywordtype">int</span> <a class="code" href="group__codecs.html#g7c9e6538f84c368be2b56a3c9ba702be">mm_codec_unregisterall</a>(<span class="keywordtype">void</span>);
+<a name="l00337"></a>00337 <span class="keywordtype">void</span> <a class="code" href="group__codecs.html#gf39e72460fb85f5ca41f6e270a68aacc">mm_codec_registerdefaultcodecs</a>(<span class="keywordtype">void</span>);
+<a name="l00338"></a>00338
+<a name="l00339"></a>00339 <span class="keywordtype">char</span> *mm_base64_decode(<span class="keywordtype">char</span> *);
+<a name="l00340"></a>00340 <span class="keywordtype">char</span> *mm_base64_encode(<span class="keywordtype">char</span> *, u_int32_t);
+<a name="l00341"></a>00341
+<a name="l00342"></a>00342 <span class="keywordtype">void</span> <a class="code" href="group__error.html#g69de7c9bee1d535593a55807590de543">mm_error_init</a>(<span class="keywordtype">void</span>);
+<a name="l00343"></a>00343 <span class="keywordtype">void</span> <a class="code" href="group__error.html#g92006c97728639d8f32f5bc4c6e2a47f">mm_error_setmsg</a>(<span class="keyword">const</span> <span class="keywordtype">char</span> *, ...);
+<a name="l00344"></a>00344 <span class="keywordtype">void</span> mm_error_setlineno(<span class="keywordtype">int</span> lineno);
+<a name="l00345"></a>00345 <span class="keywordtype">char</span> *<a class="code" href="group__error.html#g8654857a3ac349b87d798902912371a3">mm_error_string</a>(<span class="keywordtype">void</span>);
+<a name="l00346"></a>00346 <span class="keywordtype">int</span> mm_error_lineno(<span class="keywordtype">void</span>);
+<a name="l00347"></a>00347
+<a name="l00348"></a>00348 <span class="keywordtype">void</span> mm_warning_add(MM_CTX *, <span class="keywordtype">int</span>, <span class="keyword">const</span> <span class="keywordtype">char</span> *, ...);
+<a name="l00349"></a>00349 <span class="keyword">struct </span>mm_warning *mm_warning_next(MM_CTX *, <span class="keyword">struct</span> mm_warning **);
+<a name="l00350"></a>00350
+<a name="l00351"></a>00351 <span class="preprocessor">#ifndef HAVE_STRLCPY</span>
+<a name="l00352"></a>00352 <span class="preprocessor"></span>size_t strlcpy(<span class="keywordtype">char</span> *, <span class="keyword">const</span> <span class="keywordtype">char</span> *, size_t);
+<a name="l00353"></a>00353 <span class="preprocessor">#endif </span><span class="comment">/* ! HAVE_STRLCPY */</span>
+<a name="l00354"></a>00354 <span class="preprocessor">#ifndef HAVE_STRLCAT</span>
+<a name="l00355"></a>00355 <span class="preprocessor"></span>size_t strlcat(<span class="keywordtype">char</span> *, <span class="keyword">const</span> <span class="keywordtype">char</span> *, size_t);
+<a name="l00356"></a>00356 <span class="preprocessor">#endif </span><span class="comment">/* ! HAVE_STRLCAT */</span>
+<a name="l00357"></a>00357
+<a name="l00358"></a>00358 <span class="preprocessor">#define MM_ISINIT() do { \</span>
+<a name="l00359"></a>00359 <span class="preprocessor"> assert(mm_library_isinitialized() == 1); \</span>
+<a name="l00360"></a>00360 <span class="preprocessor">} while (0);</span>
+<a name="l00361"></a>00361 <span class="preprocessor"></span>
+<a name="l00362"></a>00362 <span class="preprocessor">#endif </span><span class="comment">/* ! _MM_H_INCLUDED */</span>
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/mm__codecs_8c.html b/main/minimime/mm-docs/html/mm__codecs_8c.html
new file mode 100644
index 000000000..286282b95
--- /dev/null
+++ b/main/minimime/mm-docs/html/mm__codecs_8c.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: mm_codecs.c File Reference</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>mm_codecs.c File Reference</h1><code>#include &lt;sys/types.h&gt;</code><br>
+<code>#include &lt;sys/stat.h&gt;</code><br>
+<code>#include &lt;stdio.h&gt;</code><br>
+<code>#include &lt;stdlib.h&gt;</code><br>
+<code>#include &lt;unistd.h&gt;</code><br>
+<code>#include &lt;fcntl.h&gt;</code><br>
+<code>#include &lt;string.h&gt;</code><br>
+<code>#include &lt;assert.h&gt;</code><br>
+<code>#include &quot;<a class="el" href="mm__internal_8h-source.html">mm_internal.h</a>&quot;</code><br>
+<code>#include &quot;mm_util.h&quot;</code><br>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td colspan="2"><div class="groupHeader">Codec manipulation</div></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__codecs.html#g6ccb0f7a1d7c870dc3dae04f31d6ccca">mm_codec_hasdecoder</a> (const char *encoding)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__codecs.html#g50ff257b794ceaec7aedf9ae18bfcc57">mm_codec_hasencoder</a> (const char *encoding)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__codecs.html#g9e19f6343128fd7e4ec57c3d55049b55">mm_codec_isregistered</a> (const char *encoding)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__codecs.html#gf97a7311c909888ed9f6f14d6f1bf397">mm_codec_register</a> (const char *encoding, char *(*encoder)(char *data, u_int32_t i), char *(*decoder)(char *data))</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__codecs.html#g0c71696bc70f834386193e3c7a0e2ca4">mm_codec_unregister</a> (const char *encoding)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__codecs.html#g7c9e6538f84c368be2b56a3c9ba702be">mm_codec_unregisterall</a> (void)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__codecs.html#gf39e72460fb85f5ca41f6e270a68aacc">mm_codec_registerdefaultcodecs</a> (void)</td></tr>
+
+<tr><td colspan="2"><br><h2>Variables</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="b669b6dc7c7d10408d8da81b3f1a30d3"></a><!-- doxytag: member="mm_codecs.c::codecs" ref="b669b6dc7c7d10408d8da81b3f1a30d3" args="" -->
+mm_codecs&nbsp;</td><td class="memItemRight" valign="bottom"><b>codecs</b></td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+This module contains functions to manipulate MiniMIME codecs <hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/mm__contenttype_8c.html b/main/minimime/mm-docs/html/mm__contenttype_8c.html
new file mode 100644
index 000000000..77b44a8b5
--- /dev/null
+++ b/main/minimime/mm-docs/html/mm__contenttype_8c.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: mm_contenttype.c File Reference</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>mm_contenttype.c File Reference</h1><code>#include &lt;stdio.h&gt;</code><br>
+<code>#include &lt;stdlib.h&gt;</code><br>
+<code>#include &lt;stdarg.h&gt;</code><br>
+<code>#include &lt;string.h&gt;</code><br>
+<code>#include &lt;ctype.h&gt;</code><br>
+<code>#include &lt;assert.h&gt;</code><br>
+<code>#include &quot;<a class="el" href="mm__internal_8h-source.html">mm_internal.h</a>&quot;</code><br>
+<code>#include &quot;mm_util.h&quot;</code><br>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Data Structures</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">struct &nbsp;</td><td class="memItemRight" valign="bottom"><b>mm_encoding_mappings</b></td></tr>
+
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td colspan="2"><div class="groupHeader">Functions for manipulating Content-Type objects</div></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_content *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#g3880ac74a20b4a9f610a4159568e1801">mm_content_new</a> (void)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#g404314481125849bce869ee4b0f647af">mm_content_free</a> (struct mm_content *ct)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#g080b7ed798ed497dcd635a6bab86962f">mm_content_attachparam</a> (struct mm_content *ct, struct mm_param *param)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#g451441ee557ab5ef29477f3dc8330bf6">mm_content_getparambyname</a> (struct mm_content *ct, const char *name)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g1ba63e679d2b49aceb6cfec8a6752581"></a><!-- doxytag: member="mm_contenttype.c::mm_content_getparamobjbyname" ref="g1ba63e679d2b49aceb6cfec8a6752581" args="(struct mm_content *ct, const char *name)" -->
+mm_param *&nbsp;</td><td class="memItemRight" valign="bottom"><b>mm_content_getparamobjbyname</b> (struct mm_content *ct, const char *name)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#g7bab273d117c6c0cacad20361d8fb1c8">mm_content_setmaintype</a> (struct mm_content *ct, char *value, int copy)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#gb213081017abf6bc7e601c6bf4214924">mm_content_getmaintype</a> (struct mm_content *ct)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#g97f77ef40c14cd0fb397bad358ee5d49">mm_content_getsubtype</a> (struct mm_content *ct)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="ga6d8453eb35bd695c4944e53b7040b65"></a><!-- doxytag: member="mm_contenttype.c::mm_content_gettype" ref="ga6d8453eb35bd695c4944e53b7040b65" args="(struct mm_content *ct)" -->
+char *&nbsp;</td><td class="memItemRight" valign="bottom"><b>mm_content_gettype</b> (struct mm_content *ct)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#g14b0738410d566ad2312405946f22212">mm_content_setsubtype</a> (struct mm_content *ct, char *value, int copy)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g878686678ea2ba97aa8edb1206a564d8"></a><!-- doxytag: member="mm_contenttype.c::mm_content_settype" ref="g878686678ea2ba97aa8edb1206a564d8" args="(struct mm_content *ct, const char *fmt,...)" -->
+int&nbsp;</td><td class="memItemRight" valign="bottom"><b>mm_content_settype</b> (struct mm_content *ct, const char *fmt,...)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#ga7fa479f27e73dea57257421d8fc9fc5">mm_content_iscomposite</a> (struct mm_content *ct)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#gb724b5979182fa272fe4fd1b72b395d5">mm_content_isvalidencoding</a> (const char *encoding)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#gea945e48ac5cca846715543634b9afe4">mm_content_setencoding</a> (struct mm_content *ct, const char *encoding)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#gbff87e581cd04db16e91245e9e9de67d">mm_content_getencoding</a> (struct mm_content *ct, const char *encoding)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#g792e7d33fbb30e0123408bcef9d3204c">mm_content_paramstostring</a> (struct mm_content *ct)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__contenttype.html#g18a99c95e35a76f13a77a83c4231e738">mm_content_tostring</a> (struct mm_content *ct)</td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+This module contains functions for manipulating Content-Type objects. <hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/mm__context_8c.html b/main/minimime/mm-docs/html/mm__context_8c.html
new file mode 100644
index 000000000..064caad5d
--- /dev/null
+++ b/main/minimime/mm-docs/html/mm__context_8c.html
@@ -0,0 +1,63 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: mm_context.c File Reference</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>mm_context.c File Reference</h1><code>#include &lt;stdio.h&gt;</code><br>
+<code>#include &lt;stdlib.h&gt;</code><br>
+<code>#include &lt;stdarg.h&gt;</code><br>
+<code>#include &lt;string.h&gt;</code><br>
+<code>#include &lt;assert.h&gt;</code><br>
+<code>#include &quot;<a class="el" href="mm__internal_8h-source.html">mm_internal.h</a>&quot;</code><br>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td colspan="2"><div class="groupHeader">Manipulating MiniMIME contexts</div></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">MM_CTX *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#g919fd41f85534d9c87c256857faa2610">mm_context_new</a> (void)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#g76392d5269e9ef340c2f5f8336f7193b">mm_context_free</a> (MM_CTX *ctx)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#gec3ca486a61b392ff68774242086768e">mm_context_attachpart</a> (MM_CTX *ctx, struct mm_mimepart *part)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#g73a3dd187053aeabca4836dc28a6c468">mm_context_attachpart_after</a> (MM_CTX *ctx, struct mm_mimepart *part, int pos)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#g53d20c33a401539ef1ffa45f3dddb983">mm_context_deletepart</a> (MM_CTX *ctx, int which, int freemem)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#gf5bb032ad1c481d31d7b1b0710939712">mm_context_countparts</a> (MM_CTX *ctx)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_mimepart *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#g57fea229675f3e56a77eb40bb8193ee3">mm_context_getpart</a> (MM_CTX *ctx, int which)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#g1e73cadba4acd3ef9dd148dd0c2c3e70">mm_context_iscomposite</a> (MM_CTX *ctx)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#g8733dee7d83d3205349a7ee4ee5b2750">mm_context_haswarnings</a> (MM_CTX *ctx)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#g9710e485f51167099d90f0d659979068">mm_context_generateboundary</a> (MM_CTX *ctx)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#gc0e7cc297516618d4773830a1988fc8d">mm_context_setpreamble</a> (MM_CTX *ctx, char *preamble)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g1ebbdd51106ccdee77ca421f9692bde7"></a><!-- doxytag: member="mm_context.c::mm_context_getpreamble" ref="g1ebbdd51106ccdee77ca421f9692bde7" args="(MM_CTX *ctx)" -->
+char *&nbsp;</td><td class="memItemRight" valign="bottom"><b>mm_context_getpreamble</b> (MM_CTX *ctx)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__context.html#g5288136ab923605f6508c09359ae5772">mm_context_flatten</a> (MM_CTX *ctx, char **flat, size_t *length, int flags)</td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Modules for manipulating MiniMIME contexts <hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/mm__envelope_8c.html b/main/minimime/mm-docs/html/mm__envelope_8c.html
new file mode 100644
index 000000000..62fd8d784
--- /dev/null
+++ b/main/minimime/mm-docs/html/mm__envelope_8c.html
@@ -0,0 +1,44 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: mm_envelope.c File Reference</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>mm_envelope.c File Reference</h1><code>#include &lt;stdio.h&gt;</code><br>
+<code>#include &lt;stdlib.h&gt;</code><br>
+<code>#include &lt;stdarg.h&gt;</code><br>
+<code>#include &lt;string.h&gt;</code><br>
+<code>#include &lt;ctype.h&gt;</code><br>
+<code>#include &lt;assert.h&gt;</code><br>
+<code>#include &quot;<a class="el" href="mm__internal_8h-source.html">mm_internal.h</a>&quot;</code><br>
+<code>#include &quot;mm_util.h&quot;</code><br>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td colspan="2"><div class="groupHeader">Accessing and manipulating a message's envelope</div></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__envelope.html#g38f1164142cedfc3253b068a81f85563">mm_envelope_getheaders</a> (MM_CTX *ctx, char **result, size_t *length)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__envelope.html#gb2c43c1645e42ae0860c902ce1dda788">mm_envelope_setheader</a> (MM_CTX *ctx, const char *name, const char *fmt,...)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__envelope.html#ge63da17c56867ca2406a4eaf73230baf">mm_envelope_getrecipients</a> (MM_CTX *ctx, char **result, size_t *length)</td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+This module contains functions for accessing a message's envelope. This are mainly wrapper functions for easy access. <hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/mm__error_8c.html b/main/minimime/mm-docs/html/mm__error_8c.html
new file mode 100644
index 000000000..87ff13783
--- /dev/null
+++ b/main/minimime/mm-docs/html/mm__error_8c.html
@@ -0,0 +1,49 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: mm_error.c File Reference</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>mm_error.c File Reference</h1><code>#include &lt;stdio.h&gt;</code><br>
+<code>#include &lt;stdlib.h&gt;</code><br>
+<code>#include &lt;stdarg.h&gt;</code><br>
+<code>#include &lt;string.h&gt;</code><br>
+<code>#include &lt;assert.h&gt;</code><br>
+<code>#include &lt;errno.h&gt;</code><br>
+<code>#include &quot;<a class="el" href="mm__internal_8h-source.html">mm_internal.h</a>&quot;</code><br>
+<code>#include &quot;mm_util.h&quot;</code><br>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__error.html#g69de7c9bee1d535593a55807590de543">mm_error_init</a> (void)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__error.html#g92006c97728639d8f32f5bc4c6e2a47f">mm_error_setmsg</a> (const char *fmt,...)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="190c991d7bb378b6cd6f995ffc3011f7"></a><!-- doxytag: member="mm_error.c::mm_error_setlineno" ref="190c991d7bb378b6cd6f995ffc3011f7" args="(int lineno)" -->
+void&nbsp;</td><td class="memItemRight" valign="bottom"><b>mm_error_setlineno</b> (int lineno)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__error.html#g8654857a3ac349b87d798902912371a3">mm_error_string</a> (void)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="c84acacac29f1e6efd10bb3a89eab272"></a><!-- doxytag: member="mm_error.c::mm_error_lineno" ref="c84acacac29f1e6efd10bb3a89eab272" args="(void)" -->
+int&nbsp;</td><td class="memItemRight" valign="bottom"><b>mm_error_lineno</b> (void)</td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+This module contains functions for MiniMIME error information/manipulation <hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/mm__header_8c.html b/main/minimime/mm-docs/html/mm__header_8c.html
new file mode 100644
index 000000000..7d0212e6b
--- /dev/null
+++ b/main/minimime/mm-docs/html/mm__header_8c.html
@@ -0,0 +1,131 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: mm_header.c File Reference</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>mm_header.c File Reference</h1><code>#include &lt;stdio.h&gt;</code><br>
+<code>#include &lt;stdlib.h&gt;</code><br>
+<code>#include &lt;stdarg.h&gt;</code><br>
+<code>#include &lt;string.h&gt;</code><br>
+<code>#include &lt;ctype.h&gt;</code><br>
+<code>#include &lt;assert.h&gt;</code><br>
+<code>#include &quot;<a class="el" href="mm__internal_8h-source.html">mm_internal.h</a>&quot;</code><br>
+<code>#include &quot;mm_util.h&quot;</code><br>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_mimeheader *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="mm__header_8c.html#2f2c5f2f640111caf3096ed46b5986a4">mm_mimeheader_new</a> (void)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="mm__header_8c.html#61e3e62728f720ac381196ec59303064">mm_mimeheader_free</a> (struct mm_mimeheader *header)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_mimeheader *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="mm__header_8c.html#07a7f7dcebc91aa86f5478e1d84341a1">mm_mimeheader_generate</a> (const char *name, const char *value)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="26657e44385646fde63712d7110492d7"></a><!-- doxytag: member="mm_header.c::mm_mimeheader_uncomment" ref="26657e44385646fde63712d7110492d7" args="(struct mm_mimeheader *header)" -->
+int&nbsp;</td><td class="memItemRight" valign="bottom"><b>mm_mimeheader_uncomment</b> (struct mm_mimeheader *header)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="2081ee4c43e88d5a318a783069a5d471"></a><!-- doxytag: member="mm_header.c::mm_mimeheader_uncommentbyname" ref="2081ee4c43e88d5a318a783069a5d471" args="(struct mm_mimepart *part, const char *name)" -->
+int&nbsp;</td><td class="memItemRight" valign="bottom"><b>mm_mimeheader_uncommentbyname</b> (struct mm_mimepart *part, const char *name)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="9f9bcb0fb26461bd349c15366748ecb7"></a><!-- doxytag: member="mm_header.c::mm_mimeheader_uncommentall" ref="9f9bcb0fb26461bd349c15366748ecb7" args="(struct mm_mimepart *part)" -->
+int&nbsp;</td><td class="memItemRight" valign="bottom"><b>mm_mimeheader_uncommentall</b> (struct mm_mimepart *part)</td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+This module contains functions for manipulating MIME headers <hr><h2>Function Documentation</h2>
+<a class="anchor" name="61e3e62728f720ac381196ec59303064"></a><!-- doxytag: member="mm_header.c::mm_mimeheader_free" ref="61e3e62728f720ac381196ec59303064" args="(struct mm_mimeheader *header)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void mm_mimeheader_free </td>
+ <td>(</td>
+ <td class="paramtype">struct mm_mimeheader *&nbsp;</td>
+ <td class="paramname"> <em>header</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Frees a MIME header object<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>header</em>&nbsp;</td><td>The MIME header object which to free </td></tr>
+ </table>
+</dl>
+
+</div>
+</div><p>
+<a class="anchor" name="07a7f7dcebc91aa86f5478e1d84341a1"></a><!-- doxytag: member="mm_header.c::mm_mimeheader_generate" ref="07a7f7dcebc91aa86f5478e1d84341a1" args="(const char *name, const char *value)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">struct mm_mimeheader* mm_mimeheader_generate </td>
+ <td>(</td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>name</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>value</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Creates a new MIME header, but does no checks whatsoever (create as-is)
+</div>
+</div><p>
+<a class="anchor" name="2f2c5f2f640111caf3096ed46b5986a4"></a><!-- doxytag: member="mm_header.c::mm_mimeheader_new" ref="2f2c5f2f640111caf3096ed46b5986a4" args="(void)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">struct mm_mimeheader* mm_mimeheader_new </td>
+ <td>(</td>
+ <td class="paramtype">void&nbsp;</td>
+ <td class="paramname"> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Creates a new MIME header object<p>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A new and initialized MIME header object </dd></dl>
+<dl class="see" compact><dt><b>See also:</b></dt><dd><a class="el" href="mm__header_8c.html#61e3e62728f720ac381196ec59303064">mm_mimeheader_free</a></dd></dl>
+This function creates and initializes a new MIME header object, which must later be freed using <a class="el" href="mm__header_8c.html#61e3e62728f720ac381196ec59303064">mm_mimeheader_free()</a>
+</div>
+</div><p>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/mm__internal_8h-source.html b/main/minimime/mm-docs/html/mm__internal_8h-source.html
new file mode 100644
index 000000000..1f92a3e94
--- /dev/null
+++ b/main/minimime/mm-docs/html/mm__internal_8h-source.html
@@ -0,0 +1,82 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: mm_internal.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>mm_internal.h</h1><a href="mm__internal_8h.html">Go to the documentation of this file.</a><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*</span>
+<a name="l00002"></a>00002 <span class="comment"> * $Id$</span>
+<a name="l00003"></a>00003 <span class="comment"> *</span>
+<a name="l00004"></a>00004 <span class="comment"> * MiniMIME - a library for handling MIME messages</span>
+<a name="l00005"></a>00005 <span class="comment"> *</span>
+<a name="l00006"></a>00006 <span class="comment"> * Copyright (C) 2003 Jann Fischer &lt;rezine@mistrust.net&gt;</span>
+<a name="l00007"></a>00007 <span class="comment"> * All rights reserved.</span>
+<a name="l00008"></a>00008 <span class="comment"> *</span>
+<a name="l00009"></a>00009 <span class="comment"> * Redistribution and use in source and binary forms, with or without</span>
+<a name="l00010"></a>00010 <span class="comment"> * modification, are permitted provided that the following conditions</span>
+<a name="l00011"></a>00011 <span class="comment"> * are met:</span>
+<a name="l00012"></a>00012 <span class="comment"> *</span>
+<a name="l00013"></a>00013 <span class="comment"> * 1. Redistributions of source code must retain the above copyright</span>
+<a name="l00014"></a>00014 <span class="comment"> * notice, this list of conditions and the following disclaimer.</span>
+<a name="l00015"></a>00015 <span class="comment"> * 2. Redistributions in binary form must reproduce the above copyright</span>
+<a name="l00016"></a>00016 <span class="comment"> * notice, this list of conditions and the following disclaimer in the</span>
+<a name="l00017"></a>00017 <span class="comment"> * documentation and/or other materials provided with the distribution.</span>
+<a name="l00018"></a>00018 <span class="comment"> * 3. Neither the name of the author nor the names of the contributors</span>
+<a name="l00019"></a>00019 <span class="comment"> * may be used to endorse or promote products derived from this software</span>
+<a name="l00020"></a>00020 <span class="comment"> * without specific prior written permission.</span>
+<a name="l00021"></a>00021 <span class="comment"> *</span>
+<a name="l00022"></a>00022 <span class="comment"> * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND</span>
+<a name="l00023"></a>00023 <span class="comment"> * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE</span>
+<a name="l00024"></a>00024 <span class="comment"> * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE</span>
+<a name="l00025"></a>00025 <span class="comment"> * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD</span>
+<a name="l00026"></a>00026 <span class="comment"> * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR</span>
+<a name="l00027"></a>00027 <span class="comment"> * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF</span>
+<a name="l00028"></a>00028 <span class="comment"> * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS</span>
+<a name="l00029"></a>00029 <span class="comment"> * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN</span>
+<a name="l00030"></a>00030 <span class="comment"> * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)</span>
+<a name="l00031"></a>00031 <span class="comment"> * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF</span>
+<a name="l00032"></a>00032 <span class="comment"> * THE POSSIBILITY OF SUCH DAMAGE.</span>
+<a name="l00033"></a>00033 <span class="comment"> */</span>
+<a name="l00034"></a>00034
+<a name="l00038"></a>00038 <span class="preprocessor">#ifndef _MM_INTERNAL_H_INCLUDED</span>
+<a name="l00039"></a>00039 <span class="preprocessor"></span><span class="preprocessor">#define _MM_INTERNAL_H_INCLUDED</span>
+<a name="l00040"></a>00040 <span class="preprocessor"></span>
+<a name="l00041"></a>00041 <span class="preprocessor">#include "mm.h"</span>
+<a name="l00042"></a>00042
+<a name="l00043"></a>00043 <span class="preprocessor">#define debugp(m, ...) do { \</span>
+<a name="l00044"></a>00044 <span class="preprocessor"> fprintf(stderr, "%s:%d:: ", __FILE__, __LINE__); \</span>
+<a name="l00045"></a>00045 <span class="preprocessor"> fprintf(stderr, m, ## __VA_ARGS__); \</span>
+<a name="l00046"></a>00046 <span class="preprocessor"> fprintf(stderr, "\n"); \</span>
+<a name="l00047"></a>00047 <span class="preprocessor"> fflush(stderr); \</span>
+<a name="l00048"></a>00048 <span class="preprocessor">} while (0); </span>
+<a name="l00049"></a>00049 <span class="preprocessor"></span>
+<a name="l00054"></a>00054 <span class="preprocessor">#ifndef __HAVE_LEAK_DETECTION</span>
+<a name="l00055"></a>00055 <span class="preprocessor"></span><span class="keywordtype">void</span> *<a class="code" href="group__util.html#g2ff4ef58da7e543466e75f20f2a2d8b7">xmalloc</a>(size_t);
+<a name="l00056"></a>00056 <span class="keywordtype">void</span> *<a class="code" href="group__util.html#ge14637b4672461f1f0bee822406d68dc">xrealloc</a>(<span class="keywordtype">void</span> *, size_t);
+<a name="l00057"></a>00057 <span class="keywordtype">void</span> xfree(<span class="keywordtype">void</span> *);
+<a name="l00058"></a>00058 <span class="keywordtype">char</span> *xstrdup(<span class="keyword">const</span> <span class="keywordtype">char</span> *);
+<a name="l00059"></a>00059 <span class="preprocessor">#endif</span>
+<a name="l00060"></a>00060 <span class="preprocessor"></span>
+<a name="l00061"></a>00061 <span class="keywordtype">char</span> *<a class="code" href="group__util.html#g3ae25483c8a42f6562f2a916a511228f">xstrsep</a>(<span class="keywordtype">char</span> **, <span class="keyword">const</span> <span class="keywordtype">char</span> *);
+<a name="l00062"></a>00062
+<a name="l00063"></a>00063 <span class="comment">/* THIS FILE IS INTENTIONALLY LEFT BLANK */</span>
+<a name="l00064"></a>00064
+<a name="l00065"></a>00065 <span class="preprocessor">#endif </span><span class="comment">/* ! _MM_INTERNAL_H_INCLUDED */</span>
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/mm__internal_8h.html b/main/minimime/mm-docs/html/mm__internal_8h.html
new file mode 100644
index 000000000..8afb665ec
--- /dev/null
+++ b/main/minimime/mm-docs/html/mm__internal_8h.html
@@ -0,0 +1,78 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: mm_internal.h File Reference</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>mm_internal.h File Reference</h1><code>#include &quot;mm.h&quot;</code><br>
+
+<p>
+<a href="mm__internal_8h-source.html">Go to the source code of this file.</a><table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Defines</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">#define&nbsp;</td><td class="memItemRight" valign="bottom"><b>debugp</b>(m,...)</td></tr>
+
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td colspan="2"><div class="groupHeader">Utility functions</div></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__util.html#g2ff4ef58da7e543466e75f20f2a2d8b7">xmalloc</a> (size_t)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__util.html#ge14637b4672461f1f0bee822406d68dc">xrealloc</a> (void *, size_t)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g35c4383ff0dee2de18985e6edfed1ae6"></a><!-- doxytag: member="mm_internal.h::xfree" ref="g35c4383ff0dee2de18985e6edfed1ae6" args="(void *)" -->
+void&nbsp;</td><td class="memItemRight" valign="bottom"><b>xfree</b> (void *)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="g2961ae74e91b0b28acdf9822438a581c"></a><!-- doxytag: member="mm_internal.h::xstrdup" ref="g2961ae74e91b0b28acdf9822438a581c" args="(const char *)" -->
+char *&nbsp;</td><td class="memItemRight" valign="bottom"><b>xstrdup</b> (const char *)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__util.html#g3ae25483c8a42f6562f2a916a511228f">xstrsep</a> (char **, const char *)</td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Data definitions for MiniMIME <hr><h2>Define Documentation</h2>
+<a class="anchor" name="089dd7bda22f552c35ebdc06a8849c56"></a><!-- doxytag: member="mm_internal.h::debugp" ref="089dd7bda22f552c35ebdc06a8849c56" args="(m,...)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">#define debugp </td>
+ <td>(</td>
+ <td class="paramtype">m, <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype"> <em>...</em>&nbsp;</td>
+ <td class="paramname"> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+<b>Value:</b><div class="fragment"><pre class="fragment"><span class="keywordflow">do</span> { \
+ fprintf(stderr, <span class="stringliteral">"%s:%d:: "</span>, __FILE__, __LINE__); \
+ fprintf(stderr, m, ## __VA_ARGS__); \
+ fprintf(stderr, <span class="stringliteral">"\n"</span>); \
+ fflush(stderr); \
+} <span class="keywordflow">while</span> (0);
+</pre></div>
+</div>
+</div><p>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/mm__mem_8h-source.html b/main/minimime/mm-docs/html/mm__mem_8h-source.html
new file mode 100644
index 000000000..69ddd73dc
--- /dev/null
+++ b/main/minimime/mm-docs/html/mm__mem_8h-source.html
@@ -0,0 +1,56 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: mm_mem.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>mm_mem.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="preprocessor">#ifndef __MEM_H</span>
+<a name="l00002"></a>00002 <span class="preprocessor"></span><span class="preprocessor">#define __MEM_H</span>
+<a name="l00003"></a>00003 <span class="preprocessor"></span>
+<a name="l00004"></a>00004 <span class="preprocessor">#ifdef __HAVE_LEAK_DETECTION</span>
+<a name="l00005"></a>00005 <span class="preprocessor"></span>
+<a name="l00006"></a>00006 <span class="preprocessor">#define NAMEOF(v) #v</span>
+<a name="l00007"></a>00007 <span class="preprocessor"></span><span class="preprocessor">#define xmalloc(x) MM_malloc(x, __FILE__, __LINE__)</span>
+<a name="l00008"></a>00008 <span class="preprocessor"></span><span class="preprocessor">#define xfree(x) MM_free(x, __FILE__, __LINE__, NAMEOF(x))</span>
+<a name="l00009"></a>00009 <span class="preprocessor"></span><span class="preprocessor">#define xstrdup(x) MM_strdup(x, __FILE__, __LINE__)</span>
+<a name="l00010"></a>00010 <span class="preprocessor"></span><span class="preprocessor">#define xrealloc(x, y) MM_realloc(x, y, __FILE__, __LINE__)</span>
+<a name="l00011"></a>00011 <span class="preprocessor"></span>
+<a name="l00012"></a>00012 TAILQ_HEAD(MM_chunks, MM_mem_chunk);
+<a name="l00013"></a>00013
+<a name="l00014"></a>00014 <span class="keyword">struct </span>MM_mem_chunk {
+<a name="l00015"></a>00015 <span class="keywordtype">void</span> *address;
+<a name="l00016"></a>00016 <span class="keyword">const</span> <span class="keywordtype">char</span> *filename;
+<a name="l00017"></a>00017 u_int32_t line;
+<a name="l00018"></a>00018 size_t size;
+<a name="l00019"></a>00019
+<a name="l00020"></a>00020 TAILQ_ENTRY(MM_mem_chunk) next;
+<a name="l00021"></a>00021 };
+<a name="l00022"></a>00022
+<a name="l00023"></a>00023 <span class="keywordtype">void</span> *MM_malloc(size_t, <span class="keywordtype">char</span> *, <span class="keywordtype">int</span>);
+<a name="l00024"></a>00024 <span class="keywordtype">void</span> *MM_realloc(<span class="keywordtype">void</span> *, size_t, <span class="keywordtype">char</span> *, <span class="keywordtype">int</span>);
+<a name="l00025"></a>00025 <span class="keywordtype">void</span> MM_free(<span class="keywordtype">void</span> *, <span class="keywordtype">char</span> *, <span class="keywordtype">int</span>, <span class="keywordtype">char</span> *);
+<a name="l00026"></a>00026 <span class="keywordtype">char</span> *MM_strdup(const <span class="keywordtype">char</span> *, <span class="keywordtype">char</span> *, <span class="keywordtype">int</span>);
+<a name="l00027"></a>00027 <span class="keywordtype">void</span> MM_leakd_init(<span class="keywordtype">void</span>);
+<a name="l00028"></a>00028 <span class="keywordtype">void</span> MM_leakd_printallocated(<span class="keywordtype">void</span>);
+<a name="l00029"></a>00029 <span class="keywordtype">void</span> MM_leakd_flush(<span class="keywordtype">void</span>);
+<a name="l00030"></a>00030
+<a name="l00031"></a>00031 <span class="preprocessor">#endif </span><span class="comment">/* __HAVE_LEAK_DETECTION */</span>
+<a name="l00032"></a>00032 <span class="preprocessor">#endif </span><span class="comment">/* ! HAVE_MEM_H */</span>
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/mm__mimepart_8c.html b/main/minimime/mm-docs/html/mm__mimepart_8c.html
new file mode 100644
index 000000000..210dd8dc9
--- /dev/null
+++ b/main/minimime/mm-docs/html/mm__mimepart_8c.html
@@ -0,0 +1,79 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: mm_mimepart.c File Reference</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>mm_mimepart.c File Reference</h1><code>#include &lt;sys/types.h&gt;</code><br>
+<code>#include &lt;sys/stat.h&gt;</code><br>
+<code>#include &lt;stdio.h&gt;</code><br>
+<code>#include &lt;stdlib.h&gt;</code><br>
+<code>#include &lt;string.h&gt;</code><br>
+<code>#include &lt;unistd.h&gt;</code><br>
+<code>#include &lt;fcntl.h&gt;</code><br>
+<code>#include &lt;ctype.h&gt;</code><br>
+<code>#include &lt;assert.h&gt;</code><br>
+<code>#include &quot;<a class="el" href="mm__internal_8h-source.html">mm_internal.h</a>&quot;</code><br>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td colspan="2"><div class="groupHeader">Creating and destroying MIME parts</div></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_mimepart *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g417e5dd361e30cddb91e1d9a5e30b223">mm_mimepart_new</a> (void)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_mimepart *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#ged8112012a337371ae8093adb1ab6d27">mm_mimepart_fromfile</a> (const char *filename)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#gbf47790a0bb96b22bc5e236bc40cb32e">mm_mimepart_free</a> (struct mm_mimepart *part)</td></tr>
+
+<tr><td colspan="2"><div class="groupHeader">Accessing the MIME part's mail header</div></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g46a674ff6b9873c0c45fa4eb5d94fd62">mm_mimepart_attachheader</a> (struct mm_mimepart *part, struct mm_mimeheader *header)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g44c78abfb0535312bcb427a2cd220026">mm_mimepart_countheaders</a> (struct mm_mimepart *part)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#gf89da502ac54306994bdb452448a8026">mm_mimepart_countheaderbyname</a> (struct mm_mimepart *part, const char *name)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_mimeheader *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#ga3ca298eaa82f4ef3ea731511ac84e53">mm_mimepart_getheaderbyname</a> (struct mm_mimepart *part, const char *name, int idx)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">const char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g779f11f7a6a54f83763b5ef6ff87e48f">mm_mimepart_getheadervalue</a> (struct mm_mimepart *part, const char *name, int idx)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g4440bdcfddf88eb642b6a834a0557176">mm_mimepart_headers_start</a> (struct mm_mimepart *part, struct mm_mimeheader **id)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_mimeheader *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g8e9064736efdeebf4b257cc45f8a6adf">mm_mimepart_headers_next</a> (struct mm_mimepart *part, struct mm_mimeheader **id)</td></tr>
+
+<tr><td colspan="2"><div class="groupHeader">Accessing and manipulating the MIME part's body</div></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g52dc9f27a2801e4f6abb1effd2ed838d">mm_mimepart_getbody</a> (struct mm_mimepart *part, int opaque)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#gd1def098c00edc546b03e98e9ff8b27a">mm_mimepart_setbody</a> (struct mm_mimepart *part, const char *data, int opaque)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">size_t&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#gf8ccae1737dc4b9b91958fe448da677f">mm_mimepart_getlength</a> (struct mm_mimepart *part)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g4551bf4460e5d165bbcd9f32d4f625de">mm_mimepart_decode</a> (struct mm_mimepart *part)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#gf19d3ace5ae174b3eaa35f9ddbe6e216">mm_mimepart_flatten</a> (struct mm_mimepart *part, char **result, size_t *length, int opaque)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g164bb39a266559574c252f11266809ff">mm_mimepart_setdefaultcontenttype</a> (struct mm_mimepart *part, int composite)</td></tr>
+
+<tr><td colspan="2"><div class="groupHeader">Accessing the MIME part's Content-Type information</div></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g01822bc93b4741af75b5379384354e37">mm_mimepart_attachcontenttype</a> (struct mm_mimepart *part, struct mm_content *ct)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_content *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__mimepart.html#g210e2ceee56f8349f6778006da87d080">mm_mimepart_gettype</a> (struct mm_mimepart *part)</td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+This module contains functions for manipulating MIME header objects. <hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/mm__mimeutil_8c.html b/main/minimime/mm-docs/html/mm__mimeutil_8c.html
new file mode 100644
index 000000000..7823572d7
--- /dev/null
+++ b/main/minimime/mm-docs/html/mm__mimeutil_8c.html
@@ -0,0 +1,76 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: mm_mimeutil.c File Reference</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>mm_mimeutil.c File Reference</h1><code>#include &lt;sys/time.h&gt;</code><br>
+<code>#include &lt;stdio.h&gt;</code><br>
+<code>#include &lt;stdlib.h&gt;</code><br>
+<code>#include &lt;string.h&gt;</code><br>
+<code>#include &lt;time.h&gt;</code><br>
+<code>#include &lt;assert.h&gt;</code><br>
+<code>#include &quot;<a class="el" href="mm__internal_8h-source.html">mm_internal.h</a>&quot;</code><br>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Defines</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="257774e1a30f8190b3d99891be64210a"></a><!-- doxytag: member="mm_mimeutil.c::MM_DATE_LENGTH" ref="257774e1a30f8190b3d99891be64210a" args="" -->
+#define&nbsp;</td><td class="memItemRight" valign="bottom"><b>MM_DATE_LENGTH</b>&nbsp;&nbsp;&nbsp;50</td></tr>
+
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="mm__mimeutil_8c.html#a7b7f63b42dfa7a7f907b615aa4cd057">mm_mimeutil_gendate</a> (char **result)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="a72e503ba7ce2552456c6bd5935febe9"></a><!-- doxytag: member="mm_mimeutil.c::mm_mimeutil_genboundary" ref="a72e503ba7ce2552456c6bd5935febe9" args="(char *prefix, size_t length, char **result)" -->
+int&nbsp;</td><td class="memItemRight" valign="bottom"><b>mm_mimeutil_genboundary</b> (char *prefix, size_t length, char **result)</td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+This module contains various MIME related utility functions. <hr><h2>Function Documentation</h2>
+<a class="anchor" name="a7b7f63b42dfa7a7f907b615aa4cd057"></a><!-- doxytag: member="mm_mimeutil.c::mm_mimeutil_gendate" ref="a7b7f63b42dfa7a7f907b615aa4cd057" args="(char **result)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_mimeutil_gendate </td>
+ <td>(</td>
+ <td class="paramtype">char **&nbsp;</td>
+ <td class="paramname"> <em>result</em> </td>
+ <td>&nbsp;)&nbsp;</td>
+ <td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Generates an RFC 2822 conform date string<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>timezone</em>&nbsp;</td><td>Whether to include timezone information </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>A pointer to the actual date string </dd></dl>
+<dl class="note" compact><dt><b>Note:</b></dt><dd>The pointer returned must be freed some time</dd></dl>
+This function generates an RFC 2822 conform date string to use in message headers. It allocates memory to hold the string and returns a pointer to it. The generated date is in the format (example):<p>
+Thu, 25 December 2003 16:35:22 +0100 (CET)<p>
+This function dynamically allocates memory and returns a pointer to it. This memory should be released with free() once not needed anymore.
+</div>
+</div><p>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/mm__param_8c.html b/main/minimime/mm-docs/html/mm__param_8c.html
new file mode 100644
index 000000000..149cf2140
--- /dev/null
+++ b/main/minimime/mm-docs/html/mm__param_8c.html
@@ -0,0 +1,57 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: mm_param.c File Reference</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>mm_param.c File Reference</h1><code>#include &lt;sys/types.h&gt;</code><br>
+<code>#include &lt;sys/stat.h&gt;</code><br>
+<code>#include &lt;stdio.h&gt;</code><br>
+<code>#include &lt;stdlib.h&gt;</code><br>
+<code>#include &lt;unistd.h&gt;</code><br>
+<code>#include &lt;fcntl.h&gt;</code><br>
+<code>#include &lt;string.h&gt;</code><br>
+<code>#include &lt;ctype.h&gt;</code><br>
+<code>#include &lt;assert.h&gt;</code><br>
+<code>#include &quot;<a class="el" href="mm__internal_8h-source.html">mm_internal.h</a>&quot;</code><br>
+<code>#include &quot;mm_util.h&quot;</code><br>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td colspan="2"><div class="groupHeader">Functions for manipulating MIME parameters</div></td></tr>
+<tr><td colspan="2"><div class="groupText">MIME parameters are properties attached to certain MIME headers, such as Content-Type and Content-Disposition. MIME parameters have a textual representations as in <em>name=value</em>. They contain important information about the MIME structure of a message, such as the boundary string used, which charset was used to encode the message and so on. This module provides simple to use functions to query or set MIME parameters.<p>
+Each MIME header may hold an arbitrary amount of such parameters, which are delimeted by each other with a semicolon. <br><br></div></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_param *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__param.html#gd3ac756551bf5a29a07d5992bfdbde09">mm_param_new</a> (void)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__param.html#g46339038e995799e6a3e37512f442fc9">mm_param_free</a> (struct mm_param *param)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">mm_param *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__param.html#gd3970def45b8bede334f4b89a41dec15">mm_param_generate</a> (const char *name, const char *value)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__param.html#g2a266c63c7e89cf829b2af8e995e55e8">mm_param_setname</a> (struct mm_param *param, const char *name, int copy)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__param.html#gca3e636ab5700462eb32ca5bc19e4cc6">mm_param_setvalue</a> (struct mm_param *param, const char *value, int copy)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">const char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__param.html#g0e0ddccf47a2b1e0ad5bcc52c7b39753">mm_param_getname</a> (struct mm_param *param)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">const char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__param.html#g3c6f8cddd409de3000c31584e140561e">mm_param_getvalue</a> (struct mm_param *param)</td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Functions to manipulate MIME parameters <hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/mm__parse_8c.html b/main/minimime/mm-docs/html/mm__parse_8c.html
new file mode 100644
index 000000000..8ce150272
--- /dev/null
+++ b/main/minimime/mm-docs/html/mm__parse_8c.html
@@ -0,0 +1,198 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: mm_parse.c File Reference</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>mm_parse.c File Reference</h1><code>#include &lt;sys/types.h&gt;</code><br>
+<code>#include &lt;sys/stat.h&gt;</code><br>
+<code>#include &lt;stdio.h&gt;</code><br>
+<code>#include &lt;stdlib.h&gt;</code><br>
+<code>#include &lt;unistd.h&gt;</code><br>
+<code>#include &lt;fcntl.h&gt;</code><br>
+<code>#include &lt;string.h&gt;</code><br>
+<code>#include &lt;ctype.h&gt;</code><br>
+<code>#include &lt;assert.h&gt;</code><br>
+<code>#include &quot;<a class="el" href="mm__internal_8h-source.html">mm_internal.h</a>&quot;</code><br>
+<code>#include &quot;mm_util.h&quot;</code><br>
+<code>#include &quot;mimeparser.h&quot;</code><br>
+<code>#include &quot;mimeparser.tab.h&quot;</code><br>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="mm__parse_8c.html#187cf71c0f6c2da1384823e3f20aa1a2">PARSER_initialize</a> (MM_CTX *, int)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="92d7d8e20b6def16fcf2649e0d88651f"></a><!-- doxytag: member="mm_parse.c::PARSER_setbuffer" ref="92d7d8e20b6def16fcf2649e0d88651f" args="(const char *)" -->
+void&nbsp;</td><td class="memItemRight" valign="bottom"><b>PARSER_setbuffer</b> (const char *)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="04446354e4248226578b90007d728a7b"></a><!-- doxytag: member="mm_parse.c::PARSER_setfp" ref="04446354e4248226578b90007d728a7b" args="(FILE *)" -->
+void&nbsp;</td><td class="memItemRight" valign="bottom"><b>PARSER_setfp</b> (FILE *)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="mm__parse_8c.html#58c960b6017f13d4e4ec5f09b3c38495">mm_parse_mem</a> (MM_CTX *ctx, const char *text, int parsemode, int flags)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">int&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="mm__parse_8c.html#cc9f623682b05f330c46e72e4e9d66cc">mm_parse_file</a> (MM_CTX *ctx, const char *filename, int parsemode, int flags)</td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+Functions to parse MIME messages <hr><h2>Function Documentation</h2>
+<a class="anchor" name="cc9f623682b05f330c46e72e4e9d66cc"></a><!-- doxytag: member="mm_parse.c::mm_parse_file" ref="cc9f623682b05f330c46e72e4e9d66cc" args="(MM_CTX *ctx, const char *filename, int parsemode, int flags)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_parse_file </td>
+ <td>(</td>
+ <td class="paramtype">MM_CTX *&nbsp;</td>
+ <td class="paramname"> <em>ctx</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>filename</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>parsemode</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>flags</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Parses a file into a MiniMIME context<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ctx</em>&nbsp;</td><td>A valid MiniMIME context object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>filename</em>&nbsp;</td><td>The name of the file to parse </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>parsemode</em>&nbsp;</td><td>The parsemode </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>flags</em>&nbsp;</td><td>The flags to pass to the parser </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 on success or -1 on failure </dd></dl>
+<dl class="note" compact><dt><b>Note:</b></dt><dd>Sets mm_errno if an error occurs</dd></dl>
+This function parses a MIME message, stored in the filesystem according to the parseflags and stores the results in the MiniMIME context specified by ctx.<p>
+The following modes can be used to specify how the message should be parsed:<p>
+<ul>
+<li>MM_PARSE_STRICT: Do not tolerate MIME violations</li><li>MM_PARSE_LOOSE: Tolerate as much MIME violations as possible</li></ul>
+<p>
+The context needs to be initialized before using <a class="el" href="group__context.html#g919fd41f85534d9c87c256857faa2610">mm_context_new()</a> and may be freed using <a class="el" href="group__context.html#g76392d5269e9ef340c2f5f8336f7193b">mm_context_free()</a>.
+</div>
+</div><p>
+<a class="anchor" name="58c960b6017f13d4e4ec5f09b3c38495"></a><!-- doxytag: member="mm_parse.c::mm_parse_mem" ref="58c960b6017f13d4e4ec5f09b3c38495" args="(MM_CTX *ctx, const char *text, int parsemode, int flags)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">int mm_parse_mem </td>
+ <td>(</td>
+ <td class="paramtype">MM_CTX *&nbsp;</td>
+ <td class="paramname"> <em>ctx</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">const char *&nbsp;</td>
+ <td class="paramname"> <em>text</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>parsemode</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>flags</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Parses a NUL-terminated string into a MiniMIME context<p>
+<dl compact><dt><b>Parameters:</b></dt><dd>
+ <table border="0" cellspacing="2" cellpadding="0">
+ <tr><td valign="top"></td><td valign="top"><em>ctx</em>&nbsp;</td><td>A valid MiniMIME context object </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>text</em>&nbsp;</td><td>The NUL-terminated string to parse </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>parsemode</em>&nbsp;</td><td>The parsemode </td></tr>
+ <tr><td valign="top"></td><td valign="top"><em>flags</em>&nbsp;</td><td>The flags to pass to the parser </td></tr>
+ </table>
+</dl>
+<dl class="return" compact><dt><b>Returns:</b></dt><dd>0 on success or -1 on failure </dd></dl>
+<dl class="note" compact><dt><b>Note:</b></dt><dd>Sets mm_errno if an error occurs</dd></dl>
+This function parses a MIME message, stored in the memory region pointed to by text (must be NUL-terminated) according to the parseflags and stores the results in the MiniMIME context specified by ctx.<p>
+The following modes can be used to specify how the message should be parsed:<p>
+<ul>
+<li>MM_PARSE_STRICT: Do not tolerate MIME violations</li><li>MM_PARSE_LOOSE: Tolerate as much MIME violations as possible</li></ul>
+<p>
+The context needs to be initialized before using <a class="el" href="group__context.html#g919fd41f85534d9c87c256857faa2610">mm_context_new()</a> and may be freed using <a class="el" href="group__context.html#g76392d5269e9ef340c2f5f8336f7193b">mm_context_free()</a>.
+</div>
+</div><p>
+<a class="anchor" name="187cf71c0f6c2da1384823e3f20aa1a2"></a><!-- doxytag: member="mm_parse.c::PARSER_initialize" ref="187cf71c0f6c2da1384823e3f20aa1a2" args="(MM_CTX *, int)" -->
+<div class="memitem">
+<div class="memproto">
+ <table class="memname">
+ <tr>
+ <td class="memname">void PARSER_initialize </td>
+ <td>(</td>
+ <td class="paramtype">MM_CTX *&nbsp;</td>
+ <td class="paramname"> <em>newctx</em>, </td>
+ </tr>
+ <tr>
+ <td class="paramkey"></td>
+ <td></td>
+ <td class="paramtype">int&nbsp;</td>
+ <td class="paramname"> <em>mode</em></td><td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td></td>
+ <td>)</td>
+ <td></td><td></td><td width="100%"></td>
+ </tr>
+ </table>
+</div>
+<div class="memdoc">
+
+<p>
+Initializes the parser engine.
+</div>
+</div><p>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/mm__queue_8h-source.html b/main/minimime/mm-docs/html/mm__queue_8h-source.html
new file mode 100644
index 000000000..250134461
--- /dev/null
+++ b/main/minimime/mm-docs/html/mm__queue_8h-source.html
@@ -0,0 +1,532 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: mm_queue.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>mm_queue.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/* $OpenBSD: queue.h,v 1.25 2004/04/08 16:08:21 henning Exp $ */</span>
+<a name="l00002"></a>00002 <span class="comment">/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */</span>
+<a name="l00003"></a>00003
+<a name="l00004"></a>00004 <span class="comment">/*</span>
+<a name="l00005"></a>00005 <span class="comment"> * Copyright (c) 1991, 1993</span>
+<a name="l00006"></a>00006 <span class="comment"> * The Regents of the University of California. All rights reserved.</span>
+<a name="l00007"></a>00007 <span class="comment"> *</span>
+<a name="l00008"></a>00008 <span class="comment"> * Redistribution and use in source and binary forms, with or without</span>
+<a name="l00009"></a>00009 <span class="comment"> * modification, are permitted provided that the following conditions</span>
+<a name="l00010"></a>00010 <span class="comment"> * are met:</span>
+<a name="l00011"></a>00011 <span class="comment"> * 1. Redistributions of source code must retain the above copyright</span>
+<a name="l00012"></a>00012 <span class="comment"> * notice, this list of conditions and the following disclaimer.</span>
+<a name="l00013"></a>00013 <span class="comment"> * 2. Redistributions in binary form must reproduce the above copyright</span>
+<a name="l00014"></a>00014 <span class="comment"> * notice, this list of conditions and the following disclaimer in the</span>
+<a name="l00015"></a>00015 <span class="comment"> * documentation and/or other materials provided with the distribution.</span>
+<a name="l00016"></a>00016 <span class="comment"> * 3. Neither the name of the University nor the names of its contributors</span>
+<a name="l00017"></a>00017 <span class="comment"> * may be used to endorse or promote products derived from this software</span>
+<a name="l00018"></a>00018 <span class="comment"> * without specific prior written permission.</span>
+<a name="l00019"></a>00019 <span class="comment"> *</span>
+<a name="l00020"></a>00020 <span class="comment"> * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND</span>
+<a name="l00021"></a>00021 <span class="comment"> * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE</span>
+<a name="l00022"></a>00022 <span class="comment"> * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE</span>
+<a name="l00023"></a>00023 <span class="comment"> * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE</span>
+<a name="l00024"></a>00024 <span class="comment"> * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL</span>
+<a name="l00025"></a>00025 <span class="comment"> * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS</span>
+<a name="l00026"></a>00026 <span class="comment"> * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)</span>
+<a name="l00027"></a>00027 <span class="comment"> * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT</span>
+<a name="l00028"></a>00028 <span class="comment"> * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY</span>
+<a name="l00029"></a>00029 <span class="comment"> * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF</span>
+<a name="l00030"></a>00030 <span class="comment"> * SUCH DAMAGE.</span>
+<a name="l00031"></a>00031 <span class="comment"> *</span>
+<a name="l00032"></a>00032 <span class="comment"> * @(#)queue.h 8.5 (Berkeley) 8/20/94</span>
+<a name="l00033"></a>00033 <span class="comment"> */</span>
+<a name="l00034"></a>00034
+<a name="l00035"></a>00035 <span class="preprocessor">#ifndef _SYS_QUEUE_H_</span>
+<a name="l00036"></a>00036 <span class="preprocessor"></span><span class="preprocessor">#define _SYS_QUEUE_H_</span>
+<a name="l00037"></a>00037 <span class="preprocessor"></span>
+<a name="l00038"></a>00038 <span class="comment">/*</span>
+<a name="l00039"></a>00039 <span class="comment"> * This file defines five types of data structures: singly-linked lists, </span>
+<a name="l00040"></a>00040 <span class="comment"> * lists, simple queues, tail queues, and circular queues.</span>
+<a name="l00041"></a>00041 <span class="comment"> *</span>
+<a name="l00042"></a>00042 <span class="comment"> *</span>
+<a name="l00043"></a>00043 <span class="comment"> * A singly-linked list is headed by a single forward pointer. The elements</span>
+<a name="l00044"></a>00044 <span class="comment"> * are singly linked for minimum space and pointer manipulation overhead at</span>
+<a name="l00045"></a>00045 <span class="comment"> * the expense of O(n) removal for arbitrary elements. New elements can be</span>
+<a name="l00046"></a>00046 <span class="comment"> * added to the list after an existing element or at the head of the list.</span>
+<a name="l00047"></a>00047 <span class="comment"> * Elements being removed from the head of the list should use the explicit</span>
+<a name="l00048"></a>00048 <span class="comment"> * macro for this purpose for optimum efficiency. A singly-linked list may</span>
+<a name="l00049"></a>00049 <span class="comment"> * only be traversed in the forward direction. Singly-linked lists are ideal</span>
+<a name="l00050"></a>00050 <span class="comment"> * for applications with large datasets and few or no removals or for</span>
+<a name="l00051"></a>00051 <span class="comment"> * implementing a LIFO queue.</span>
+<a name="l00052"></a>00052 <span class="comment"> *</span>
+<a name="l00053"></a>00053 <span class="comment"> * A list is headed by a single forward pointer (or an array of forward</span>
+<a name="l00054"></a>00054 <span class="comment"> * pointers for a hash table header). The elements are doubly linked</span>
+<a name="l00055"></a>00055 <span class="comment"> * so that an arbitrary element can be removed without a need to</span>
+<a name="l00056"></a>00056 <span class="comment"> * traverse the list. New elements can be added to the list before</span>
+<a name="l00057"></a>00057 <span class="comment"> * or after an existing element or at the head of the list. A list</span>
+<a name="l00058"></a>00058 <span class="comment"> * may only be traversed in the forward direction.</span>
+<a name="l00059"></a>00059 <span class="comment"> *</span>
+<a name="l00060"></a>00060 <span class="comment"> * A simple queue is headed by a pair of pointers, one the head of the</span>
+<a name="l00061"></a>00061 <span class="comment"> * list and the other to the tail of the list. The elements are singly</span>
+<a name="l00062"></a>00062 <span class="comment"> * linked to save space, so elements can only be removed from the</span>
+<a name="l00063"></a>00063 <span class="comment"> * head of the list. New elements can be added to the list before or after</span>
+<a name="l00064"></a>00064 <span class="comment"> * an existing element, at the head of the list, or at the end of the</span>
+<a name="l00065"></a>00065 <span class="comment"> * list. A simple queue may only be traversed in the forward direction.</span>
+<a name="l00066"></a>00066 <span class="comment"> *</span>
+<a name="l00067"></a>00067 <span class="comment"> * A tail queue is headed by a pair of pointers, one to the head of the</span>
+<a name="l00068"></a>00068 <span class="comment"> * list and the other to the tail of the list. The elements are doubly</span>
+<a name="l00069"></a>00069 <span class="comment"> * linked so that an arbitrary element can be removed without a need to</span>
+<a name="l00070"></a>00070 <span class="comment"> * traverse the list. New elements can be added to the list before or</span>
+<a name="l00071"></a>00071 <span class="comment"> * after an existing element, at the head of the list, or at the end of</span>
+<a name="l00072"></a>00072 <span class="comment"> * the list. A tail queue may be traversed in either direction.</span>
+<a name="l00073"></a>00073 <span class="comment"> *</span>
+<a name="l00074"></a>00074 <span class="comment"> * A circle queue is headed by a pair of pointers, one to the head of the</span>
+<a name="l00075"></a>00075 <span class="comment"> * list and the other to the tail of the list. The elements are doubly</span>
+<a name="l00076"></a>00076 <span class="comment"> * linked so that an arbitrary element can be removed without a need to</span>
+<a name="l00077"></a>00077 <span class="comment"> * traverse the list. New elements can be added to the list before or after</span>
+<a name="l00078"></a>00078 <span class="comment"> * an existing element, at the head of the list, or at the end of the list.</span>
+<a name="l00079"></a>00079 <span class="comment"> * A circle queue may be traversed in either direction, but has a more</span>
+<a name="l00080"></a>00080 <span class="comment"> * complex end of list detection.</span>
+<a name="l00081"></a>00081 <span class="comment"> *</span>
+<a name="l00082"></a>00082 <span class="comment"> * For details on the use of these macros, see the queue(3) manual page.</span>
+<a name="l00083"></a>00083 <span class="comment"> */</span>
+<a name="l00084"></a>00084
+<a name="l00085"></a>00085 <span class="comment">/*</span>
+<a name="l00086"></a>00086 <span class="comment"> * Singly-linked List definitions.</span>
+<a name="l00087"></a>00087 <span class="comment"> */</span>
+<a name="l00088"></a>00088 <span class="preprocessor">#define SLIST_HEAD(name, type) \</span>
+<a name="l00089"></a>00089 <span class="preprocessor">struct name { \</span>
+<a name="l00090"></a>00090 <span class="preprocessor"> struct type *slh_first; </span><span class="comment">/* first element */</span> \
+<a name="l00091"></a>00091 }
+<a name="l00092"></a>00092
+<a name="l00093"></a>00093 <span class="preprocessor">#define SLIST_HEAD_INITIALIZER(head) \</span>
+<a name="l00094"></a>00094 <span class="preprocessor"> { NULL }</span>
+<a name="l00095"></a>00095 <span class="preprocessor"></span>
+<a name="l00096"></a>00096 <span class="preprocessor">#define SLIST_ENTRY(type) \</span>
+<a name="l00097"></a>00097 <span class="preprocessor">struct { \</span>
+<a name="l00098"></a>00098 <span class="preprocessor"> struct type *sle_next; </span><span class="comment">/* next element */</span> \
+<a name="l00099"></a>00099 }
+<a name="l00100"></a>00100
+<a name="l00101"></a>00101 <span class="comment">/*</span>
+<a name="l00102"></a>00102 <span class="comment"> * Singly-linked List access methods.</span>
+<a name="l00103"></a>00103 <span class="comment"> */</span>
+<a name="l00104"></a>00104 <span class="preprocessor">#define SLIST_FIRST(head) ((head)-&gt;slh_first)</span>
+<a name="l00105"></a>00105 <span class="preprocessor"></span><span class="preprocessor">#define SLIST_END(head) NULL</span>
+<a name="l00106"></a>00106 <span class="preprocessor"></span><span class="preprocessor">#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))</span>
+<a name="l00107"></a>00107 <span class="preprocessor"></span><span class="preprocessor">#define SLIST_NEXT(elm, field) ((elm)-&gt;field.sle_next)</span>
+<a name="l00108"></a>00108 <span class="preprocessor"></span>
+<a name="l00109"></a>00109 <span class="preprocessor">#define SLIST_FOREACH(var, head, field) \</span>
+<a name="l00110"></a>00110 <span class="preprocessor"> for((var) = SLIST_FIRST(head); \</span>
+<a name="l00111"></a>00111 <span class="preprocessor"> (var) != SLIST_END(head); \</span>
+<a name="l00112"></a>00112 <span class="preprocessor"> (var) = SLIST_NEXT(var, field))</span>
+<a name="l00113"></a>00113 <span class="preprocessor"></span>
+<a name="l00114"></a>00114 <span class="preprocessor">#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \</span>
+<a name="l00115"></a>00115 <span class="preprocessor"> for ((varp) = &amp;SLIST_FIRST((head)); \</span>
+<a name="l00116"></a>00116 <span class="preprocessor"> ((var) = *(varp)) != SLIST_END(head); \</span>
+<a name="l00117"></a>00117 <span class="preprocessor"> (varp) = &amp;SLIST_NEXT((var), field))</span>
+<a name="l00118"></a>00118 <span class="preprocessor"></span>
+<a name="l00119"></a>00119 <span class="comment">/*</span>
+<a name="l00120"></a>00120 <span class="comment"> * Singly-linked List functions.</span>
+<a name="l00121"></a>00121 <span class="comment"> */</span>
+<a name="l00122"></a>00122 <span class="preprocessor">#define SLIST_INIT(head) { \</span>
+<a name="l00123"></a>00123 <span class="preprocessor"> SLIST_FIRST(head) = SLIST_END(head); \</span>
+<a name="l00124"></a>00124 <span class="preprocessor">}</span>
+<a name="l00125"></a>00125 <span class="preprocessor"></span>
+<a name="l00126"></a>00126 <span class="preprocessor">#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \</span>
+<a name="l00127"></a>00127 <span class="preprocessor"> (elm)-&gt;field.sle_next = (slistelm)-&gt;field.sle_next; \</span>
+<a name="l00128"></a>00128 <span class="preprocessor"> (slistelm)-&gt;field.sle_next = (elm); \</span>
+<a name="l00129"></a>00129 <span class="preprocessor">} while (0)</span>
+<a name="l00130"></a>00130 <span class="preprocessor"></span>
+<a name="l00131"></a>00131 <span class="preprocessor">#define SLIST_INSERT_HEAD(head, elm, field) do { \</span>
+<a name="l00132"></a>00132 <span class="preprocessor"> (elm)-&gt;field.sle_next = (head)-&gt;slh_first; \</span>
+<a name="l00133"></a>00133 <span class="preprocessor"> (head)-&gt;slh_first = (elm); \</span>
+<a name="l00134"></a>00134 <span class="preprocessor">} while (0)</span>
+<a name="l00135"></a>00135 <span class="preprocessor"></span>
+<a name="l00136"></a>00136 <span class="preprocessor">#define SLIST_REMOVE_NEXT(head, elm, field) do { \</span>
+<a name="l00137"></a>00137 <span class="preprocessor"> (elm)-&gt;field.sle_next = (elm)-&gt;field.sle_next-&gt;field.sle_next; \</span>
+<a name="l00138"></a>00138 <span class="preprocessor">} while (0)</span>
+<a name="l00139"></a>00139 <span class="preprocessor"></span>
+<a name="l00140"></a>00140 <span class="preprocessor">#define SLIST_REMOVE_HEAD(head, field) do { \</span>
+<a name="l00141"></a>00141 <span class="preprocessor"> (head)-&gt;slh_first = (head)-&gt;slh_first-&gt;field.sle_next; \</span>
+<a name="l00142"></a>00142 <span class="preprocessor">} while (0)</span>
+<a name="l00143"></a>00143 <span class="preprocessor"></span>
+<a name="l00144"></a>00144 <span class="preprocessor">#define SLIST_REMOVE(head, elm, type, field) do { \</span>
+<a name="l00145"></a>00145 <span class="preprocessor"> if ((head)-&gt;slh_first == (elm)) { \</span>
+<a name="l00146"></a>00146 <span class="preprocessor"> SLIST_REMOVE_HEAD((head), field); \</span>
+<a name="l00147"></a>00147 <span class="preprocessor"> } \</span>
+<a name="l00148"></a>00148 <span class="preprocessor"> else { \</span>
+<a name="l00149"></a>00149 <span class="preprocessor"> struct type *curelm = (head)-&gt;slh_first; \</span>
+<a name="l00150"></a>00150 <span class="preprocessor"> while( curelm-&gt;field.sle_next != (elm) ) \</span>
+<a name="l00151"></a>00151 <span class="preprocessor"> curelm = curelm-&gt;field.sle_next; \</span>
+<a name="l00152"></a>00152 <span class="preprocessor"> curelm-&gt;field.sle_next = \</span>
+<a name="l00153"></a>00153 <span class="preprocessor"> curelm-&gt;field.sle_next-&gt;field.sle_next; \</span>
+<a name="l00154"></a>00154 <span class="preprocessor"> } \</span>
+<a name="l00155"></a>00155 <span class="preprocessor">} while (0)</span>
+<a name="l00156"></a>00156 <span class="preprocessor"></span>
+<a name="l00157"></a>00157 <span class="comment">/*</span>
+<a name="l00158"></a>00158 <span class="comment"> * List definitions.</span>
+<a name="l00159"></a>00159 <span class="comment"> */</span>
+<a name="l00160"></a>00160 <span class="preprocessor">#define LIST_HEAD(name, type) \</span>
+<a name="l00161"></a>00161 <span class="preprocessor">struct name { \</span>
+<a name="l00162"></a>00162 <span class="preprocessor"> struct type *lh_first; </span><span class="comment">/* first element */</span> \
+<a name="l00163"></a>00163 }
+<a name="l00164"></a>00164
+<a name="l00165"></a>00165 <span class="preprocessor">#define LIST_HEAD_INITIALIZER(head) \</span>
+<a name="l00166"></a>00166 <span class="preprocessor"> { NULL }</span>
+<a name="l00167"></a>00167 <span class="preprocessor"></span>
+<a name="l00168"></a>00168 <span class="preprocessor">#define LIST_ENTRY(type) \</span>
+<a name="l00169"></a>00169 <span class="preprocessor">struct { \</span>
+<a name="l00170"></a>00170 <span class="preprocessor"> struct type *le_next; </span><span class="comment">/* next element */</span> \
+<a name="l00171"></a>00171 struct type **le_prev; <span class="comment">/* address of previous next element */</span> \
+<a name="l00172"></a>00172 }
+<a name="l00173"></a>00173
+<a name="l00174"></a>00174 <span class="comment">/*</span>
+<a name="l00175"></a>00175 <span class="comment"> * List access methods</span>
+<a name="l00176"></a>00176 <span class="comment"> */</span>
+<a name="l00177"></a>00177 <span class="preprocessor">#define LIST_FIRST(head) ((head)-&gt;lh_first)</span>
+<a name="l00178"></a>00178 <span class="preprocessor"></span><span class="preprocessor">#define LIST_END(head) NULL</span>
+<a name="l00179"></a>00179 <span class="preprocessor"></span><span class="preprocessor">#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))</span>
+<a name="l00180"></a>00180 <span class="preprocessor"></span><span class="preprocessor">#define LIST_NEXT(elm, field) ((elm)-&gt;field.le_next)</span>
+<a name="l00181"></a>00181 <span class="preprocessor"></span>
+<a name="l00182"></a>00182 <span class="preprocessor">#define LIST_FOREACH(var, head, field) \</span>
+<a name="l00183"></a>00183 <span class="preprocessor"> for((var) = LIST_FIRST(head); \</span>
+<a name="l00184"></a>00184 <span class="preprocessor"> (var)!= LIST_END(head); \</span>
+<a name="l00185"></a>00185 <span class="preprocessor"> (var) = LIST_NEXT(var, field))</span>
+<a name="l00186"></a>00186 <span class="preprocessor"></span>
+<a name="l00187"></a>00187 <span class="comment">/*</span>
+<a name="l00188"></a>00188 <span class="comment"> * List functions.</span>
+<a name="l00189"></a>00189 <span class="comment"> */</span>
+<a name="l00190"></a>00190 <span class="preprocessor">#define LIST_INIT(head) do { \</span>
+<a name="l00191"></a>00191 <span class="preprocessor"> LIST_FIRST(head) = LIST_END(head); \</span>
+<a name="l00192"></a>00192 <span class="preprocessor">} while (0)</span>
+<a name="l00193"></a>00193 <span class="preprocessor"></span>
+<a name="l00194"></a>00194 <span class="preprocessor">#define LIST_INSERT_AFTER(listelm, elm, field) do { \</span>
+<a name="l00195"></a>00195 <span class="preprocessor"> if (((elm)-&gt;field.le_next = (listelm)-&gt;field.le_next) != NULL) \</span>
+<a name="l00196"></a>00196 <span class="preprocessor"> (listelm)-&gt;field.le_next-&gt;field.le_prev = \</span>
+<a name="l00197"></a>00197 <span class="preprocessor"> &amp;(elm)-&gt;field.le_next; \</span>
+<a name="l00198"></a>00198 <span class="preprocessor"> (listelm)-&gt;field.le_next = (elm); \</span>
+<a name="l00199"></a>00199 <span class="preprocessor"> (elm)-&gt;field.le_prev = &amp;(listelm)-&gt;field.le_next; \</span>
+<a name="l00200"></a>00200 <span class="preprocessor">} while (0)</span>
+<a name="l00201"></a>00201 <span class="preprocessor"></span>
+<a name="l00202"></a>00202 <span class="preprocessor">#define LIST_INSERT_BEFORE(listelm, elm, field) do { \</span>
+<a name="l00203"></a>00203 <span class="preprocessor"> (elm)-&gt;field.le_prev = (listelm)-&gt;field.le_prev; \</span>
+<a name="l00204"></a>00204 <span class="preprocessor"> (elm)-&gt;field.le_next = (listelm); \</span>
+<a name="l00205"></a>00205 <span class="preprocessor"> *(listelm)-&gt;field.le_prev = (elm); \</span>
+<a name="l00206"></a>00206 <span class="preprocessor"> (listelm)-&gt;field.le_prev = &amp;(elm)-&gt;field.le_next; \</span>
+<a name="l00207"></a>00207 <span class="preprocessor">} while (0)</span>
+<a name="l00208"></a>00208 <span class="preprocessor"></span>
+<a name="l00209"></a>00209 <span class="preprocessor">#define LIST_INSERT_HEAD(head, elm, field) do { \</span>
+<a name="l00210"></a>00210 <span class="preprocessor"> if (((elm)-&gt;field.le_next = (head)-&gt;lh_first) != NULL) \</span>
+<a name="l00211"></a>00211 <span class="preprocessor"> (head)-&gt;lh_first-&gt;field.le_prev = &amp;(elm)-&gt;field.le_next;\</span>
+<a name="l00212"></a>00212 <span class="preprocessor"> (head)-&gt;lh_first = (elm); \</span>
+<a name="l00213"></a>00213 <span class="preprocessor"> (elm)-&gt;field.le_prev = &amp;(head)-&gt;lh_first; \</span>
+<a name="l00214"></a>00214 <span class="preprocessor">} while (0)</span>
+<a name="l00215"></a>00215 <span class="preprocessor"></span>
+<a name="l00216"></a>00216 <span class="preprocessor">#define LIST_REMOVE(elm, field) do { \</span>
+<a name="l00217"></a>00217 <span class="preprocessor"> if ((elm)-&gt;field.le_next != NULL) \</span>
+<a name="l00218"></a>00218 <span class="preprocessor"> (elm)-&gt;field.le_next-&gt;field.le_prev = \</span>
+<a name="l00219"></a>00219 <span class="preprocessor"> (elm)-&gt;field.le_prev; \</span>
+<a name="l00220"></a>00220 <span class="preprocessor"> *(elm)-&gt;field.le_prev = (elm)-&gt;field.le_next; \</span>
+<a name="l00221"></a>00221 <span class="preprocessor">} while (0)</span>
+<a name="l00222"></a>00222 <span class="preprocessor"></span>
+<a name="l00223"></a>00223 <span class="preprocessor">#define LIST_REPLACE(elm, elm2, field) do { \</span>
+<a name="l00224"></a>00224 <span class="preprocessor"> if (((elm2)-&gt;field.le_next = (elm)-&gt;field.le_next) != NULL) \</span>
+<a name="l00225"></a>00225 <span class="preprocessor"> (elm2)-&gt;field.le_next-&gt;field.le_prev = \</span>
+<a name="l00226"></a>00226 <span class="preprocessor"> &amp;(elm2)-&gt;field.le_next; \</span>
+<a name="l00227"></a>00227 <span class="preprocessor"> (elm2)-&gt;field.le_prev = (elm)-&gt;field.le_prev; \</span>
+<a name="l00228"></a>00228 <span class="preprocessor"> *(elm2)-&gt;field.le_prev = (elm2); \</span>
+<a name="l00229"></a>00229 <span class="preprocessor">} while (0)</span>
+<a name="l00230"></a>00230 <span class="preprocessor"></span>
+<a name="l00231"></a>00231 <span class="comment">/*</span>
+<a name="l00232"></a>00232 <span class="comment"> * Simple queue definitions.</span>
+<a name="l00233"></a>00233 <span class="comment"> */</span>
+<a name="l00234"></a>00234 <span class="preprocessor">#define SIMPLEQ_HEAD(name, type) \</span>
+<a name="l00235"></a>00235 <span class="preprocessor">struct name { \</span>
+<a name="l00236"></a>00236 <span class="preprocessor"> struct type *sqh_first; </span><span class="comment">/* first element */</span> \
+<a name="l00237"></a>00237 struct type **sqh_last; <span class="comment">/* addr of last next element */</span> \
+<a name="l00238"></a>00238 }
+<a name="l00239"></a>00239
+<a name="l00240"></a>00240 <span class="preprocessor">#define SIMPLEQ_HEAD_INITIALIZER(head) \</span>
+<a name="l00241"></a>00241 <span class="preprocessor"> { NULL, &amp;(head).sqh_first }</span>
+<a name="l00242"></a>00242 <span class="preprocessor"></span>
+<a name="l00243"></a>00243 <span class="preprocessor">#define SIMPLEQ_ENTRY(type) \</span>
+<a name="l00244"></a>00244 <span class="preprocessor">struct { \</span>
+<a name="l00245"></a>00245 <span class="preprocessor"> struct type *sqe_next; </span><span class="comment">/* next element */</span> \
+<a name="l00246"></a>00246 }
+<a name="l00247"></a>00247
+<a name="l00248"></a>00248 <span class="comment">/*</span>
+<a name="l00249"></a>00249 <span class="comment"> * Simple queue access methods.</span>
+<a name="l00250"></a>00250 <span class="comment"> */</span>
+<a name="l00251"></a>00251 <span class="preprocessor">#define SIMPLEQ_FIRST(head) ((head)-&gt;sqh_first)</span>
+<a name="l00252"></a>00252 <span class="preprocessor"></span><span class="preprocessor">#define SIMPLEQ_END(head) NULL</span>
+<a name="l00253"></a>00253 <span class="preprocessor"></span><span class="preprocessor">#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))</span>
+<a name="l00254"></a>00254 <span class="preprocessor"></span><span class="preprocessor">#define SIMPLEQ_NEXT(elm, field) ((elm)-&gt;field.sqe_next)</span>
+<a name="l00255"></a>00255 <span class="preprocessor"></span>
+<a name="l00256"></a>00256 <span class="preprocessor">#define SIMPLEQ_FOREACH(var, head, field) \</span>
+<a name="l00257"></a>00257 <span class="preprocessor"> for((var) = SIMPLEQ_FIRST(head); \</span>
+<a name="l00258"></a>00258 <span class="preprocessor"> (var) != SIMPLEQ_END(head); \</span>
+<a name="l00259"></a>00259 <span class="preprocessor"> (var) = SIMPLEQ_NEXT(var, field))</span>
+<a name="l00260"></a>00260 <span class="preprocessor"></span>
+<a name="l00261"></a>00261 <span class="comment">/*</span>
+<a name="l00262"></a>00262 <span class="comment"> * Simple queue functions.</span>
+<a name="l00263"></a>00263 <span class="comment"> */</span>
+<a name="l00264"></a>00264 <span class="preprocessor">#define SIMPLEQ_INIT(head) do { \</span>
+<a name="l00265"></a>00265 <span class="preprocessor"> (head)-&gt;sqh_first = NULL; \</span>
+<a name="l00266"></a>00266 <span class="preprocessor"> (head)-&gt;sqh_last = &amp;(head)-&gt;sqh_first; \</span>
+<a name="l00267"></a>00267 <span class="preprocessor">} while (0)</span>
+<a name="l00268"></a>00268 <span class="preprocessor"></span>
+<a name="l00269"></a>00269 <span class="preprocessor">#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \</span>
+<a name="l00270"></a>00270 <span class="preprocessor"> if (((elm)-&gt;field.sqe_next = (head)-&gt;sqh_first) == NULL) \</span>
+<a name="l00271"></a>00271 <span class="preprocessor"> (head)-&gt;sqh_last = &amp;(elm)-&gt;field.sqe_next; \</span>
+<a name="l00272"></a>00272 <span class="preprocessor"> (head)-&gt;sqh_first = (elm); \</span>
+<a name="l00273"></a>00273 <span class="preprocessor">} while (0)</span>
+<a name="l00274"></a>00274 <span class="preprocessor"></span>
+<a name="l00275"></a>00275 <span class="preprocessor">#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \</span>
+<a name="l00276"></a>00276 <span class="preprocessor"> (elm)-&gt;field.sqe_next = NULL; \</span>
+<a name="l00277"></a>00277 <span class="preprocessor"> *(head)-&gt;sqh_last = (elm); \</span>
+<a name="l00278"></a>00278 <span class="preprocessor"> (head)-&gt;sqh_last = &amp;(elm)-&gt;field.sqe_next; \</span>
+<a name="l00279"></a>00279 <span class="preprocessor">} while (0)</span>
+<a name="l00280"></a>00280 <span class="preprocessor"></span>
+<a name="l00281"></a>00281 <span class="preprocessor">#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \</span>
+<a name="l00282"></a>00282 <span class="preprocessor"> if (((elm)-&gt;field.sqe_next = (listelm)-&gt;field.sqe_next) == NULL)\</span>
+<a name="l00283"></a>00283 <span class="preprocessor"> (head)-&gt;sqh_last = &amp;(elm)-&gt;field.sqe_next; \</span>
+<a name="l00284"></a>00284 <span class="preprocessor"> (listelm)-&gt;field.sqe_next = (elm); \</span>
+<a name="l00285"></a>00285 <span class="preprocessor">} while (0)</span>
+<a name="l00286"></a>00286 <span class="preprocessor"></span>
+<a name="l00287"></a>00287 <span class="preprocessor">#define SIMPLEQ_REMOVE_HEAD(head, elm, field) do { \</span>
+<a name="l00288"></a>00288 <span class="preprocessor"> if (((head)-&gt;sqh_first = (elm)-&gt;field.sqe_next) == NULL) \</span>
+<a name="l00289"></a>00289 <span class="preprocessor"> (head)-&gt;sqh_last = &amp;(head)-&gt;sqh_first; \</span>
+<a name="l00290"></a>00290 <span class="preprocessor">} while (0)</span>
+<a name="l00291"></a>00291 <span class="preprocessor"></span>
+<a name="l00292"></a>00292 <span class="comment">/*</span>
+<a name="l00293"></a>00293 <span class="comment"> * Tail queue definitions.</span>
+<a name="l00294"></a>00294 <span class="comment"> */</span>
+<a name="l00295"></a>00295 <span class="preprocessor">#define TAILQ_HEAD(name, type) \</span>
+<a name="l00296"></a>00296 <span class="preprocessor">struct name { \</span>
+<a name="l00297"></a>00297 <span class="preprocessor"> struct type *tqh_first; </span><span class="comment">/* first element */</span> \
+<a name="l00298"></a>00298 struct type **tqh_last; <span class="comment">/* addr of last next element */</span> \
+<a name="l00299"></a>00299 }
+<a name="l00300"></a>00300
+<a name="l00301"></a>00301 <span class="preprocessor">#define TAILQ_HEAD_INITIALIZER(head) \</span>
+<a name="l00302"></a>00302 <span class="preprocessor"> { NULL, &amp;(head).tqh_first }</span>
+<a name="l00303"></a>00303 <span class="preprocessor"></span>
+<a name="l00304"></a>00304 <span class="preprocessor">#define TAILQ_ENTRY(type) \</span>
+<a name="l00305"></a>00305 <span class="preprocessor">struct { \</span>
+<a name="l00306"></a>00306 <span class="preprocessor"> struct type *tqe_next; </span><span class="comment">/* next element */</span> \
+<a name="l00307"></a>00307 struct type **tqe_prev; <span class="comment">/* address of previous next element */</span> \
+<a name="l00308"></a>00308 }
+<a name="l00309"></a>00309
+<a name="l00310"></a>00310 <span class="comment">/* </span>
+<a name="l00311"></a>00311 <span class="comment"> * tail queue access methods </span>
+<a name="l00312"></a>00312 <span class="comment"> */</span>
+<a name="l00313"></a>00313 <span class="preprocessor">#define TAILQ_FIRST(head) ((head)-&gt;tqh_first)</span>
+<a name="l00314"></a>00314 <span class="preprocessor"></span><span class="preprocessor">#define TAILQ_END(head) NULL</span>
+<a name="l00315"></a>00315 <span class="preprocessor"></span><span class="preprocessor">#define TAILQ_NEXT(elm, field) ((elm)-&gt;field.tqe_next)</span>
+<a name="l00316"></a>00316 <span class="preprocessor"></span><span class="preprocessor">#define TAILQ_LAST(head, headname) \</span>
+<a name="l00317"></a>00317 <span class="preprocessor"> (*(((struct headname *)((head)-&gt;tqh_last))-&gt;tqh_last))</span>
+<a name="l00318"></a>00318 <span class="preprocessor"></span><span class="comment">/* XXX */</span>
+<a name="l00319"></a>00319 <span class="preprocessor">#define TAILQ_PREV(elm, headname, field) \</span>
+<a name="l00320"></a>00320 <span class="preprocessor"> (*(((struct headname *)((elm)-&gt;field.tqe_prev))-&gt;tqh_last))</span>
+<a name="l00321"></a>00321 <span class="preprocessor"></span><span class="preprocessor">#define TAILQ_EMPTY(head) \</span>
+<a name="l00322"></a>00322 <span class="preprocessor"> (TAILQ_FIRST(head) == TAILQ_END(head))</span>
+<a name="l00323"></a>00323 <span class="preprocessor"></span>
+<a name="l00324"></a>00324 <span class="preprocessor">#define TAILQ_FOREACH(var, head, field) \</span>
+<a name="l00325"></a>00325 <span class="preprocessor"> for((var) = TAILQ_FIRST(head); \</span>
+<a name="l00326"></a>00326 <span class="preprocessor"> (var) != TAILQ_END(head); \</span>
+<a name="l00327"></a>00327 <span class="preprocessor"> (var) = TAILQ_NEXT(var, field))</span>
+<a name="l00328"></a>00328 <span class="preprocessor"></span>
+<a name="l00329"></a>00329 <span class="preprocessor">#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \</span>
+<a name="l00330"></a>00330 <span class="preprocessor"> for((var) = TAILQ_LAST(head, headname); \</span>
+<a name="l00331"></a>00331 <span class="preprocessor"> (var) != TAILQ_END(head); \</span>
+<a name="l00332"></a>00332 <span class="preprocessor"> (var) = TAILQ_PREV(var, headname, field))</span>
+<a name="l00333"></a>00333 <span class="preprocessor"></span>
+<a name="l00334"></a>00334 <span class="comment">/*</span>
+<a name="l00335"></a>00335 <span class="comment"> * Tail queue functions.</span>
+<a name="l00336"></a>00336 <span class="comment"> */</span>
+<a name="l00337"></a>00337 <span class="preprocessor">#define TAILQ_INIT(head) do { \</span>
+<a name="l00338"></a>00338 <span class="preprocessor"> (head)-&gt;tqh_first = NULL; \</span>
+<a name="l00339"></a>00339 <span class="preprocessor"> (head)-&gt;tqh_last = &amp;(head)-&gt;tqh_first; \</span>
+<a name="l00340"></a>00340 <span class="preprocessor">} while (0)</span>
+<a name="l00341"></a>00341 <span class="preprocessor"></span>
+<a name="l00342"></a>00342 <span class="preprocessor">#define TAILQ_INSERT_HEAD(head, elm, field) do { \</span>
+<a name="l00343"></a>00343 <span class="preprocessor"> if (((elm)-&gt;field.tqe_next = (head)-&gt;tqh_first) != NULL) \</span>
+<a name="l00344"></a>00344 <span class="preprocessor"> (head)-&gt;tqh_first-&gt;field.tqe_prev = \</span>
+<a name="l00345"></a>00345 <span class="preprocessor"> &amp;(elm)-&gt;field.tqe_next; \</span>
+<a name="l00346"></a>00346 <span class="preprocessor"> else \</span>
+<a name="l00347"></a>00347 <span class="preprocessor"> (head)-&gt;tqh_last = &amp;(elm)-&gt;field.tqe_next; \</span>
+<a name="l00348"></a>00348 <span class="preprocessor"> (head)-&gt;tqh_first = (elm); \</span>
+<a name="l00349"></a>00349 <span class="preprocessor"> (elm)-&gt;field.tqe_prev = &amp;(head)-&gt;tqh_first; \</span>
+<a name="l00350"></a>00350 <span class="preprocessor">} while (0)</span>
+<a name="l00351"></a>00351 <span class="preprocessor"></span>
+<a name="l00352"></a>00352 <span class="preprocessor">#define TAILQ_INSERT_TAIL(head, elm, field) do { \</span>
+<a name="l00353"></a>00353 <span class="preprocessor"> (elm)-&gt;field.tqe_next = NULL; \</span>
+<a name="l00354"></a>00354 <span class="preprocessor"> (elm)-&gt;field.tqe_prev = (head)-&gt;tqh_last; \</span>
+<a name="l00355"></a>00355 <span class="preprocessor"> *(head)-&gt;tqh_last = (elm); \</span>
+<a name="l00356"></a>00356 <span class="preprocessor"> (head)-&gt;tqh_last = &amp;(elm)-&gt;field.tqe_next; \</span>
+<a name="l00357"></a>00357 <span class="preprocessor">} while (0)</span>
+<a name="l00358"></a>00358 <span class="preprocessor"></span>
+<a name="l00359"></a>00359 <span class="preprocessor">#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \</span>
+<a name="l00360"></a>00360 <span class="preprocessor"> if (((elm)-&gt;field.tqe_next = (listelm)-&gt;field.tqe_next) != NULL)\</span>
+<a name="l00361"></a>00361 <span class="preprocessor"> (elm)-&gt;field.tqe_next-&gt;field.tqe_prev = \</span>
+<a name="l00362"></a>00362 <span class="preprocessor"> &amp;(elm)-&gt;field.tqe_next; \</span>
+<a name="l00363"></a>00363 <span class="preprocessor"> else \</span>
+<a name="l00364"></a>00364 <span class="preprocessor"> (head)-&gt;tqh_last = &amp;(elm)-&gt;field.tqe_next; \</span>
+<a name="l00365"></a>00365 <span class="preprocessor"> (listelm)-&gt;field.tqe_next = (elm); \</span>
+<a name="l00366"></a>00366 <span class="preprocessor"> (elm)-&gt;field.tqe_prev = &amp;(listelm)-&gt;field.tqe_next; \</span>
+<a name="l00367"></a>00367 <span class="preprocessor">} while (0)</span>
+<a name="l00368"></a>00368 <span class="preprocessor"></span>
+<a name="l00369"></a>00369 <span class="preprocessor">#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \</span>
+<a name="l00370"></a>00370 <span class="preprocessor"> (elm)-&gt;field.tqe_prev = (listelm)-&gt;field.tqe_prev; \</span>
+<a name="l00371"></a>00371 <span class="preprocessor"> (elm)-&gt;field.tqe_next = (listelm); \</span>
+<a name="l00372"></a>00372 <span class="preprocessor"> *(listelm)-&gt;field.tqe_prev = (elm); \</span>
+<a name="l00373"></a>00373 <span class="preprocessor"> (listelm)-&gt;field.tqe_prev = &amp;(elm)-&gt;field.tqe_next; \</span>
+<a name="l00374"></a>00374 <span class="preprocessor">} while (0)</span>
+<a name="l00375"></a>00375 <span class="preprocessor"></span>
+<a name="l00376"></a>00376 <span class="preprocessor">#define TAILQ_REMOVE(head, elm, field) do { \</span>
+<a name="l00377"></a>00377 <span class="preprocessor"> if (((elm)-&gt;field.tqe_next) != NULL) \</span>
+<a name="l00378"></a>00378 <span class="preprocessor"> (elm)-&gt;field.tqe_next-&gt;field.tqe_prev = \</span>
+<a name="l00379"></a>00379 <span class="preprocessor"> (elm)-&gt;field.tqe_prev; \</span>
+<a name="l00380"></a>00380 <span class="preprocessor"> else \</span>
+<a name="l00381"></a>00381 <span class="preprocessor"> (head)-&gt;tqh_last = (elm)-&gt;field.tqe_prev; \</span>
+<a name="l00382"></a>00382 <span class="preprocessor"> *(elm)-&gt;field.tqe_prev = (elm)-&gt;field.tqe_next; \</span>
+<a name="l00383"></a>00383 <span class="preprocessor">} while (0)</span>
+<a name="l00384"></a>00384 <span class="preprocessor"></span>
+<a name="l00385"></a>00385 <span class="preprocessor">#define TAILQ_REPLACE(head, elm, elm2, field) do { \</span>
+<a name="l00386"></a>00386 <span class="preprocessor"> if (((elm2)-&gt;field.tqe_next = (elm)-&gt;field.tqe_next) != NULL) \</span>
+<a name="l00387"></a>00387 <span class="preprocessor"> (elm2)-&gt;field.tqe_next-&gt;field.tqe_prev = \</span>
+<a name="l00388"></a>00388 <span class="preprocessor"> &amp;(elm2)-&gt;field.tqe_next; \</span>
+<a name="l00389"></a>00389 <span class="preprocessor"> else \</span>
+<a name="l00390"></a>00390 <span class="preprocessor"> (head)-&gt;tqh_last = &amp;(elm2)-&gt;field.tqe_next; \</span>
+<a name="l00391"></a>00391 <span class="preprocessor"> (elm2)-&gt;field.tqe_prev = (elm)-&gt;field.tqe_prev; \</span>
+<a name="l00392"></a>00392 <span class="preprocessor"> *(elm2)-&gt;field.tqe_prev = (elm2); \</span>
+<a name="l00393"></a>00393 <span class="preprocessor">} while (0)</span>
+<a name="l00394"></a>00394 <span class="preprocessor"></span>
+<a name="l00395"></a>00395 <span class="comment">/*</span>
+<a name="l00396"></a>00396 <span class="comment"> * Circular queue definitions.</span>
+<a name="l00397"></a>00397 <span class="comment"> */</span>
+<a name="l00398"></a>00398 <span class="preprocessor">#define CIRCLEQ_HEAD(name, type) \</span>
+<a name="l00399"></a>00399 <span class="preprocessor">struct name { \</span>
+<a name="l00400"></a>00400 <span class="preprocessor"> struct type *cqh_first; </span><span class="comment">/* first element */</span> \
+<a name="l00401"></a>00401 struct type *cqh_last; <span class="comment">/* last element */</span> \
+<a name="l00402"></a>00402 }
+<a name="l00403"></a>00403
+<a name="l00404"></a>00404 <span class="preprocessor">#define CIRCLEQ_HEAD_INITIALIZER(head) \</span>
+<a name="l00405"></a>00405 <span class="preprocessor"> { CIRCLEQ_END(&amp;head), CIRCLEQ_END(&amp;head) }</span>
+<a name="l00406"></a>00406 <span class="preprocessor"></span>
+<a name="l00407"></a>00407 <span class="preprocessor">#define CIRCLEQ_ENTRY(type) \</span>
+<a name="l00408"></a>00408 <span class="preprocessor">struct { \</span>
+<a name="l00409"></a>00409 <span class="preprocessor"> struct type *cqe_next; </span><span class="comment">/* next element */</span> \
+<a name="l00410"></a>00410 struct type *cqe_prev; <span class="comment">/* previous element */</span> \
+<a name="l00411"></a>00411 }
+<a name="l00412"></a>00412
+<a name="l00413"></a>00413 <span class="comment">/*</span>
+<a name="l00414"></a>00414 <span class="comment"> * Circular queue access methods </span>
+<a name="l00415"></a>00415 <span class="comment"> */</span>
+<a name="l00416"></a>00416 <span class="preprocessor">#define CIRCLEQ_FIRST(head) ((head)-&gt;cqh_first)</span>
+<a name="l00417"></a>00417 <span class="preprocessor"></span><span class="preprocessor">#define CIRCLEQ_LAST(head) ((head)-&gt;cqh_last)</span>
+<a name="l00418"></a>00418 <span class="preprocessor"></span><span class="preprocessor">#define CIRCLEQ_END(head) ((void *)(head))</span>
+<a name="l00419"></a>00419 <span class="preprocessor"></span><span class="preprocessor">#define CIRCLEQ_NEXT(elm, field) ((elm)-&gt;field.cqe_next)</span>
+<a name="l00420"></a>00420 <span class="preprocessor"></span><span class="preprocessor">#define CIRCLEQ_PREV(elm, field) ((elm)-&gt;field.cqe_prev)</span>
+<a name="l00421"></a>00421 <span class="preprocessor"></span><span class="preprocessor">#define CIRCLEQ_EMPTY(head) \</span>
+<a name="l00422"></a>00422 <span class="preprocessor"> (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))</span>
+<a name="l00423"></a>00423 <span class="preprocessor"></span>
+<a name="l00424"></a>00424 <span class="preprocessor">#define CIRCLEQ_FOREACH(var, head, field) \</span>
+<a name="l00425"></a>00425 <span class="preprocessor"> for((var) = CIRCLEQ_FIRST(head); \</span>
+<a name="l00426"></a>00426 <span class="preprocessor"> (var) != CIRCLEQ_END(head); \</span>
+<a name="l00427"></a>00427 <span class="preprocessor"> (var) = CIRCLEQ_NEXT(var, field))</span>
+<a name="l00428"></a>00428 <span class="preprocessor"></span>
+<a name="l00429"></a>00429 <span class="preprocessor">#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \</span>
+<a name="l00430"></a>00430 <span class="preprocessor"> for((var) = CIRCLEQ_LAST(head); \</span>
+<a name="l00431"></a>00431 <span class="preprocessor"> (var) != CIRCLEQ_END(head); \</span>
+<a name="l00432"></a>00432 <span class="preprocessor"> (var) = CIRCLEQ_PREV(var, field))</span>
+<a name="l00433"></a>00433 <span class="preprocessor"></span>
+<a name="l00434"></a>00434 <span class="comment">/*</span>
+<a name="l00435"></a>00435 <span class="comment"> * Circular queue functions.</span>
+<a name="l00436"></a>00436 <span class="comment"> */</span>
+<a name="l00437"></a>00437 <span class="preprocessor">#define CIRCLEQ_INIT(head) do { \</span>
+<a name="l00438"></a>00438 <span class="preprocessor"> (head)-&gt;cqh_first = CIRCLEQ_END(head); \</span>
+<a name="l00439"></a>00439 <span class="preprocessor"> (head)-&gt;cqh_last = CIRCLEQ_END(head); \</span>
+<a name="l00440"></a>00440 <span class="preprocessor">} while (0)</span>
+<a name="l00441"></a>00441 <span class="preprocessor"></span>
+<a name="l00442"></a>00442 <span class="preprocessor">#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \</span>
+<a name="l00443"></a>00443 <span class="preprocessor"> (elm)-&gt;field.cqe_next = (listelm)-&gt;field.cqe_next; \</span>
+<a name="l00444"></a>00444 <span class="preprocessor"> (elm)-&gt;field.cqe_prev = (listelm); \</span>
+<a name="l00445"></a>00445 <span class="preprocessor"> if ((listelm)-&gt;field.cqe_next == CIRCLEQ_END(head)) \</span>
+<a name="l00446"></a>00446 <span class="preprocessor"> (head)-&gt;cqh_last = (elm); \</span>
+<a name="l00447"></a>00447 <span class="preprocessor"> else \</span>
+<a name="l00448"></a>00448 <span class="preprocessor"> (listelm)-&gt;field.cqe_next-&gt;field.cqe_prev = (elm); \</span>
+<a name="l00449"></a>00449 <span class="preprocessor"> (listelm)-&gt;field.cqe_next = (elm); \</span>
+<a name="l00450"></a>00450 <span class="preprocessor">} while (0)</span>
+<a name="l00451"></a>00451 <span class="preprocessor"></span>
+<a name="l00452"></a>00452 <span class="preprocessor">#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \</span>
+<a name="l00453"></a>00453 <span class="preprocessor"> (elm)-&gt;field.cqe_next = (listelm); \</span>
+<a name="l00454"></a>00454 <span class="preprocessor"> (elm)-&gt;field.cqe_prev = (listelm)-&gt;field.cqe_prev; \</span>
+<a name="l00455"></a>00455 <span class="preprocessor"> if ((listelm)-&gt;field.cqe_prev == CIRCLEQ_END(head)) \</span>
+<a name="l00456"></a>00456 <span class="preprocessor"> (head)-&gt;cqh_first = (elm); \</span>
+<a name="l00457"></a>00457 <span class="preprocessor"> else \</span>
+<a name="l00458"></a>00458 <span class="preprocessor"> (listelm)-&gt;field.cqe_prev-&gt;field.cqe_next = (elm); \</span>
+<a name="l00459"></a>00459 <span class="preprocessor"> (listelm)-&gt;field.cqe_prev = (elm); \</span>
+<a name="l00460"></a>00460 <span class="preprocessor">} while (0)</span>
+<a name="l00461"></a>00461 <span class="preprocessor"></span>
+<a name="l00462"></a>00462 <span class="preprocessor">#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \</span>
+<a name="l00463"></a>00463 <span class="preprocessor"> (elm)-&gt;field.cqe_next = (head)-&gt;cqh_first; \</span>
+<a name="l00464"></a>00464 <span class="preprocessor"> (elm)-&gt;field.cqe_prev = CIRCLEQ_END(head); \</span>
+<a name="l00465"></a>00465 <span class="preprocessor"> if ((head)-&gt;cqh_last == CIRCLEQ_END(head)) \</span>
+<a name="l00466"></a>00466 <span class="preprocessor"> (head)-&gt;cqh_last = (elm); \</span>
+<a name="l00467"></a>00467 <span class="preprocessor"> else \</span>
+<a name="l00468"></a>00468 <span class="preprocessor"> (head)-&gt;cqh_first-&gt;field.cqe_prev = (elm); \</span>
+<a name="l00469"></a>00469 <span class="preprocessor"> (head)-&gt;cqh_first = (elm); \</span>
+<a name="l00470"></a>00470 <span class="preprocessor">} while (0)</span>
+<a name="l00471"></a>00471 <span class="preprocessor"></span>
+<a name="l00472"></a>00472 <span class="preprocessor">#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \</span>
+<a name="l00473"></a>00473 <span class="preprocessor"> (elm)-&gt;field.cqe_next = CIRCLEQ_END(head); \</span>
+<a name="l00474"></a>00474 <span class="preprocessor"> (elm)-&gt;field.cqe_prev = (head)-&gt;cqh_last; \</span>
+<a name="l00475"></a>00475 <span class="preprocessor"> if ((head)-&gt;cqh_first == CIRCLEQ_END(head)) \</span>
+<a name="l00476"></a>00476 <span class="preprocessor"> (head)-&gt;cqh_first = (elm); \</span>
+<a name="l00477"></a>00477 <span class="preprocessor"> else \</span>
+<a name="l00478"></a>00478 <span class="preprocessor"> (head)-&gt;cqh_last-&gt;field.cqe_next = (elm); \</span>
+<a name="l00479"></a>00479 <span class="preprocessor"> (head)-&gt;cqh_last = (elm); \</span>
+<a name="l00480"></a>00480 <span class="preprocessor">} while (0)</span>
+<a name="l00481"></a>00481 <span class="preprocessor"></span>
+<a name="l00482"></a>00482 <span class="preprocessor">#define CIRCLEQ_REMOVE(head, elm, field) do { \</span>
+<a name="l00483"></a>00483 <span class="preprocessor"> if ((elm)-&gt;field.cqe_next == CIRCLEQ_END(head)) \</span>
+<a name="l00484"></a>00484 <span class="preprocessor"> (head)-&gt;cqh_last = (elm)-&gt;field.cqe_prev; \</span>
+<a name="l00485"></a>00485 <span class="preprocessor"> else \</span>
+<a name="l00486"></a>00486 <span class="preprocessor"> (elm)-&gt;field.cqe_next-&gt;field.cqe_prev = \</span>
+<a name="l00487"></a>00487 <span class="preprocessor"> (elm)-&gt;field.cqe_prev; \</span>
+<a name="l00488"></a>00488 <span class="preprocessor"> if ((elm)-&gt;field.cqe_prev == CIRCLEQ_END(head)) \</span>
+<a name="l00489"></a>00489 <span class="preprocessor"> (head)-&gt;cqh_first = (elm)-&gt;field.cqe_next; \</span>
+<a name="l00490"></a>00490 <span class="preprocessor"> else \</span>
+<a name="l00491"></a>00491 <span class="preprocessor"> (elm)-&gt;field.cqe_prev-&gt;field.cqe_next = \</span>
+<a name="l00492"></a>00492 <span class="preprocessor"> (elm)-&gt;field.cqe_next; \</span>
+<a name="l00493"></a>00493 <span class="preprocessor">} while (0)</span>
+<a name="l00494"></a>00494 <span class="preprocessor"></span>
+<a name="l00495"></a>00495 <span class="preprocessor">#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \</span>
+<a name="l00496"></a>00496 <span class="preprocessor"> if (((elm2)-&gt;field.cqe_next = (elm)-&gt;field.cqe_next) == \</span>
+<a name="l00497"></a>00497 <span class="preprocessor"> CIRCLEQ_END(head)) \</span>
+<a name="l00498"></a>00498 <span class="preprocessor"> (head).cqh_last = (elm2); \</span>
+<a name="l00499"></a>00499 <span class="preprocessor"> else \</span>
+<a name="l00500"></a>00500 <span class="preprocessor"> (elm2)-&gt;field.cqe_next-&gt;field.cqe_prev = (elm2); \</span>
+<a name="l00501"></a>00501 <span class="preprocessor"> if (((elm2)-&gt;field.cqe_prev = (elm)-&gt;field.cqe_prev) == \</span>
+<a name="l00502"></a>00502 <span class="preprocessor"> CIRCLEQ_END(head)) \</span>
+<a name="l00503"></a>00503 <span class="preprocessor"> (head).cqh_first = (elm2); \</span>
+<a name="l00504"></a>00504 <span class="preprocessor"> else \</span>
+<a name="l00505"></a>00505 <span class="preprocessor"> (elm2)-&gt;field.cqe_prev-&gt;field.cqe_next = (elm2); \</span>
+<a name="l00506"></a>00506 <span class="preprocessor">} while (0)</span>
+<a name="l00507"></a>00507 <span class="preprocessor"></span>
+<a name="l00508"></a>00508 <span class="preprocessor">#endif </span><span class="comment">/* !_SYS_QUEUE_H_ */</span>
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/mm__util_8c.html b/main/minimime/mm-docs/html/mm__util_8c.html
new file mode 100644
index 000000000..780feb796
--- /dev/null
+++ b/main/minimime/mm-docs/html/mm__util_8c.html
@@ -0,0 +1,58 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: mm_util.c File Reference</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>mm_util.c File Reference</h1><code>#include &lt;stdio.h&gt;</code><br>
+<code>#include &lt;stdlib.h&gt;</code><br>
+<code>#include &lt;string.h&gt;</code><br>
+<code>#include &lt;time.h&gt;</code><br>
+<code>#include &lt;assert.h&gt;</code><br>
+<code>#include &quot;<a class="el" href="mm__internal_8h-source.html">mm_internal.h</a>&quot;</code><br>
+<table border="0" cellpadding="0" cellspacing="0">
+<tr><td></td></tr>
+<tr><td colspan="2"><br><h2>Functions</h2></td></tr>
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__util.html#g2ff4ef58da7e543466e75f20f2a2d8b7">xmalloc</a> (size_t size)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">void *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__util.html#ge14637b4672461f1f0bee822406d68dc">xrealloc</a> (void *p, size_t size)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="700bf3013e33311eacdd1f20d13bdc9a"></a><!-- doxytag: member="mm_util.c::xstrdup" ref="700bf3013e33311eacdd1f20d13bdc9a" args="(const char *str)" -->
+char *&nbsp;</td><td class="memItemRight" valign="bottom"><b>xstrdup</b> (const char *str)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="91fc771d8aa78ca2ac43244c491da52d"></a><!-- doxytag: member="mm_util.c::xfree" ref="91fc771d8aa78ca2ac43244c491da52d" args="(void *p)" -->
+void&nbsp;</td><td class="memItemRight" valign="bottom"><b>xfree</b> (void *p)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__util.html#gf0f89a29a634f6f1f833abb1e214a6b1">mm_unquote</a> (const char *string)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__util.html#g49c016ff4cfd02f1b019c4dce5aac357">mm_uncomment</a> (const char *string)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__util.html#g3ae25483c8a42f6562f2a916a511228f">xstrsep</a> (char **stringp, const char *delim)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__util.html#gf62be7dd21e545f8db72f3c9e3b6a3c3">mm_stripchars</a> (char *input, char *strip)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top">char *&nbsp;</td><td class="memItemRight" valign="bottom"><a class="el" href="group__util.html#g0747d4b4e33644263e6d73d2d8d4818b">mm_addchars</a> (char *input, char *add, u_int16_t linelength)</td></tr>
+
+<tr><td class="memItemLeft" nowrap align="right" valign="top"><a class="anchor" name="a965d3d1c625253beffd53051b38548e"></a><!-- doxytag: member="mm_util.c::mm_striptrailing" ref="a965d3d1c625253beffd53051b38548e" args="(char **what, const char *charset)" -->
+void&nbsp;</td><td class="memItemRight" valign="bottom"><b>mm_striptrailing</b> (char **what, const char *charset)</td></tr>
+
+</table>
+<hr><a name="_details"></a><h2>Detailed Description</h2>
+This module contains utility functions for the MiniMIME library <hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/mm__util_8h-source.html b/main/minimime/mm-docs/html/mm__util_8h-source.html
new file mode 100644
index 000000000..88dc9be5f
--- /dev/null
+++ b/main/minimime/mm-docs/html/mm__util_8h-source.html
@@ -0,0 +1,74 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: mm_util.h Source File</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li id="current"><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<div class="tabs">
+ <ul>
+ <li><a href="files.html"><span>File&nbsp;List</span></a></li>
+ <li><a href="globals.html"><span>Globals</span></a></li>
+ </ul></div>
+<h1>mm_util.h</h1><div class="fragment"><pre class="fragment"><a name="l00001"></a>00001 <span class="comment">/*</span>
+<a name="l00002"></a>00002 <span class="comment"> * $Id$</span>
+<a name="l00003"></a>00003 <span class="comment"> *</span>
+<a name="l00004"></a>00004 <span class="comment"> * MiniMIME - a library for handling MIME messages</span>
+<a name="l00005"></a>00005 <span class="comment"> *</span>
+<a name="l00006"></a>00006 <span class="comment"> * Copyright (C) 2003 Jann Fischer &lt;rezine@mistrust.net&gt;</span>
+<a name="l00007"></a>00007 <span class="comment"> * All rights reserved.</span>
+<a name="l00008"></a>00008 <span class="comment"> *</span>
+<a name="l00009"></a>00009 <span class="comment"> * Redistribution and use in source and binary forms, with or without</span>
+<a name="l00010"></a>00010 <span class="comment"> * modification, are permitted provided that the following conditions</span>
+<a name="l00011"></a>00011 <span class="comment"> * are met:</span>
+<a name="l00012"></a>00012 <span class="comment"> *</span>
+<a name="l00013"></a>00013 <span class="comment"> * 1. Redistributions of source code must retain the above copyright</span>
+<a name="l00014"></a>00014 <span class="comment"> * notice, this list of conditions and the following disclaimer.</span>
+<a name="l00015"></a>00015 <span class="comment"> * 2. Redistributions in binary form must reproduce the above copyright</span>
+<a name="l00016"></a>00016 <span class="comment"> * notice, this list of conditions and the following disclaimer in the</span>
+<a name="l00017"></a>00017 <span class="comment"> * documentation and/or other materials provided with the distribution.</span>
+<a name="l00018"></a>00018 <span class="comment"> *</span>
+<a name="l00019"></a>00019 <span class="comment"> * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND</span>
+<a name="l00020"></a>00020 <span class="comment"> * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE</span>
+<a name="l00021"></a>00021 <span class="comment"> * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE</span>
+<a name="l00022"></a>00022 <span class="comment"> * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD</span>
+<a name="l00023"></a>00023 <span class="comment"> * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR</span>
+<a name="l00024"></a>00024 <span class="comment"> * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF</span>
+<a name="l00025"></a>00025 <span class="comment"> * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS</span>
+<a name="l00026"></a>00026 <span class="comment"> * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN</span>
+<a name="l00027"></a>00027 <span class="comment"> * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)</span>
+<a name="l00028"></a>00028 <span class="comment"> * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF</span>
+<a name="l00029"></a>00029 <span class="comment"> * THE POSSIBILITY OF SUCH DAMAGE.</span>
+<a name="l00030"></a>00030 <span class="comment"> */</span>
+<a name="l00031"></a>00031 <span class="preprocessor">#ifndef __MM_UTIL_H</span>
+<a name="l00032"></a>00032 <span class="preprocessor"></span><span class="preprocessor">#define __MM_UTIL_H</span>
+<a name="l00033"></a>00033 <span class="preprocessor"></span>
+<a name="l00034"></a>00034 <span class="preprocessor">#define STRIP_TRAILING(str, charset) do { \</span>
+<a name="l00035"></a>00035 <span class="preprocessor"> size_t eos, i, hit; \</span>
+<a name="l00036"></a>00036 <span class="preprocessor"> for (eos = strlen(str); eos &gt; 0; eos--) { \</span>
+<a name="l00037"></a>00037 <span class="preprocessor"> hit = 0; \</span>
+<a name="l00038"></a>00038 <span class="preprocessor"> for (i = 0; i &lt;= strlen(charset); i++) { \</span>
+<a name="l00039"></a>00039 <span class="preprocessor"> if (str[eos] == charset[i]) {\</span>
+<a name="l00040"></a>00040 <span class="preprocessor"> str[eos] = '\0'; \</span>
+<a name="l00041"></a>00041 <span class="preprocessor"> hit = 1; \</span>
+<a name="l00042"></a>00042 <span class="preprocessor"> break; \</span>
+<a name="l00043"></a>00043 <span class="preprocessor"> } \</span>
+<a name="l00044"></a>00044 <span class="preprocessor"> } \</span>
+<a name="l00045"></a>00045 <span class="preprocessor"> if (!hit) \</span>
+<a name="l00046"></a>00046 <span class="preprocessor"> break; \</span>
+<a name="l00047"></a>00047 <span class="preprocessor"> } \</span>
+<a name="l00048"></a>00048 <span class="preprocessor">} while (0);</span>
+<a name="l00049"></a>00049 <span class="preprocessor"></span>
+<a name="l00050"></a>00050 <span class="preprocessor">#endif </span><span class="comment">/* ! __MM_UTIL_H */</span>
+</pre></div><hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:08 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/modules.html b/main/minimime/mm-docs/html/modules.html
new file mode 100644
index 000000000..505732527
--- /dev/null
+++ b/main/minimime/mm-docs/html/modules.html
@@ -0,0 +1,30 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: Module Index</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li id="current"><a href="modules.html"><span>Modules</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ <li><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<h1>MiniMIME Modules</h1>Here is a list of all modules:<ul>
+<li><a class="el" href="group__codecs.html">Manipulating MiniMIME codecs</a>
+<li><a class="el" href="group__contenttype.html">Accessing and manipulating Content-Type objects</a>
+<li><a class="el" href="group__context.html">Accessing and manipulating MIME contexts</a>
+<li><a class="el" href="group__envelope.html">Accessing and manipulating a message's envelope</a>
+<li><a class="el" href="group__error.html">MiniMIME error functions</a>
+<li><a class="el" href="group__mimepart.html">Accessing and manipulating MIME parts</a>
+<li><a class="el" href="group__mimeutil.html">MIME related utility functions</a>
+<li><a class="el" href="group__param.html">Accessing and manipulating MIME parameters</a>
+<li><a class="el" href="group__util.html">General purpose utility functions</a>
+</ul>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:09 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/pages.html b/main/minimime/mm-docs/html/pages.html
new file mode 100644
index 000000000..362d4af9b
--- /dev/null
+++ b/main/minimime/mm-docs/html/pages.html
@@ -0,0 +1,23 @@
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
+<html><head><meta http-equiv="Content-Type" content="text/html;charset=iso-8859-1">
+<title>MiniMIME: Page Index</title>
+<link href="doxygen.css" rel="stylesheet" type="text/css">
+<link href="tabs.css" rel="stylesheet" type="text/css">
+</head><body>
+<!-- Generated by Doxygen 1.5.1 -->
+<div class="tabs">
+ <ul>
+ <li><a href="index.html"><span>Main&nbsp;Page</span></a></li>
+ <li><a href="modules.html"><span>Modules</span></a></li>
+ <li><a href="files.html"><span>Files</span></a></li>
+ <li id="current"><a href="pages.html"><span>Related&nbsp;Pages</span></a></li>
+ </ul></div>
+<h1>MiniMIME Related Pages</h1>Here is a list of all related documentation pages:<ul>
+<li><a class="el" href="bug.html">Bug List</a>
+
+</ul>
+<hr size="1"><address style="align: right;"><small>Generated on Thu Mar 29 17:59:09 2007 for MiniMIME by&nbsp;
+<a href="http://www.doxygen.org/index.html">
+<img src="doxygen.png" alt="doxygen" align="middle" border="0"></a> 1.5.1 </small></address>
+</body>
+</html>
diff --git a/main/minimime/mm-docs/html/tabs.css b/main/minimime/mm-docs/html/tabs.css
new file mode 100644
index 000000000..a61552a67
--- /dev/null
+++ b/main/minimime/mm-docs/html/tabs.css
@@ -0,0 +1,102 @@
+/* tabs styles, based on http://www.alistapart.com/articles/slidingdoors */
+
+DIV.tabs
+{
+ float : left;
+ width : 100%;
+ background : url("tab_b.gif") repeat-x bottom;
+ margin-bottom : 4px;
+}
+
+DIV.tabs UL
+{
+ margin : 0px;
+ padding-left : 10px;
+ list-style : none;
+}
+
+DIV.tabs LI, DIV.tabs FORM
+{
+ display : inline;
+ margin : 0px;
+ padding : 0px;
+}
+
+DIV.tabs FORM
+{
+ float : right;
+}
+
+DIV.tabs A
+{
+ float : left;
+ background : url("tab_r.gif") no-repeat right top;
+ border-bottom : 1px solid #84B0C7;
+ font-size : x-small;
+ font-weight : bold;
+ text-decoration : none;
+}
+
+DIV.tabs A:hover
+{
+ background-position: 100% -150px;
+}
+
+DIV.tabs A:link, DIV.tabs A:visited,
+DIV.tabs A:active, DIV.tabs A:hover
+{
+ color: #1A419D;
+}
+
+DIV.tabs SPAN
+{
+ float : left;
+ display : block;
+ background : url("tab_l.gif") no-repeat left top;
+ padding : 5px 9px;
+ white-space : nowrap;
+}
+
+DIV.tabs INPUT
+{
+ float : right;
+ display : inline;
+ font-size : 1em;
+}
+
+DIV.tabs TD
+{
+ font-size : x-small;
+ font-weight : bold;
+ text-decoration : none;
+}
+
+
+
+/* Commented Backslash Hack hides rule from IE5-Mac \*/
+DIV.tabs SPAN {float : none;}
+/* End IE5-Mac hack */
+
+DIV.tabs A:hover SPAN
+{
+ background-position: 0% -150px;
+}
+
+DIV.tabs LI#current A
+{
+ background-position: 100% -150px;
+ border-width : 0px;
+}
+
+DIV.tabs LI#current SPAN
+{
+ background-position: 0% -150px;
+ padding-bottom : 6px;
+}
+
+DIV.nav
+{
+ background : none;
+ border : none;
+ border-bottom : 1px solid #84B0C7;
+}
diff --git a/main/minimime/mm-docs/latex/Makefile b/main/minimime/mm-docs/latex/Makefile
new file mode 100644
index 000000000..776fcf968
--- /dev/null
+++ b/main/minimime/mm-docs/latex/Makefile
@@ -0,0 +1,39 @@
+all: clean refman.dvi
+
+ps: refman.ps
+
+pdf: refman.pdf
+
+ps_2on1: refman_2on1.ps
+
+pdf_2on1: refman_2on1.pdf
+
+refman.ps: refman.dvi
+ dvips -o refman.ps refman.dvi
+
+refman.pdf: refman.ps
+ ps2pdf refman.ps refman.pdf
+
+refman.dvi: refman.tex doxygen.sty
+ echo "Running latex..."
+ latex refman.tex
+ echo "Running makeindex..."
+ makeindex refman.idx
+ echo "Rerunning latex...."
+ latex refman.tex
+ latex_count=5 ; \
+ while egrep -s 'Rerun (LaTeX|to get cross-references right)' refman.log && [ $$latex_count -gt 0 ] ;\
+ do \
+ echo "Rerunning latex...." ;\
+ latex refman.tex ;\
+ latex_count=`expr $$latex_count - 1` ;\
+ done
+
+refman_2on1.ps: refman.ps
+ psnup -2 refman.ps >refman_2on1.ps
+
+refman_2on1.pdf: refman_2on1.ps
+ ps2pdf refman_2on1.ps refman_2on1.pdf
+
+clean:
+ rm -f *.ps *.dvi *.aux *.toc *.idx *.ind *.ilg *.log *.out refman.pdf
diff --git a/main/minimime/mm-docs/latex/bug.tex b/main/minimime/mm-docs/latex/bug.tex
new file mode 100644
index 000000000..0850a8f78
--- /dev/null
+++ b/main/minimime/mm-docs/latex/bug.tex
@@ -0,0 +1,9 @@
+\section{Bug List}\label{bug}
+\label{bug__bug000001}
+ \begin{description}
+\item[Global \doxyref{mm\_\-content\_\-setmaintype}{p.}{group__contenttype_g7bab273d117c6c0cacad20361d8fb1c8} ]The xfree() call could lead to undesirable results. Do we really need it? \end{description}
+
+
+\label{bug__bug000002}
+ \begin{description}
+\item[Global \doxyref{mm\_\-content\_\-setsubtype}{p.}{group__contenttype_g14b0738410d566ad2312405946f22212} ]The xfree() call could lead to undesirable results. Do we really need it? \end{description}
diff --git a/main/minimime/mm-docs/latex/doxygen.sty b/main/minimime/mm-docs/latex/doxygen.sty
new file mode 100644
index 000000000..37e398292
--- /dev/null
+++ b/main/minimime/mm-docs/latex/doxygen.sty
@@ -0,0 +1,78 @@
+\NeedsTeXFormat{LaTeX2e}
+\ProvidesPackage{doxygen}
+\RequirePackage{calc}
+\RequirePackage{array}
+\pagestyle{fancyplain}
+\newcommand{\clearemptydoublepage}{\newpage{\pagestyle{empty}\cleardoublepage}}
+\renewcommand{\chaptermark}[1]{\markboth{#1}{}}
+\renewcommand{\sectionmark}[1]{\markright{\thesection\ #1}}
+\lhead[\fancyplain{}{\bfseries\thepage}]
+ {\fancyplain{}{\bfseries\rightmark}}
+\rhead[\fancyplain{}{\bfseries\leftmark}]
+ {\fancyplain{}{\bfseries\thepage}}
+\rfoot[\fancyplain{}{\bfseries\scriptsize Generated on Thu Mar 29 17:59:08 2007 for Mini\-MIME by Doxygen }]{}
+\lfoot[]{\fancyplain{}{\bfseries\scriptsize Generated on Thu Mar 29 17:59:08 2007 for Mini\-MIME by Doxygen }}
+\cfoot{}
+\newenvironment{Code}
+{\footnotesize}
+{\normalsize}
+\newcommand{\doxyref}[3]{\textbf{#1} (\textnormal{#2}\,\pageref{#3})}
+\newenvironment{DocInclude}
+{\footnotesize}
+{\normalsize}
+\newenvironment{VerbInclude}
+{\footnotesize}
+{\normalsize}
+\newenvironment{Image}
+{\begin{figure}[H]}
+{\end{figure}}
+\newenvironment{ImageNoCaption}{}{}
+\newenvironment{CompactList}
+{\begin{list}{}{
+ \setlength{\leftmargin}{0.5cm}
+ \setlength{\itemsep}{0pt}
+ \setlength{\parsep}{0pt}
+ \setlength{\topsep}{0pt}
+ \renewcommand{\makelabel}{\hfill}}}
+{\end{list}}
+\newenvironment{CompactItemize}
+{
+ \begin{itemize}
+ \setlength{\itemsep}{-3pt}
+ \setlength{\parsep}{0pt}
+ \setlength{\topsep}{0pt}
+ \setlength{\partopsep}{0pt}
+}
+{\end{itemize}}
+\newcommand{\PBS}[1]{\let\temp=\\#1\let\\=\temp}
+\newlength{\tmplength}
+\newenvironment{TabularC}[1]
+{
+\setlength{\tmplength}
+ {\linewidth/(#1)-\tabcolsep*2-\arrayrulewidth*(#1+1)/(#1)}
+ \par\begin{tabular*}{\linewidth}
+ {*{#1}{|>{\PBS\raggedright\hspace{0pt}}p{\the\tmplength}}|}
+}
+{\end{tabular*}\par}
+\newcommand{\entrylabel}[1]{
+ {\parbox[b]{\labelwidth-4pt}{\makebox[0pt][l]{\textbf{#1}}\vspace{1.5\baselineskip}}}}
+\newenvironment{Desc}
+{\begin{list}{}
+ {
+ \settowidth{\labelwidth}{40pt}
+ \setlength{\leftmargin}{\labelwidth}
+ \setlength{\parsep}{0pt}
+ \setlength{\itemsep}{-4pt}
+ \renewcommand{\makelabel}{\entrylabel}
+ }
+}
+{\end{list}}
+\newenvironment{Indent}
+ {\begin{list}{}{\setlength{\leftmargin}{0.5cm}}
+ \item[]\ignorespaces}
+ {\unskip\end{list}}
+\setlength{\parindent}{0cm}
+\setlength{\parskip}{0.2cm}
+\addtocounter{secnumdepth}{1}
+\sloppy
+\usepackage[T1]{fontenc}
diff --git a/main/minimime/mm-docs/latex/files.tex b/main/minimime/mm-docs/latex/files.tex
new file mode 100644
index 000000000..fd49692db
--- /dev/null
+++ b/main/minimime/mm-docs/latex/files.tex
@@ -0,0 +1,21 @@
+\section{Mini\-MIME File List}
+Here is a list of all documented files with brief descriptions:\begin{CompactList}
+\item\contentsline{section}{\textbf{mimeparser.h} }{\pageref{mimeparser_8h}}{}
+\item\contentsline{section}{\textbf{mimeparser.tab.h} }{\pageref{mimeparser_8tab_8h}}{}
+\item\contentsline{section}{\textbf{mm.h} }{\pageref{mm_8h}}{}
+\item\contentsline{section}{{\bf mm\_\-codecs.c} }{\pageref{mm__codecs_8c}}{}
+\item\contentsline{section}{{\bf mm\_\-contenttype.c} }{\pageref{mm__contenttype_8c}}{}
+\item\contentsline{section}{{\bf mm\_\-context.c} }{\pageref{mm__context_8c}}{}
+\item\contentsline{section}{{\bf mm\_\-envelope.c} }{\pageref{mm__envelope_8c}}{}
+\item\contentsline{section}{{\bf mm\_\-error.c} }{\pageref{mm__error_8c}}{}
+\item\contentsline{section}{{\bf mm\_\-header.c} }{\pageref{mm__header_8c}}{}
+\item\contentsline{section}{{\bf mm\_\-internal.h} }{\pageref{mm__internal_8h}}{}
+\item\contentsline{section}{\textbf{mm\_\-mem.h} }{\pageref{mm__mem_8h}}{}
+\item\contentsline{section}{{\bf mm\_\-mimepart.c} }{\pageref{mm__mimepart_8c}}{}
+\item\contentsline{section}{{\bf mm\_\-mimeutil.c} }{\pageref{mm__mimeutil_8c}}{}
+\item\contentsline{section}{{\bf mm\_\-param.c} }{\pageref{mm__param_8c}}{}
+\item\contentsline{section}{{\bf mm\_\-parse.c} }{\pageref{mm__parse_8c}}{}
+\item\contentsline{section}{\textbf{mm\_\-queue.h} }{\pageref{mm__queue_8h}}{}
+\item\contentsline{section}{{\bf mm\_\-util.c} }{\pageref{mm__util_8c}}{}
+\item\contentsline{section}{\textbf{mm\_\-util.h} }{\pageref{mm__util_8h}}{}
+\end{CompactList}
diff --git a/main/minimime/mm-docs/latex/group__codecs.tex b/main/minimime/mm-docs/latex/group__codecs.tex
new file mode 100644
index 000000000..33c15f6d9
--- /dev/null
+++ b/main/minimime/mm-docs/latex/group__codecs.tex
@@ -0,0 +1,119 @@
+\section{Manipulating Mini\-MIME codecs}
+\label{group__codecs}\index{Manipulating MiniMIME codecs@{Manipulating MiniMIME codecs}}
+\subsection*{Codec manipulation}
+\begin{CompactItemize}
+\item
+int {\bf mm\_\-codec\_\-hasdecoder} (const char $\ast$encoding)
+\item
+int {\bf mm\_\-codec\_\-hasencoder} (const char $\ast$encoding)
+\item
+int {\bf mm\_\-codec\_\-isregistered} (const char $\ast$encoding)
+\item
+int {\bf mm\_\-codec\_\-register} (const char $\ast$encoding, char $\ast$($\ast$encoder)(char $\ast$data, u\_\-int32\_\-t i), char $\ast$($\ast$decoder)(char $\ast$data))
+\item
+int {\bf mm\_\-codec\_\-unregister} (const char $\ast$encoding)
+\item
+int {\bf mm\_\-codec\_\-unregisterall} (void)
+\item
+void {\bf mm\_\-codec\_\-registerdefaultcodecs} (void)
+\end{CompactItemize}
+
+
+\subsection{Function Documentation}
+\index{codecs@{codecs}!mm_codec_hasdecoder@{mm\_\-codec\_\-hasdecoder}}
+\index{mm_codec_hasdecoder@{mm\_\-codec\_\-hasdecoder}!codecs@{codecs}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-codec\_\-hasdecoder (const char $\ast$ {\em encoding})}\label{group__codecs_g6ccb0f7a1d7c870dc3dae04f31d6ccca}
+
+
+Looks up whether a context has an decoder installed for a given encoding
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em encoding}]The encoding specifier to look up \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]1 if a decoder is installed or 0 if not \end{Desc}
+\index{codecs@{codecs}!mm_codec_hasencoder@{mm\_\-codec\_\-hasencoder}}
+\index{mm_codec_hasencoder@{mm\_\-codec\_\-hasencoder}!codecs@{codecs}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-codec\_\-hasencoder (const char $\ast$ {\em encoding})}\label{group__codecs_g50ff257b794ceaec7aedf9ae18bfcc57}
+
+
+Looks up whether a context has an encoder installed for a given encoding
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ctx}]A valid MIME context \item[{\em encoding}]The encoding specifier to look up \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]1 if an encoder is installed or 0 if not \end{Desc}
+\index{codecs@{codecs}!mm_codec_isregistered@{mm\_\-codec\_\-isregistered}}
+\index{mm_codec_isregistered@{mm\_\-codec\_\-isregistered}!codecs@{codecs}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-codec\_\-isregistered (const char $\ast$ {\em encoding})}\label{group__codecs_g9e19f6343128fd7e4ec57c3d55049b55}
+
+
+Looks up whether a codec for a given encoding is installed to a context
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em encoding}]The encoding specifier to look up \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]1 if a codec was found or 0 if not \end{Desc}
+\index{codecs@{codecs}!mm_codec_register@{mm\_\-codec\_\-register}}
+\index{mm_codec_register@{mm\_\-codec\_\-register}!codecs@{codecs}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-codec\_\-register (const char $\ast$ {\em encoding}, char $\ast$($\ast$)(char $\ast$data, u\_\-int32\_\-t i) {\em encoder}, char $\ast$($\ast$)(char $\ast$data) {\em decoder})}\label{group__codecs_gf97a7311c909888ed9f6f14d6f1bf397}
+
+
+Registers a codec with the Mini\-MIME library
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em encoding}]The encoding specifier for which to register the codec \item[{\em encoder}]The encoder function for this encoding \item[{\em decoder}]The decoder function for this encoding \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]1 if successfull or 0 if not\end{Desc}
+This function registers a codec for a given Mini\-MIME context. The codec may provide an decoder, an encoder or both (but not none). If there is a codec already installed for this encoding, the function will puke. \index{codecs@{codecs}!mm_codec_registerdefaultcodecs@{mm\_\-codec\_\-registerdefaultcodecs}}
+\index{mm_codec_registerdefaultcodecs@{mm\_\-codec\_\-registerdefaultcodecs}!codecs@{codecs}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}void mm\_\-codec\_\-registerdefaultcodecs (void)}\label{group__codecs_gf39e72460fb85f5ca41f6e270a68aacc}
+
+
+Registers the default codecs to a Mini\-MIME context
+
+This functions registers the codecs for the following encodings to a Mini\-MIME context:
+
+\begin{itemize}
+\item Base64\item (TODO:) Quoted-Printable \end{itemize}
+\index{codecs@{codecs}!mm_codec_unregister@{mm\_\-codec\_\-unregister}}
+\index{mm_codec_unregister@{mm\_\-codec\_\-unregister}!codecs@{codecs}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-codec\_\-unregister (const char $\ast$ {\em encoding})}\label{group__codecs_g0c71696bc70f834386193e3c7a0e2ca4}
+
+
+Unregisters a Mini\-MIME codec
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em encoding}]The encoding specifier which to unregister \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]0 if unregistered successfully, or -1 if there was no such codec \end{Desc}
+\index{codecs@{codecs}!mm_codec_unregisterall@{mm\_\-codec\_\-unregisterall}}
+\index{mm_codec_unregisterall@{mm\_\-codec\_\-unregisterall}!codecs@{codecs}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-codec\_\-unregisterall (void)}\label{group__codecs_g7c9e6538f84c368be2b56a3c9ba702be}
+
+
+Unregisters all codecs within a context
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ctx}]A valid Mini\-MIME context \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]0 if all codecs were unregistered successfully or -1 if an error occured. \end{Desc}
+\begin{Desc}
+\item[Note:]Foobar \end{Desc}
diff --git a/main/minimime/mm-docs/latex/group__contenttype.tex b/main/minimime/mm-docs/latex/group__contenttype.tex
new file mode 100644
index 000000000..166261a62
--- /dev/null
+++ b/main/minimime/mm-docs/latex/group__contenttype.tex
@@ -0,0 +1,246 @@
+\section{Accessing and manipulating Content-Type objects}
+\label{group__contenttype}\index{Accessing and manipulating Content-Type objects@{Accessing and manipulating Content-Type objects}}
+\subsection*{Functions for manipulating Content-Type objects}
+\begin{CompactItemize}
+\item
+mm\_\-content $\ast$ {\bf mm\_\-content\_\-new} (void)
+\item
+void {\bf mm\_\-content\_\-free} (struct mm\_\-content $\ast$ct)
+\item
+int {\bf mm\_\-content\_\-attachparam} (struct mm\_\-content $\ast$ct, struct mm\_\-param $\ast$param)
+\item
+char $\ast$ {\bf mm\_\-content\_\-getparambyname} (struct mm\_\-content $\ast$ct, const char $\ast$name)
+\item
+mm\_\-param $\ast$ \textbf{mm\_\-content\_\-getparamobjbyname} (struct mm\_\-content $\ast$ct, const char $\ast$name)\label{group__contenttype_g1ba63e679d2b49aceb6cfec8a6752581}
+
+\item
+int {\bf mm\_\-content\_\-setmaintype} (struct mm\_\-content $\ast$ct, char $\ast$value, int copy)
+\item
+char $\ast$ {\bf mm\_\-content\_\-getmaintype} (struct mm\_\-content $\ast$ct)
+\item
+char $\ast$ {\bf mm\_\-content\_\-getsubtype} (struct mm\_\-content $\ast$ct)
+\item
+char $\ast$ \textbf{mm\_\-content\_\-gettype} (struct mm\_\-content $\ast$ct)\label{group__contenttype_ga6d8453eb35bd695c4944e53b7040b65}
+
+\item
+int {\bf mm\_\-content\_\-setsubtype} (struct mm\_\-content $\ast$ct, char $\ast$value, int copy)
+\item
+int \textbf{mm\_\-content\_\-settype} (struct mm\_\-content $\ast$ct, const char $\ast$fmt,...)\label{group__contenttype_g878686678ea2ba97aa8edb1206a564d8}
+
+\item
+int {\bf mm\_\-content\_\-iscomposite} (struct mm\_\-content $\ast$ct)
+\item
+int {\bf mm\_\-content\_\-isvalidencoding} (const char $\ast$encoding)
+\item
+int {\bf mm\_\-content\_\-setencoding} (struct mm\_\-content $\ast$ct, const char $\ast$encoding)
+\item
+int {\bf mm\_\-content\_\-getencoding} (struct mm\_\-content $\ast$ct, const char $\ast$encoding)
+\item
+char $\ast$ {\bf mm\_\-content\_\-paramstostring} (struct mm\_\-content $\ast$ct)
+\item
+char $\ast$ {\bf mm\_\-content\_\-tostring} (struct mm\_\-content $\ast$ct)
+\end{CompactItemize}
+\subsection*{Variables}
+\begin{CompactItemize}
+\item
+int \textbf{mm\_\-encoding\_\-mappings::type}\label{group__contenttype_g6c458a8611981109bf0519b5ae21e12e}
+
+\end{CompactItemize}
+
+
+\subsection{Function Documentation}
+\index{contenttype@{contenttype}!mm_content_attachparam@{mm\_\-content\_\-attachparam}}
+\index{mm_content_attachparam@{mm\_\-content\_\-attachparam}!contenttype@{contenttype}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-content\_\-attachparam (struct mm\_\-content $\ast$ {\em ct}, struct mm\_\-param $\ast$ {\em param})}\label{group__contenttype_g080b7ed798ed497dcd635a6bab86962f}
+
+
+Attaches a parameter to a Content-Type object
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ct}]The target Content-Type object \item[{\em param}]The Content-Type parameter which to attach \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]0 on success and -1 on failure \end{Desc}
+\index{contenttype@{contenttype}!mm_content_free@{mm\_\-content\_\-free}}
+\index{mm_content_free@{mm\_\-content\_\-free}!contenttype@{contenttype}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}void mm\_\-content\_\-free (struct mm\_\-content $\ast$ {\em ct})}\label{group__contenttype_g404314481125849bce869ee4b0f647af}
+
+
+Releases all memory associated with an Content-Type object
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ct}]A Content-Type object \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]Nothing \end{Desc}
+\index{contenttype@{contenttype}!mm_content_getencoding@{mm\_\-content\_\-getencoding}}
+\index{mm_content_getencoding@{mm\_\-content\_\-getencoding}!contenttype@{contenttype}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-content\_\-getencoding (struct mm\_\-content $\ast$ {\em ct}, const char $\ast$ {\em encoding})}\label{group__contenttype_gbff87e581cd04db16e91245e9e9de67d}
+
+
+Gets the numerical ID of a content encoding identifier
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ct}]A valid Content Type object \item[{\em encoding}]A string representing the content encoding identifier \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]The numerical ID of the content encoding \end{Desc}
+\index{contenttype@{contenttype}!mm_content_getmaintype@{mm\_\-content\_\-getmaintype}}
+\index{mm_content_getmaintype@{mm\_\-content\_\-getmaintype}!contenttype@{contenttype}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}char$\ast$ mm\_\-content\_\-getmaintype (struct mm\_\-content $\ast$ {\em ct})}\label{group__contenttype_gb213081017abf6bc7e601c6bf4214924}
+
+
+Retrieves the main MIME type stored in a Content-Type object
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ct}]A valid Content-Type object \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]A pointer to the string representing the main type \end{Desc}
+\index{contenttype@{contenttype}!mm_content_getparambyname@{mm\_\-content\_\-getparambyname}}
+\index{mm_content_getparambyname@{mm\_\-content\_\-getparambyname}!contenttype@{contenttype}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}char$\ast$ mm\_\-content\_\-getparambyname (struct mm\_\-content $\ast$ {\em ct}, const char $\ast$ {\em name})}\label{group__contenttype_g451441ee557ab5ef29477f3dc8330bf6}
+
+
+Gets a parameter value from a Content-Type object.
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ct}]the Content-Type object \item[{\em name}]the name of the parameter to retrieve \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]The value of the parameter on success or a NULL pointer on failure \end{Desc}
+\index{contenttype@{contenttype}!mm_content_getsubtype@{mm\_\-content\_\-getsubtype}}
+\index{mm_content_getsubtype@{mm\_\-content\_\-getsubtype}!contenttype@{contenttype}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}char$\ast$ mm\_\-content\_\-getsubtype (struct mm\_\-content $\ast$ {\em ct})}\label{group__contenttype_g97f77ef40c14cd0fb397bad358ee5d49}
+
+
+Retrieves the sub MIME type stored in a Content-Type object
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ct}]A valid Content-Type object \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]A pointer to the string holding the current sub MIME type \end{Desc}
+\index{contenttype@{contenttype}!mm_content_iscomposite@{mm\_\-content\_\-iscomposite}}
+\index{mm_content_iscomposite@{mm\_\-content\_\-iscomposite}!contenttype@{contenttype}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-content\_\-iscomposite (struct mm\_\-content $\ast$ {\em ct})}\label{group__contenttype_ga7fa479f27e73dea57257421d8fc9fc5}
+
+
+Checks whether the Content-Type represents a composite message or not
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ct}]A valid Content-Type object \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]1 if the Content-Type object represents a composite message or 0 if not. \end{Desc}
+\index{contenttype@{contenttype}!mm_content_isvalidencoding@{mm\_\-content\_\-isvalidencoding}}
+\index{mm_content_isvalidencoding@{mm\_\-content\_\-isvalidencoding}!contenttype@{contenttype}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-content\_\-isvalidencoding (const char $\ast$ {\em encoding})}\label{group__contenttype_gb724b5979182fa272fe4fd1b72b395d5}
+
+
+Verifies whether a string represents a valid encoding or not.
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em encoding}]The string to verify \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]1 if the encoding string is valid or 0 if not \end{Desc}
+\index{contenttype@{contenttype}!mm_content_new@{mm\_\-content\_\-new}}
+\index{mm_content_new@{mm\_\-content\_\-new}!contenttype@{contenttype}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}struct mm\_\-content$\ast$ mm\_\-content\_\-new (void)}\label{group__contenttype_g3880ac74a20b4a9f610a4159568e1801}
+
+
+Creates a new object to hold a Content-Type representation. The allocated memory must later be freed using \doxyref{mm\_\-content\_\-free()}{p.}{group__contenttype_g404314481125849bce869ee4b0f647af}
+
+\begin{Desc}
+\item[Returns:]An object representing a MIME Content-Type \end{Desc}
+\begin{Desc}
+\item[See also:]\doxyref{mm\_\-content\_\-free}{p.}{group__contenttype_g404314481125849bce869ee4b0f647af} \end{Desc}
+\index{contenttype@{contenttype}!mm_content_paramstostring@{mm\_\-content\_\-paramstostring}}
+\index{mm_content_paramstostring@{mm\_\-content\_\-paramstostring}!contenttype@{contenttype}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}char$\ast$ mm\_\-content\_\-paramstostring (struct mm\_\-content $\ast$ {\em ct})}\label{group__contenttype_g792e7d33fbb30e0123408bcef9d3204c}
+
+
+Constructs a MIME conform string of Content-Type parameters.
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ct}]A valid Content Type object \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]A pointer to a string representing the Content-Type parameters in MIME terminology, or NULL if either the Content-Type object is invalid, has no parameters or no memory could be allocated.\end{Desc}
+This function constructs a MIME conform string including all the parameters associated with the given Content-Type object. It should NOT be used if you need an opaque copy of the current MIME part (e.g. for PGP purposes). \index{contenttype@{contenttype}!mm_content_setencoding@{mm\_\-content\_\-setencoding}}
+\index{mm_content_setencoding@{mm\_\-content\_\-setencoding}!contenttype@{contenttype}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-content\_\-setencoding (struct mm\_\-content $\ast$ {\em ct}, const char $\ast$ {\em encoding})}\label{group__contenttype_gea945e48ac5cca846715543634b9afe4}
+
+
+Set the encoding of a MIME entitity according to a mapping table
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ct}]A valid content type object \item[{\em encoding}]A string representing the content encoding \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]0 if successfull or -1 if not (i.e. unknown content encoding) \end{Desc}
+\index{contenttype@{contenttype}!mm_content_setmaintype@{mm\_\-content\_\-setmaintype}}
+\index{mm_content_setmaintype@{mm\_\-content\_\-setmaintype}!contenttype@{contenttype}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-content\_\-setmaintype (struct mm\_\-content $\ast$ {\em ct}, char $\ast$ {\em value}, int {\em copy})}\label{group__contenttype_g7bab273d117c6c0cacad20361d8fb1c8}
+
+
+Sets the MIME main type for a MIME Content-Type object
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ct}]The MIME Content-Type object \item[{\em value}]The value which to set the main type to \item[{\em copy}]Whether to make a copy of the value (original value must be freed afterwards to prevent memory leaks). \end{description}
+\end{Desc}
+
+
+\begin{Desc}
+\item[{\bf Bug}]The xfree() call could lead to undesirable results. Do we really need it? \end{Desc}
+\index{contenttype@{contenttype}!mm_content_setsubtype@{mm\_\-content\_\-setsubtype}}
+\index{mm_content_setsubtype@{mm\_\-content\_\-setsubtype}!contenttype@{contenttype}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-content\_\-setsubtype (struct mm\_\-content $\ast$ {\em ct}, char $\ast$ {\em value}, int {\em copy})}\label{group__contenttype_g14b0738410d566ad2312405946f22212}
+
+
+Sets the MIME sub type for a MIME Content-Type object
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ct}]The MIME Content-Type object \item[{\em value}]The value which to set the sub type to \item[{\em copy}]Whether to make a copy of the value (original value must be freed afterwards to prevent memory leaks). \end{description}
+\end{Desc}
+
+
+\begin{Desc}
+\item[{\bf Bug}]The xfree() call could lead to undesirable results. Do we really need it? \end{Desc}
+\index{contenttype@{contenttype}!mm_content_tostring@{mm\_\-content\_\-tostring}}
+\index{mm_content_tostring@{mm\_\-content\_\-tostring}!contenttype@{contenttype}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}char$\ast$ mm\_\-content\_\-tostring (struct mm\_\-content $\ast$ {\em ct})}\label{group__contenttype_g18a99c95e35a76f13a77a83c4231e738}
+
+
+Creates a Content-Type header according to the object given
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ct}]A valid Content-Type object \end{description}
+\end{Desc}
diff --git a/main/minimime/mm-docs/latex/group__context.tex b/main/minimime/mm-docs/latex/group__context.tex
new file mode 100644
index 000000000..aa28a7ba5
--- /dev/null
+++ b/main/minimime/mm-docs/latex/group__context.tex
@@ -0,0 +1,214 @@
+\section{Accessing and manipulating MIME contexts}
+\label{group__context}\index{Accessing and manipulating MIME contexts@{Accessing and manipulating MIME contexts}}
+\subsection*{Manipulating Mini\-MIME contexts}
+\begin{CompactItemize}
+\item
+MM\_\-CTX $\ast$ {\bf mm\_\-context\_\-new} (void)
+\item
+void {\bf mm\_\-context\_\-free} (MM\_\-CTX $\ast$ctx)
+\item
+int {\bf mm\_\-context\_\-attachpart} (MM\_\-CTX $\ast$ctx, struct mm\_\-mimepart $\ast$part)
+\item
+int {\bf mm\_\-context\_\-attachpart\_\-after} (MM\_\-CTX $\ast$ctx, struct mm\_\-mimepart $\ast$part, int pos)
+\item
+int {\bf mm\_\-context\_\-deletepart} (MM\_\-CTX $\ast$ctx, int which, int freemem)
+\item
+int {\bf mm\_\-context\_\-countparts} (MM\_\-CTX $\ast$ctx)
+\item
+mm\_\-mimepart $\ast$ {\bf mm\_\-context\_\-getpart} (MM\_\-CTX $\ast$ctx, int which)
+\item
+int {\bf mm\_\-context\_\-iscomposite} (MM\_\-CTX $\ast$ctx)
+\item
+int {\bf mm\_\-context\_\-haswarnings} (MM\_\-CTX $\ast$ctx)
+\item
+int {\bf mm\_\-context\_\-generateboundary} (MM\_\-CTX $\ast$ctx)
+\item
+int {\bf mm\_\-context\_\-setpreamble} (MM\_\-CTX $\ast$ctx, char $\ast$preamble)
+\item
+char $\ast$ \textbf{mm\_\-context\_\-getpreamble} (MM\_\-CTX $\ast$ctx)\label{group__context_g1ebbdd51106ccdee77ca421f9692bde7}
+
+\item
+int {\bf mm\_\-context\_\-flatten} (MM\_\-CTX $\ast$ctx, char $\ast$$\ast$flat, size\_\-t $\ast$length, int flags)
+\end{CompactItemize}
+
+
+\subsection{Detailed Description}
+Each message in Mini\-MIME is represented by a so called ``context''. A context holds all necessary information given about a MIME message, such as the envelope, all MIME parts etc.
+
+\subsection{Function Documentation}
+\index{context@{context}!mm_context_attachpart@{mm\_\-context\_\-attachpart}}
+\index{mm_context_attachpart@{mm\_\-context\_\-attachpart}!context@{context}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-context\_\-attachpart (MM\_\-CTX $\ast$ {\em ctx}, struct mm\_\-mimepart $\ast$ {\em part})}\label{group__context_gec3ca486a61b392ff68774242086768e}
+
+
+Attaches a MIME part object to a Mini\-MIME context.
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ctx}]the Mini\-MIME context \item[{\em part}]the MIME part object to attach \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]0 on success or -1 on failure. Sets mm\_\-errno on failure.\end{Desc}
+This function attaches a MIME part to a context, appending it to the end of the message.
+
+The MIME part should be initialized before attaching it using \doxyref{mm\_\-mimepart\_\-new()}{p.}{group__mimepart_g417e5dd361e30cddb91e1d9a5e30b223}. \index{context@{context}!mm_context_attachpart_after@{mm\_\-context\_\-attachpart\_\-after}}
+\index{mm_context_attachpart_after@{mm\_\-context\_\-attachpart\_\-after}!context@{context}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-context\_\-attachpart\_\-after (MM\_\-CTX $\ast$ {\em ctx}, struct mm\_\-mimepart $\ast$ {\em part}, int {\em pos})}\label{group__context_g73a3dd187053aeabca4836dc28a6c468}
+
+
+Attaches a MIME part object to a Mini\-MIME context at a given position
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ctx}]A valid Mini\-MIME context \item[{\em part}]The MIME part object to attach \item[{\em pos}]After which part to attach the object \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]0 on success or -1 if the given position is invalid \end{Desc}
+\begin{Desc}
+\item[See also:]\doxyref{mm\_\-context\_\-attachpart}{p.}{group__context_gec3ca486a61b392ff68774242086768e}\end{Desc}
+This function attaches a MIME part object after a given position in the specified context. If the position is invalid (out of range), the part will not get attached to the message and the function returns -1. If the index was in range, the MIME part will get attached after the MIME part at the given position, moving any possible following MIME parts one down the hierarchy. \index{context@{context}!mm_context_countparts@{mm\_\-context\_\-countparts}}
+\index{mm_context_countparts@{mm\_\-context\_\-countparts}!context@{context}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-context\_\-countparts (MM\_\-CTX $\ast$ {\em ctx})}\label{group__context_gf5bb032ad1c481d31d7b1b0710939712}
+
+
+Counts the number of attached MIME part objects in a given Mini\-MIME context
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ctx}]The Mini\-MIME context \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]The number of attached MIME part objects \end{Desc}
+\index{context@{context}!mm_context_deletepart@{mm\_\-context\_\-deletepart}}
+\index{mm_context_deletepart@{mm\_\-context\_\-deletepart}!context@{context}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-context\_\-deletepart (MM\_\-CTX $\ast$ {\em ctx}, int {\em which}, int {\em freemem})}\label{group__context_g53d20c33a401539ef1ffa45f3dddb983}
+
+
+Deletes a MIME part object from a Mini\-MIME context
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ctx}]A valid Mini\-MIME context object \item[{\em which}]The number of the MIME part object to delete \item[{\em freemem}]Whether to free the memory associated with the MIME part object \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]0 on success or -1 on failure. Sets mm\_\-errno on failure.\end{Desc}
+This function deletes a MIME part from a given context. The MIME part to delete is specified as numerical index by the parameter ``which''. If the parameter ``freemem'' is set to anything greater than 0, the memory that is associated will be free'd by using \doxyref{mm\_\-mimepart\_\-free()}{p.}{group__mimepart_gbf47790a0bb96b22bc5e236bc40cb32e}, otherwise the memory is left untouched (if you still have a pointer to the MIME part around). \index{context@{context}!mm_context_flatten@{mm\_\-context\_\-flatten}}
+\index{mm_context_flatten@{mm\_\-context\_\-flatten}!context@{context}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-context\_\-flatten (MM\_\-CTX $\ast$ {\em ctx}, char $\ast$$\ast$ {\em flat}, size\_\-t $\ast$ {\em length}, int {\em flags})}\label{group__context_g5288136ab923605f6508c09359ae5772}
+
+
+Creates an ASCII message of the specified context
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ctx}]A valid Mini\-MIME context object \item[{\em flat}]Where to store the message \item[{\em flags}]Flags that affect the flattening process\end{description}
+\end{Desc}
+This function ``flattens'' a Mini\-MIME context, that is, it creates an ASCII represantation of the message the context contains. The flags can be a bitwise combination of the following constants:
+
+\begin{itemize}
+\item MM\_\-FLATTEN\_\-OPAQUE : use opaque MIME parts when flattening\item MM\_\-FLATTEN\_\-SKIPENVELOPE : do not flatten the envelope part\end{itemize}
+
+
+Great care is taken to not produce invalid MIME output. \index{context@{context}!mm_context_free@{mm\_\-context\_\-free}}
+\index{mm_context_free@{mm\_\-context\_\-free}!context@{context}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}void mm\_\-context\_\-free (MM\_\-CTX $\ast$ {\em ctx})}\label{group__context_g76392d5269e9ef340c2f5f8336f7193b}
+
+
+Releases a Mini\-MIME context object
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ctx}]A valid Mini\-MIME context \end{description}
+\end{Desc}
+\begin{Desc}
+\item[See also:]\doxyref{mm\_\-context\_\-new}{p.}{group__context_g919fd41f85534d9c87c256857faa2610}\end{Desc}
+This function releases all memory associated with Mini\-MIME context object that was created using \doxyref{mm\_\-context\_\-new()}{p.}{group__context_g919fd41f85534d9c87c256857faa2610}. It will also release all memory used for the MIME parts attached, and their specific properties (such as Content-Type information, headers, and the body data). \index{context@{context}!mm_context_generateboundary@{mm\_\-context\_\-generateboundary}}
+\index{mm_context_generateboundary@{mm\_\-context\_\-generateboundary}!context@{context}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-context\_\-generateboundary (MM\_\-CTX $\ast$ {\em ctx})}\label{group__context_g9710e485f51167099d90f0d659979068}
+
+
+Generates a generic boundary string for a given context
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ctx}]A valid Mini\-MIME context \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]0 on success or -1 on failure\end{Desc}
+This function generates a default boundary string for the given context. If there is already a boundary for the context, the memory will be free()'d. \index{context@{context}!mm_context_getpart@{mm\_\-context\_\-getpart}}
+\index{mm_context_getpart@{mm\_\-context\_\-getpart}!context@{context}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}struct mm\_\-mimepart$\ast$ mm\_\-context\_\-getpart (MM\_\-CTX $\ast$ {\em ctx}, int {\em which})}\label{group__context_g57fea229675f3e56a77eb40bb8193ee3}
+
+
+Gets a specified MIME part object from a Mime\-MIME context
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ctx}]The Mini\-MIME context \item[{\em which}]The number of the MIME part object to retrieve \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]The requested MIME part object on success or a NULL pointer if there is no such part. \end{Desc}
+\index{context@{context}!mm_context_haswarnings@{mm\_\-context\_\-haswarnings}}
+\index{mm_context_haswarnings@{mm\_\-context\_\-haswarnings}!context@{context}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-context\_\-haswarnings (MM\_\-CTX $\ast$ {\em ctx})}\label{group__context_g8733dee7d83d3205349a7ee4ee5b2750}
+
+
+Checks whether there are any warnings associated with a given context
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ctx}]A valid Mini\-MIME context \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]1 if there are warnings associated with the context, otherwise 0 \end{Desc}
+\index{context@{context}!mm_context_iscomposite@{mm\_\-context\_\-iscomposite}}
+\index{mm_context_iscomposite@{mm\_\-context\_\-iscomposite}!context@{context}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-context\_\-iscomposite (MM\_\-CTX $\ast$ {\em ctx})}\label{group__context_g1e73cadba4acd3ef9dd148dd0c2c3e70}
+
+
+Checks whether a given context represents a composite (multipart) message
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ctx}]A valid Mini\-MIME context object \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]1 if the context is a composite message or 0 if it's flat \end{Desc}
+\index{context@{context}!mm_context_new@{mm\_\-context\_\-new}}
+\index{mm_context_new@{mm\_\-context\_\-new}!context@{context}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}MM\_\-CTX$\ast$ mm\_\-context\_\-new (void)}\label{group__context_g919fd41f85534d9c87c256857faa2610}
+
+
+Creates a new Mini\-MIME context object.
+
+\begin{Desc}
+\item[Returns:]a new Mini\-MIME context object \end{Desc}
+\begin{Desc}
+\item[See also:]\doxyref{mm\_\-context\_\-free}{p.}{group__context_g76392d5269e9ef340c2f5f8336f7193b}\end{Desc}
+This function creates a new Mini\-MIME context, which will hold a message. The memory needed is allocated dynamically and should later be free'd using \doxyref{mm\_\-context\_\-free()}{p.}{group__context_g76392d5269e9ef340c2f5f8336f7193b}.
+
+Before a context can be created, the Mini\-MIME library needs to be initialized properly using mm\_\-library\_\-init(). \index{context@{context}!mm_context_setpreamble@{mm\_\-context\_\-setpreamble}}
+\index{mm_context_setpreamble@{mm\_\-context\_\-setpreamble}!context@{context}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-context\_\-setpreamble (MM\_\-CTX $\ast$ {\em ctx}, char $\ast$ {\em preamble})}\label{group__context_gc0e7cc297516618d4773830a1988fc8d}
+
+
+Sets a preamble for the given Mini\-MIME context
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ctx}]A valid Mini\-MIME context \item[{\em preamble}]The preamble to set \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]0 on success or -1 on failure\end{Desc}
+This function sets the MIME preamble (the text between the end of envelope headers and the beginning of the first MIME part) for a given context object. If preamble is a NULL-pointer then the preamble will be deleted, and the currently associated memory will be free automagically. \ No newline at end of file
diff --git a/main/minimime/mm-docs/latex/group__envelope.tex b/main/minimime/mm-docs/latex/group__envelope.tex
new file mode 100644
index 000000000..613c87948
--- /dev/null
+++ b/main/minimime/mm-docs/latex/group__envelope.tex
@@ -0,0 +1,65 @@
+\section{Accessing and manipulating a message's envelope}
+\label{group__envelope}\index{Accessing and manipulating a message's envelope@{Accessing and manipulating a message's envelope}}
+\subsection*{Accessing and manipulating a message's envelope}
+\begin{CompactItemize}
+\item
+int {\bf mm\_\-envelope\_\-getheaders} (MM\_\-CTX $\ast$ctx, char $\ast$$\ast$result, size\_\-t $\ast$length)
+\item
+int {\bf mm\_\-envelope\_\-setheader} (MM\_\-CTX $\ast$ctx, const char $\ast$name, const char $\ast$fmt,...)
+\item
+int {\bf mm\_\-envelope\_\-getrecipients} (MM\_\-CTX $\ast$ctx, char $\ast$$\ast$result, size\_\-t $\ast$length)
+\end{CompactItemize}
+
+
+\subsection{Function Documentation}
+\index{envelope@{envelope}!mm_envelope_getheaders@{mm\_\-envelope\_\-getheaders}}
+\index{mm_envelope_getheaders@{mm\_\-envelope\_\-getheaders}!envelope@{envelope}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-envelope\_\-getheaders (MM\_\-CTX $\ast$ {\em ctx}, char $\ast$$\ast$ {\em result}, size\_\-t $\ast$ {\em length})}\label{group__envelope_g38f1164142cedfc3253b068a81f85563}
+
+
+Gets an ASCII representation of all envelope headers
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ctx}]A valid Mini\-MIME context \item[{\em result}]Where to store the resulting ASCII headers \item[{\em length}]Where to store the length of the result \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]0 on success or -1 on failure. \end{Desc}
+\begin{Desc}
+\item[Note:]Sets mm\_\-errno on failure\end{Desc}
+This is mainly a convinience function. It constructs an ASCII representation from all of the message's envelope headers and stores the result in headers. Memory is allocated dynamically, and the total length of the result is stored in length. This function takes care that the output is MIME conform, and folds long lines according to the MIME standard at position 78 of the string. It also nicely formats all MIME related header fields, such as the Content-Type header.
+
+Since the memory needed to store the result is allocated dynamically, one should take care of freeing it again when it's not needed anymore. If an error occurs, $\ast$result will be set to NULL, $\ast$length will be set to zero and mm\_\-errno will be set to a reasonable value. \index{envelope@{envelope}!mm_envelope_getrecipients@{mm\_\-envelope\_\-getrecipients}}
+\index{mm_envelope_getrecipients@{mm\_\-envelope\_\-getrecipients}!envelope@{envelope}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-envelope\_\-getrecipients (MM\_\-CTX $\ast$ {\em ctx}, char $\ast$$\ast$ {\em result}, size\_\-t $\ast$ {\em length})}\label{group__envelope_ge63da17c56867ca2406a4eaf73230baf}
+
+
+Gets the list of recipients for a MIME message
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ctx}]A valid Mini\-MIME context \item[{\em result}]Where to store the result \item[{\em length}]Where to store the length of the result \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]0 on success or -1 on error \end{Desc}
+\begin{Desc}
+\item[Note:]Sets mm\_\-errno on error\end{Desc}
+This functions gets the list of recipients for a given MIME message. It does so by concatenating the \char`\"{}From\char`\"{} and \char`\"{}Cc\char`\"{} header fields, and storing the results in recipients. The memory needed to store the result is allocated dynamically, and the total length of the result is stored in length.
+
+One should take care to free() the result once it's not needed anymore. \index{envelope@{envelope}!mm_envelope_setheader@{mm\_\-envelope\_\-setheader}}
+\index{mm_envelope_setheader@{mm\_\-envelope\_\-setheader}!envelope@{envelope}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-envelope\_\-setheader (MM\_\-CTX $\ast$ {\em ctx}, const char $\ast$ {\em name}, const char $\ast$ {\em fmt}, {\em ...})}\label{group__envelope_gb2c43c1645e42ae0860c902ce1dda788}
+
+
+Sets a header field in the envelope
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ctx}]A valid Mini\-MIME context \item[{\em name}]The name of the header field to set \item[{\em fmt}]A format string specifying the value of the header field \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]0 on success or -1 on failure\end{Desc}
+This function generates a new MIME header and attaches it to the first MIME part (the envelope) found in the given context. If no part is attached already, the function will return an error. The function will store a copy of ``name'' as the header's name field, and dynamically allocate the memory needed to build the format string. \ No newline at end of file
diff --git a/main/minimime/mm-docs/latex/group__error.tex b/main/minimime/mm-docs/latex/group__error.tex
new file mode 100644
index 000000000..c9c49034e
--- /dev/null
+++ b/main/minimime/mm-docs/latex/group__error.tex
@@ -0,0 +1,43 @@
+\section{Mini\-MIME error functions}
+\label{group__error}\index{MiniMIME error functions@{MiniMIME error functions}}
+\subsection*{Functions}
+\begin{CompactItemize}
+\item
+void {\bf mm\_\-error\_\-init} (void)
+\item
+void {\bf mm\_\-error\_\-setmsg} (const char $\ast$fmt,...)
+\item
+char $\ast$ {\bf mm\_\-error\_\-string} (void)
+\end{CompactItemize}
+
+
+\subsection{Function Documentation}
+\index{error@{error}!mm_error_init@{mm\_\-error\_\-init}}
+\index{mm_error_init@{mm\_\-error\_\-init}!error@{error}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}void mm\_\-error\_\-init (void)}\label{group__error_g69de7c9bee1d535593a55807590de543}
+
+
+Initializes the global error object
+
+This function initializes the global error object mm\_\-error. This must be done when the library is initialized, and is automatically called from mm\_\-init\_\-library(). \index{error@{error}!mm_error_setmsg@{mm\_\-error\_\-setmsg}}
+\index{mm_error_setmsg@{mm\_\-error\_\-setmsg}!error@{error}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}void mm\_\-error\_\-setmsg (const char $\ast$ {\em fmt}, {\em ...})}\label{group__error_g92006c97728639d8f32f5bc4c6e2a47f}
+
+
+Sets a descriptive error message
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em fmt}]The error message as format string\end{description}
+\end{Desc}
+This function is called from the various Mini\-MIME modules in case an error occured. Should never be called by the user. \index{error@{error}!mm_error_string@{mm\_\-error\_\-string}}
+\index{mm_error_string@{mm\_\-error\_\-string}!error@{error}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}char$\ast$ mm\_\-error\_\-string (void)}\label{group__error_g8654857a3ac349b87d798902912371a3}
+
+
+Retrieves the current error message
+
+\begin{Desc}
+\item[Returns:]The currently set error message\end{Desc}
+This function can be used to retrieve a descriptive error message for the current error, much like strerror() function of libc. When this function is called without an error being set, it returns the string \char`\"{}No error\char`\"{}. The string returned does not need to be freed, since it is not dynamically allocated by the library. \ No newline at end of file
diff --git a/main/minimime/mm-docs/latex/group__mimepart.tex b/main/minimime/mm-docs/latex/group__mimepart.tex
new file mode 100644
index 000000000..e9f9742d9
--- /dev/null
+++ b/main/minimime/mm-docs/latex/group__mimepart.tex
@@ -0,0 +1,333 @@
+\section{Accessing and manipulating MIME parts}
+\label{group__mimepart}\index{Accessing and manipulating MIME parts@{Accessing and manipulating MIME parts}}
+\subsection*{Creating and destroying MIME parts}
+\begin{CompactItemize}
+\item
+mm\_\-mimepart $\ast$ {\bf mm\_\-mimepart\_\-new} (void)
+\item
+mm\_\-mimepart $\ast$ {\bf mm\_\-mimepart\_\-fromfile} (const char $\ast$filename)
+\item
+void {\bf mm\_\-mimepart\_\-free} (struct mm\_\-mimepart $\ast$part)
+\end{CompactItemize}
+\subsection*{Accessing the MIME part's mail header}
+\begin{CompactItemize}
+\item
+int {\bf mm\_\-mimepart\_\-attachheader} (struct mm\_\-mimepart $\ast$part, struct mm\_\-mimeheader $\ast$header)
+\item
+int {\bf mm\_\-mimepart\_\-countheaders} (struct mm\_\-mimepart $\ast$part)
+\item
+int {\bf mm\_\-mimepart\_\-countheaderbyname} (struct mm\_\-mimepart $\ast$part, const char $\ast$name)
+\item
+mm\_\-mimeheader $\ast$ {\bf mm\_\-mimepart\_\-getheaderbyname} (struct mm\_\-mimepart $\ast$part, const char $\ast$name, int idx)
+\item
+const char $\ast$ {\bf mm\_\-mimepart\_\-getheadervalue} (struct mm\_\-mimepart $\ast$part, const char $\ast$name, int idx)
+\item
+int {\bf mm\_\-mimepart\_\-headers\_\-start} (struct mm\_\-mimepart $\ast$part, struct mm\_\-mimeheader $\ast$$\ast$id)
+\item
+mm\_\-mimeheader $\ast$ {\bf mm\_\-mimepart\_\-headers\_\-next} (struct mm\_\-mimepart $\ast$part, struct mm\_\-mimeheader $\ast$$\ast$id)
+\end{CompactItemize}
+\subsection*{Accessing and manipulating the MIME part's body}
+\begin{CompactItemize}
+\item
+char $\ast$ {\bf mm\_\-mimepart\_\-getbody} (struct mm\_\-mimepart $\ast$part, int opaque)
+\item
+void {\bf mm\_\-mimepart\_\-setbody} (struct mm\_\-mimepart $\ast$part, const char $\ast$data, int opaque)
+\item
+size\_\-t {\bf mm\_\-mimepart\_\-getlength} (struct mm\_\-mimepart $\ast$part)
+\item
+char $\ast$ {\bf mm\_\-mimepart\_\-decode} (struct mm\_\-mimepart $\ast$part)
+\item
+int {\bf mm\_\-mimepart\_\-flatten} (struct mm\_\-mimepart $\ast$part, char $\ast$$\ast$result, size\_\-t $\ast$length, int opaque)
+\item
+int {\bf mm\_\-mimepart\_\-setdefaultcontenttype} (struct mm\_\-mimepart $\ast$part, int composite)
+\end{CompactItemize}
+\subsection*{Accessing the MIME part's Content-Type information}
+\begin{CompactItemize}
+\item
+void {\bf mm\_\-mimepart\_\-attachcontenttype} (struct mm\_\-mimepart $\ast$part, struct mm\_\-content $\ast$ct)
+\item
+mm\_\-content $\ast$ {\bf mm\_\-mimepart\_\-gettype} (struct mm\_\-mimepart $\ast$part)
+\end{CompactItemize}
+
+
+\subsection{Detailed Description}
+MIME parts, also called entities, represent the structure of a MIME message. ``Normal'' internet messages have only a single part, and are called ``flat'' messages. Multipart messages have more then one part, and each MIME part can have it's own subset of headers.
+
+Provided here are functions to easily access all informations from a MIME part, including their specific headers and bodies.
+
+\subsection{Function Documentation}
+\index{mimepart@{mimepart}!mm_mimepart_attachcontenttype@{mm\_\-mimepart\_\-attachcontenttype}}
+\index{mm_mimepart_attachcontenttype@{mm\_\-mimepart\_\-attachcontenttype}!mimepart@{mimepart}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}void mm\_\-mimepart\_\-attachcontenttype (struct mm\_\-mimepart $\ast$ {\em part}, struct mm\_\-content $\ast$ {\em ct})}\label{group__mimepart_g01822bc93b4741af75b5379384354e37}
+
+
+Attaches a context type object to a MIME part
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em part}]A valid MIME part object \item[{\em ct}]The content type object to attach \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]Nothing\end{Desc}
+This function attaches a Content-Type object to a MIME part. It does not care whether the Content-Type suites the actual content in the MIME part, so the programmer should take care of that. \index{mimepart@{mimepart}!mm_mimepart_attachheader@{mm\_\-mimepart\_\-attachheader}}
+\index{mm_mimepart_attachheader@{mm\_\-mimepart\_\-attachheader}!mimepart@{mimepart}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-mimepart\_\-attachheader (struct mm\_\-mimepart $\ast$ {\em part}, struct mm\_\-mimeheader $\ast$ {\em header})}\label{group__mimepart_g46a674ff6b9873c0c45fa4eb5d94fd62}
+
+
+Attaches a mm\_\-mimeheader object to a MIME part
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em part}]A valid MIME part object \item[{\em header}]A valid MIME header object \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]0 if successfull or -1 if the header could not be attached \end{Desc}
+\index{mimepart@{mimepart}!mm_mimepart_countheaderbyname@{mm\_\-mimepart\_\-countheaderbyname}}
+\index{mm_mimepart_countheaderbyname@{mm\_\-mimepart\_\-countheaderbyname}!mimepart@{mimepart}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-mimepart\_\-countheaderbyname (struct mm\_\-mimepart $\ast$ {\em part}, const char $\ast$ {\em name})}\label{group__mimepart_gf89da502ac54306994bdb452448a8026}
+
+
+Retrieves the number of MIME headers with a given name in a MIME part
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em part}]A valid MIME part object \item[{\em name}]The name of the MIME header which to count for \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]The number of MIME headers within the MIME part \end{Desc}
+\index{mimepart@{mimepart}!mm_mimepart_countheaders@{mm\_\-mimepart\_\-countheaders}}
+\index{mm_mimepart_countheaders@{mm\_\-mimepart\_\-countheaders}!mimepart@{mimepart}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-mimepart\_\-countheaders (struct mm\_\-mimepart $\ast$ {\em part})}\label{group__mimepart_g44c78abfb0535312bcb427a2cd220026}
+
+
+Retrieves the number of MIME headers available in a MIME part
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em part}]A valid MIME part object \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]The number of MIME headers within the MIME part \end{Desc}
+\index{mimepart@{mimepart}!mm_mimepart_decode@{mm\_\-mimepart\_\-decode}}
+\index{mm_mimepart_decode@{mm\_\-mimepart\_\-decode}!mimepart@{mimepart}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}char$\ast$ mm\_\-mimepart\_\-decode (struct mm\_\-mimepart $\ast$ {\em part})}\label{group__mimepart_g4551bf4460e5d165bbcd9f32d4f625de}
+
+
+Decodes a MIME part according to it's encoding using Mini\-MIME codecs
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em A}]valid MIME part object \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]0 if the MIME part could be successfully decoded or -1 if not \end{Desc}
+\begin{Desc}
+\item[Note:]Sets mm\_\-errno on error\end{Desc}
+This function decodes the body of a MIME part with a registered decoder according to it's Content-Transfer-Encoding header field. \index{mimepart@{mimepart}!mm_mimepart_flatten@{mm\_\-mimepart\_\-flatten}}
+\index{mm_mimepart_flatten@{mm\_\-mimepart\_\-flatten}!mimepart@{mimepart}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-mimepart\_\-flatten (struct mm\_\-mimepart $\ast$ {\em part}, char $\ast$$\ast$ {\em result}, size\_\-t $\ast$ {\em length}, int {\em opaque})}\label{group__mimepart_gf19d3ace5ae174b3eaa35f9ddbe6e216}
+
+
+Creates an ASCII representation of the given MIME part
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em part}]A valid MIME part object \item[{\em result}]Where to store the result \item[{\em length}]Where to store the length of the result \item[{\em opaque}]Whether to use the opaque MIME part 0 on success or -1 on error. \end{description}
+\end{Desc}
+\begin{Desc}
+\item[See also:]\doxyref{mm\_\-context\_\-flatten}{p.}{group__context_g5288136ab923605f6508c09359ae5772}\end{Desc}
+This function creates an ASCII representation of a given MIME part. It will dynamically allocate the memory needed and stores the result in the memory region pointed to by result. The length of the result will be stored in length. If opaque is set to 1, mm\_\-mimepart\_\-flatten will store an opaque version of the MIME part in result, which means no headers will be created or sanitized. This is particulary useful if the part is digitally signed by e.g. PGP, and the signature spans the header fields of the part in question. \index{mimepart@{mimepart}!mm_mimepart_free@{mm\_\-mimepart\_\-free}}
+\index{mm_mimepart_free@{mm\_\-mimepart\_\-free}!mimepart@{mimepart}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}void mm\_\-mimepart\_\-free (struct mm\_\-mimepart $\ast$ {\em part})}\label{group__mimepart_gbf47790a0bb96b22bc5e236bc40cb32e}
+
+
+Frees all memory allocated by a mm\_\-mimepart object.
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em part}]A pointer to an allocated mm\_\-mimepart object \end{description}
+\end{Desc}
+\begin{Desc}
+\item[See also:]\doxyref{mm\_\-mimepart\_\-new}{p.}{group__mimepart_g417e5dd361e30cddb91e1d9a5e30b223} \end{Desc}
+\index{mimepart@{mimepart}!mm_mimepart_fromfile@{mm\_\-mimepart\_\-fromfile}}
+\index{mm_mimepart_fromfile@{mm\_\-mimepart\_\-fromfile}!mimepart@{mimepart}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}struct mm\_\-mimepart$\ast$ mm\_\-mimepart\_\-fromfile (const char $\ast$ {\em filename})}\label{group__mimepart_ged8112012a337371ae8093adb1ab6d27}
+
+
+Creates a MIME part from a file
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em filename}]The name of the file to create the MIME part from \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]A pointer to a new MIME part object\end{Desc}
+This function creates a new MIME part object from a file. The object should be freed using \doxyref{mm\_\-mimepart\_\-free()}{p.}{group__mimepart_gbf47790a0bb96b22bc5e236bc40cb32e} later on. This function does NOT set the Content-Type and neither does any encoding work. \index{mimepart@{mimepart}!mm_mimepart_getbody@{mm\_\-mimepart\_\-getbody}}
+\index{mm_mimepart_getbody@{mm\_\-mimepart\_\-getbody}!mimepart@{mimepart}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}char$\ast$ mm\_\-mimepart\_\-getbody (struct mm\_\-mimepart $\ast$ {\em part}, int {\em opaque})}\label{group__mimepart_g52dc9f27a2801e4f6abb1effd2ed838d}
+
+
+Gets the pointer to the MIME part's body data
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em part}]A valid MIME part object \item[{\em opaque}]Whether to get the opaque part or not \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]A pointer to the MIME part's body \end{Desc}
+\begin{Desc}
+\item[See also:]\doxyref{mm\_\-mimepart\_\-setbody}{p.}{group__mimepart_gd1def098c00edc546b03e98e9ff8b27a} \end{Desc}
+\index{mimepart@{mimepart}!mm_mimepart_getheaderbyname@{mm\_\-mimepart\_\-getheaderbyname}}
+\index{mm_mimepart_getheaderbyname@{mm\_\-mimepart\_\-getheaderbyname}!mimepart@{mimepart}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}struct mm\_\-mimeheader$\ast$ mm\_\-mimepart\_\-getheaderbyname (struct mm\_\-mimepart $\ast$ {\em part}, const char $\ast$ {\em name}, int {\em idx})}\label{group__mimepart_ga3ca298eaa82f4ef3ea731511ac84e53}
+
+
+Get a MIME header object from a MIME part
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em part}]A valid MIME part object \item[{\em name}]The name of the MIME header which to retrieve \item[{\em idx}]Which header field to get (in case of multiple headers of the same name). \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]A pointer to the requested MIME header on success, or NULL if there either isn't a header with the requested name or idx is out of range. \end{Desc}
+\index{mimepart@{mimepart}!mm_mimepart_getheadervalue@{mm\_\-mimepart\_\-getheadervalue}}
+\index{mm_mimepart_getheadervalue@{mm\_\-mimepart\_\-getheadervalue}!mimepart@{mimepart}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}const char$\ast$ mm\_\-mimepart\_\-getheadervalue (struct mm\_\-mimepart $\ast$ {\em part}, const char $\ast$ {\em name}, int {\em idx})}\label{group__mimepart_g779f11f7a6a54f83763b5ef6ff87e48f}
+
+
+Gets the value of a MIME header object
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em part}]A valid MIME part object \item[{\em name}]The name of the header field to get the value from \item[{\em idx}]The index of the header field to get, in case there are multiple headers with the same name. \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]A pointer to the requested value on success, or NULL if there either isn't a header with the requested name or idx is out of range. \end{Desc}
+\index{mimepart@{mimepart}!mm_mimepart_getlength@{mm\_\-mimepart\_\-getlength}}
+\index{mm_mimepart_getlength@{mm\_\-mimepart\_\-getlength}!mimepart@{mimepart}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}size\_\-t mm\_\-mimepart\_\-getlength (struct mm\_\-mimepart $\ast$ {\em part})}\label{group__mimepart_gf8ccae1737dc4b9b91958fe448da677f}
+
+
+Gets the length of a given MIME part object
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em part}]A valid MIME part object \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]The size of the part's body in byte.\end{Desc}
+This function returns the total length of the given MIME part's body. The length does not include the headers of the MIME parts. If the function returns 0, no body part is set currently. \index{mimepart@{mimepart}!mm_mimepart_gettype@{mm\_\-mimepart\_\-gettype}}
+\index{mm_mimepart_gettype@{mm\_\-mimepart\_\-gettype}!mimepart@{mimepart}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}struct mm\_\-content$\ast$ mm\_\-mimepart\_\-gettype (struct mm\_\-mimepart $\ast$ {\em part})}\label{group__mimepart_g210e2ceee56f8349f6778006da87d080}
+
+
+Gets the Content-Type of a given MIME part object
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em part}]A valid MIME part object \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]The Content-Type object of the specified MIME part\end{Desc}
+This function returns a pointer to the Content-Type object of the given MIME part. This pointer might be set to NULL, indicating that there is no Content-Type object for the given MIME part currently. \index{mimepart@{mimepart}!mm_mimepart_headers_next@{mm\_\-mimepart\_\-headers\_\-next}}
+\index{mm_mimepart_headers_next@{mm\_\-mimepart\_\-headers\_\-next}!mimepart@{mimepart}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}struct mm\_\-mimeheader$\ast$ mm\_\-mimepart\_\-headers\_\-next (struct mm\_\-mimepart $\ast$ {\em part}, struct mm\_\-mimeheader $\ast$$\ast$ {\em id})}\label{group__mimepart_g8e9064736efdeebf4b257cc45f8a6adf}
+
+
+Returns the next MIME header of a given MIME part object
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em part}]A valid MIME part object \item[{\em id}]A previously initialized MIME header object \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]A pointer to the MIME header object or NULL if end of headers was reached. \end{Desc}
+\begin{Desc}
+\item[See also:]\doxyref{mm\_\-mimepart\_\-headers\_\-start}{p.}{group__mimepart_g4440bdcfddf88eb642b6a834a0557176} \end{Desc}
+\index{mimepart@{mimepart}!mm_mimepart_headers_start@{mm\_\-mimepart\_\-headers\_\-start}}
+\index{mm_mimepart_headers_start@{mm\_\-mimepart\_\-headers\_\-start}!mimepart@{mimepart}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-mimepart\_\-headers\_\-start (struct mm\_\-mimepart $\ast$ {\em part}, struct mm\_\-mimeheader $\ast$$\ast$ {\em id})}\label{group__mimepart_g4440bdcfddf88eb642b6a834a0557176}
+
+
+Initializes a header loop for a given MIME part
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em part}]A valid MIME part object \item[{\em id}]The address of a MIME header object (to allow reentrance) \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]0 on success or -1 on failure \end{Desc}
+\begin{Desc}
+\item[See also:]\doxyref{mm\_\-mimepart\_\-headers\_\-next}{p.}{group__mimepart_g8e9064736efdeebf4b257cc45f8a6adf}\end{Desc}
+Looping through headers can be done in the following way:
+
+
+
+\begin{Code}\begin{verbatim} struct mm_mimeheader *header, *lheader;
+
+ mm_mimepart_headers_start(part, &lheader);
+
+ while ((header = mm_mimepart_headers_next(part, &lheader)) != NULL) {
+ printf("%s: %s\n", header->name, header->value);
+ }
+\end{verbatim}\end{Code}
+
+
+
+For convienience, the macro mm\_\-mimepart\_\-headers\_\-foreach() can be used to loop through headers in a one-shot manner. \index{mimepart@{mimepart}!mm_mimepart_new@{mm\_\-mimepart\_\-new}}
+\index{mm_mimepart_new@{mm\_\-mimepart\_\-new}!mimepart@{mimepart}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}struct mm\_\-mimepart$\ast$ mm\_\-mimepart\_\-new (void)}\label{group__mimepart_g417e5dd361e30cddb91e1d9a5e30b223}
+
+
+Allocates memory for a new mm\_\-mimepart structure and initializes it.
+
+\begin{Desc}
+\item[Returns:]A pointer to a struct of type mm\_\-mimeheader or NULL on failure \end{Desc}
+\begin{Desc}
+\item[See also:]\doxyref{mm\_\-mimepart\_\-free}{p.}{group__mimepart_gbf47790a0bb96b22bc5e236bc40cb32e} \end{Desc}
+\begin{Desc}
+\item[Note:]The memory must be freed by using \doxyref{mm\_\-mimepart\_\-free()}{p.}{group__mimepart_gbf47790a0bb96b22bc5e236bc40cb32e} later on. \end{Desc}
+\index{mimepart@{mimepart}!mm_mimepart_setbody@{mm\_\-mimepart\_\-setbody}}
+\index{mm_mimepart_setbody@{mm\_\-mimepart\_\-setbody}!mimepart@{mimepart}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}void mm\_\-mimepart\_\-setbody (struct mm\_\-mimepart $\ast$ {\em part}, const char $\ast$ {\em data}, int {\em opaque})}\label{group__mimepart_gd1def098c00edc546b03e98e9ff8b27a}
+
+
+Sets the MIME part's body data
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em part}]A valid MIME part object \item[{\em data}]A pointer to the data which to set \end{description}
+\end{Desc}
+\begin{Desc}
+\item[See also:]\doxyref{mm\_\-mimepart\_\-getbody}{p.}{group__mimepart_g52dc9f27a2801e4f6abb1effd2ed838d}\end{Desc}
+This functions sets the body data for a given MIME part. The string pointed to by data must be NUL-terminated. The data is copied into the MIME part's body, and thus, the memory pointed to by data can be freed after the operation. \index{mimepart@{mimepart}!mm_mimepart_setdefaultcontenttype@{mm\_\-mimepart\_\-setdefaultcontenttype}}
+\index{mm_mimepart_setdefaultcontenttype@{mm\_\-mimepart\_\-setdefaultcontenttype}!mimepart@{mimepart}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-mimepart\_\-setdefaultcontenttype (struct mm\_\-mimepart $\ast$ {\em part}, int {\em composite})}\label{group__mimepart_g164bb39a266559574c252f11266809ff}
+
+
+Sets the default Content-Type for a given MIME part
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em part}]A valid MIME part object \item[{\em part}]Whether the Content-Type should be for composite or not \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]0 on success or -1 on failure\end{Desc}
+This function sets a default Content-Type according to RFC 2045 with a value of \char`\"{}text/plain; charset=\char`\"{}us-ascii\char`\"{}\char`\"{}. This function should only be used if the MIME part in question does not have a valid Content-Type specification. \ No newline at end of file
diff --git a/main/minimime/mm-docs/latex/group__mimeutil.tex b/main/minimime/mm-docs/latex/group__mimeutil.tex
new file mode 100644
index 000000000..6de259976
--- /dev/null
+++ b/main/minimime/mm-docs/latex/group__mimeutil.tex
@@ -0,0 +1,2 @@
+\section{MIME related utility functions}
+\label{group__mimeutil}\index{MIME related utility functions@{MIME related utility functions}}
diff --git a/main/minimime/mm-docs/latex/group__param.tex b/main/minimime/mm-docs/latex/group__param.tex
new file mode 100644
index 000000000..320dd398c
--- /dev/null
+++ b/main/minimime/mm-docs/latex/group__param.tex
@@ -0,0 +1,127 @@
+\section{Accessing and manipulating MIME parameters}
+\label{group__param}\index{Accessing and manipulating MIME parameters@{Accessing and manipulating MIME parameters}}
+\subsection*{Functions for manipulating MIME parameters}
+MIME parameters are properties attached to certain MIME headers, such as Content-Type and Content-Disposition. MIME parameters have a textual representations as in {\em name=value\/}. They contain important information about the MIME structure of a message, such as the boundary string used, which charset was used to encode the message and so on. This module provides simple to use functions to query or set MIME parameters.
+
+Each MIME header may hold an arbitrary amount of such parameters, which are delimeted by each other with a semicolon. \begin{CompactItemize}
+\item
+mm\_\-param $\ast$ {\bf mm\_\-param\_\-new} (void)
+\item
+void {\bf mm\_\-param\_\-free} (struct mm\_\-param $\ast$param)
+\item
+mm\_\-param $\ast$ {\bf mm\_\-param\_\-generate} (const char $\ast$name, const char $\ast$value)
+\item
+char $\ast$ {\bf mm\_\-param\_\-setname} (struct mm\_\-param $\ast$param, const char $\ast$name, int copy)
+\item
+char $\ast$ {\bf mm\_\-param\_\-setvalue} (struct mm\_\-param $\ast$param, const char $\ast$value, int copy)
+\item
+const char $\ast$ {\bf mm\_\-param\_\-getname} (struct mm\_\-param $\ast$param)
+\item
+const char $\ast$ {\bf mm\_\-param\_\-getvalue} (struct mm\_\-param $\ast$param)
+\end{CompactItemize}
+
+
+\subsection{Function Documentation}
+\index{param@{param}!mm_param_free@{mm\_\-param\_\-free}}
+\index{mm_param_free@{mm\_\-param\_\-free}!param@{param}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}void mm\_\-param\_\-free (struct mm\_\-param $\ast$ {\em param})}\label{group__param_g46339038e995799e6a3e37512f442fc9}
+
+
+Releases all memory associated with a MIME parameter object.
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em param}]A valid MIME parameter object to be freed \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]Nothing \end{Desc}
+\begin{Desc}
+\item[See also:]\doxyref{mm\_\-param\_\-new}{p.}{group__param_gd3ac756551bf5a29a07d5992bfdbde09} \end{Desc}
+\index{param@{param}!mm_param_generate@{mm\_\-param\_\-generate}}
+\index{mm_param_generate@{mm\_\-param\_\-generate}!param@{param}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}struct mm\_\-param$\ast$ mm\_\-param\_\-generate (const char $\ast$ {\em name}, const char $\ast$ {\em value})}\label{group__param_gd3970def45b8bede334f4b89a41dec15}
+
+
+Generates a new Content-Type parameter with the given name and value
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em name}]The name of the MIME parameter \item[{\em value}]The value of the MIME parameter \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]A new MIME parameter object \end{Desc}
+\begin{Desc}
+\item[See also:]\doxyref{mm\_\-param\_\-free}{p.}{group__param_g46339038e995799e6a3e37512f442fc9}
+
+\doxyref{mm\_\-param\_\-new}{p.}{group__param_gd3ac756551bf5a29a07d5992bfdbde09}\end{Desc}
+This function generates a new MIME parameter, with the name and value given as the arguments. The needed memory for the operation is allocated dynamically. It stores a copy of name and value in the actual object, so the memory holding the arguments can safely be freed after successfull return of this function. \index{param@{param}!mm_param_getname@{mm\_\-param\_\-getname}}
+\index{mm_param_getname@{mm\_\-param\_\-getname}!param@{param}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}const char$\ast$ mm\_\-param\_\-getname (struct mm\_\-param $\ast$ {\em param})}\label{group__param_g0e0ddccf47a2b1e0ad5bcc52c7b39753}
+
+
+Gets the name of a MIME parameter object
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em param}]A valid MIME parameter object \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]The name of the MIME parameter \end{Desc}
+\index{param@{param}!mm_param_getvalue@{mm\_\-param\_\-getvalue}}
+\index{mm_param_getvalue@{mm\_\-param\_\-getvalue}!param@{param}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}const char$\ast$ mm\_\-param\_\-getvalue (struct mm\_\-param $\ast$ {\em param})}\label{group__param_g3c6f8cddd409de3000c31584e140561e}
+
+
+Gets the value of a MIME parameter object
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em param}]A valid MIME parameter object \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]The value of the MIME parameter \end{Desc}
+\index{param@{param}!mm_param_new@{mm\_\-param\_\-new}}
+\index{mm_param_new@{mm\_\-param\_\-new}!param@{param}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}struct mm\_\-param$\ast$ mm\_\-param\_\-new (void)}\label{group__param_gd3ac756551bf5a29a07d5992bfdbde09}
+
+
+Creates a new object to hold a MIME parameter.
+
+\begin{Desc}
+\item[Returns:]An object representing a MIME parameter \end{Desc}
+\begin{Desc}
+\item[See also:]\doxyref{mm\_\-param\_\-free}{p.}{group__param_g46339038e995799e6a3e37512f442fc9} \end{Desc}
+\begin{Desc}
+\item[Note:]The allocated memory must later be freed using \doxyref{mm\_\-param\_\-free()}{p.}{group__param_g46339038e995799e6a3e37512f442fc9} \end{Desc}
+\index{param@{param}!mm_param_setname@{mm\_\-param\_\-setname}}
+\index{mm_param_setname@{mm\_\-param\_\-setname}!param@{param}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}char$\ast$ mm\_\-param\_\-setname (struct mm\_\-param $\ast$ {\em param}, const char $\ast$ {\em name}, int {\em copy})}\label{group__param_g2a266c63c7e89cf829b2af8e995e55e8}
+
+
+Sets the name of the given MIME parameter
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em param}]A valid MIME parameter object \item[{\em name}]The new name of the parameter \item[{\em copy}]If set to $>$ 0, copy the value stored in name \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]The address of the previous name for passing to free() \end{Desc}
+\index{param@{param}!mm_param_setvalue@{mm\_\-param\_\-setvalue}}
+\index{mm_param_setvalue@{mm\_\-param\_\-setvalue}!param@{param}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}char$\ast$ mm\_\-param\_\-setvalue (struct mm\_\-param $\ast$ {\em param}, const char $\ast$ {\em value}, int {\em copy})}\label{group__param_gca3e636ab5700462eb32ca5bc19e4cc6}
+
+
+Sets the value of the given MIME parameter
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em param}]A valid MIME parameter object \item[{\em name}]The new value for the parameter \item[{\em copy}]If set to $>$ 0, copy the value stored in value \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]The address of the previous value for passing to free() \end{Desc}
diff --git a/main/minimime/mm-docs/latex/group__util.tex b/main/minimime/mm-docs/latex/group__util.tex
new file mode 100644
index 000000000..00a3c20da
--- /dev/null
+++ b/main/minimime/mm-docs/latex/group__util.tex
@@ -0,0 +1,128 @@
+\section{General purpose utility functions}
+\label{group__util}\index{General purpose utility functions@{General purpose utility functions}}
+\subsection*{Utility functions}
+\begin{CompactItemize}
+\item
+void \textbf{xfree} (void $\ast$)\label{group__util_g35c4383ff0dee2de18985e6edfed1ae6}
+
+\item
+char $\ast$ \textbf{xstrdup} (const char $\ast$)\label{group__util_g2961ae74e91b0b28acdf9822438a581c}
+
+\end{CompactItemize}
+\subsection*{Functions}
+\begin{CompactItemize}
+\item
+void $\ast$ {\bf xmalloc} (size\_\-t size)
+\item
+void $\ast$ {\bf xrealloc} (void $\ast$p, size\_\-t size)
+\item
+char $\ast$ {\bf mm\_\-unquote} (const char $\ast$string)
+\item
+char $\ast$ {\bf mm\_\-uncomment} (const char $\ast$string)
+\item
+char $\ast$ {\bf xstrsep} (char $\ast$$\ast$stringp, const char $\ast$delim)
+\item
+char $\ast$ {\bf mm\_\-stripchars} (char $\ast$input, char $\ast$strip)
+\item
+char $\ast$ {\bf mm\_\-addchars} (char $\ast$input, char $\ast$add, u\_\-int16\_\-t linelength)
+\end{CompactItemize}
+
+
+\subsection{Function Documentation}
+\index{util@{util}!mm_addchars@{mm\_\-addchars}}
+\index{mm_addchars@{mm\_\-addchars}!util@{util}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}char$\ast$ mm\_\-addchars (char $\ast$ {\em input}, char $\ast$ {\em add}, u\_\-int16\_\-t {\em linelength})}\label{group__util_g0747d4b4e33644263e6d73d2d8d4818b}
+
+
+Adds characters to a string at given positions
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em input}]The string to which to add characters \item[{\em add}]The character string to add \item[{\em linelength}]The position where to add the character \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]A copy of the string with characters added\end{Desc}
+This function adds the characters add at each linelength positions and returns this new string. \index{util@{util}!mm_stripchars@{mm\_\-stripchars}}
+\index{mm_stripchars@{mm\_\-stripchars}!util@{util}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}char$\ast$ mm\_\-stripchars (char $\ast$ {\em input}, char $\ast$ {\em strip})}\label{group__util_gf62be7dd21e545f8db72f3c9e3b6a3c3}
+
+
+Strips a given character set from a string
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em input}]The string which to strip \item[{\em strip}]The character set to strip off \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]A copy of the original string with all chars stripped \end{Desc}
+\index{util@{util}!mm_uncomment@{mm\_\-uncomment}}
+\index{mm_uncomment@{mm\_\-uncomment}!util@{util}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}char$\ast$ mm\_\-uncomment (const char $\ast$ {\em string})}\label{group__util_g49c016ff4cfd02f1b019c4dce5aac357}
+
+
+Removes MIME comments from a string
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em string}]The string to uncomment \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]A pointer to the uncommented string or NULL on error. Sets mm\_\-errno.\end{Desc}
+This function removes MIME comments from a string (included in parantheses). It returns a pointer to a newly allocated memory region in which the uncommented string is stored. The returned string needs to be freed when it's not used anymore. \index{util@{util}!mm_unquote@{mm\_\-unquote}}
+\index{mm_unquote@{mm\_\-unquote}!util@{util}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}char$\ast$ mm\_\-unquote (const char $\ast$ {\em string})}\label{group__util_gf0f89a29a634f6f1f833abb1e214a6b1}
+
+
+Unquotes a string
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em string}]The quoted string to unquote \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]A pointer to the unquoted string\end{Desc}
+This function unquotes a string. That is, it returns a pointer to a newly allocated memory region in which the unquoted string is stored. Only leading and trailing double-qoutes are removed. The string needs to be freed when it is not needed anymore. \index{util@{util}!xmalloc@{xmalloc}}
+\index{xmalloc@{xmalloc}!util@{util}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}void$\ast$ xmalloc (size\_\-t {\em size})}\label{group__util_g2ff4ef58da7e543466e75f20f2a2d8b7}
+
+
+Allocates a block of memory
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em size}]The size of the memory region to allocate \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]A pointer to the allocated memory region\end{Desc}
+\doxyref{xmalloc()}{p.}{group__util_g2ff4ef58da7e543466e75f20f2a2d8b7} calls abort() if either the size argument is negative or the requested memory amount could not be allocated via an assert() call. \index{util@{util}!xrealloc@{xrealloc}}
+\index{xrealloc@{xrealloc}!util@{util}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}void$\ast$ xrealloc (void $\ast$ {\em p}, size\_\-t {\em size})}\label{group__util_ge14637b4672461f1f0bee822406d68dc}
+
+
+realloc() wrapper
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em p}]Pointer to a memory region which should be reallocated \item[{\em size}]The new size of the memory region \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]A pointer to the reallocated memory region\end{Desc}
+\doxyref{xrealloc()}{p.}{group__util_ge14637b4672461f1f0bee822406d68dc} is a wrapper around realloc() which calls abort() if either the size argument is negative or the requested memory amount could not be allocated. \index{util@{util}!xstrsep@{xstrsep}}
+\index{xstrsep@{xstrsep}!util@{util}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}char$\ast$ xstrsep (char $\ast$$\ast$ {\em stringp}, const char $\ast$ {\em delim})}\label{group__util_g3ae25483c8a42f6562f2a916a511228f}
+
+
+separate strings
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em stringp}]A pointer to the string being splitted \item[{\em delim}]The delimeter string\end{description}
+\end{Desc}
+This function works similar to strsep(), with the difference that delim is treated as a whole. \ No newline at end of file
diff --git a/main/minimime/mm-docs/latex/mm__codecs_8c.tex b/main/minimime/mm-docs/latex/mm__codecs_8c.tex
new file mode 100644
index 000000000..1dad6cf96
--- /dev/null
+++ b/main/minimime/mm-docs/latex/mm__codecs_8c.tex
@@ -0,0 +1,41 @@
+\section{mm\_\-codecs.c File Reference}
+\label{mm__codecs_8c}\index{mm_codecs.c@{mm\_\-codecs.c}}
+{\tt \#include $<$sys/types.h$>$}\par
+{\tt \#include $<$sys/stat.h$>$}\par
+{\tt \#include $<$stdio.h$>$}\par
+{\tt \#include $<$stdlib.h$>$}\par
+{\tt \#include $<$unistd.h$>$}\par
+{\tt \#include $<$fcntl.h$>$}\par
+{\tt \#include $<$string.h$>$}\par
+{\tt \#include $<$assert.h$>$}\par
+{\tt \#include \char`\"{}mm\_\-internal.h\char`\"{}}\par
+{\tt \#include \char`\"{}mm\_\-util.h\char`\"{}}\par
+\subsection*{Functions}
+\begin{Indent}{\bf Codec manipulation}\par
+\begin{CompactItemize}
+\item
+int {\bf mm\_\-codec\_\-hasdecoder} (const char $\ast$encoding)
+\item
+int {\bf mm\_\-codec\_\-hasencoder} (const char $\ast$encoding)
+\item
+int {\bf mm\_\-codec\_\-isregistered} (const char $\ast$encoding)
+\item
+int {\bf mm\_\-codec\_\-register} (const char $\ast$encoding, char $\ast$($\ast$encoder)(char $\ast$data, u\_\-int32\_\-t i), char $\ast$($\ast$decoder)(char $\ast$data))
+\item
+int {\bf mm\_\-codec\_\-unregister} (const char $\ast$encoding)
+\item
+int {\bf mm\_\-codec\_\-unregisterall} (void)
+\item
+void {\bf mm\_\-codec\_\-registerdefaultcodecs} (void)
+\end{CompactItemize}
+\end{Indent}
+\subsection*{Variables}
+\begin{CompactItemize}
+\item
+mm\_\-codecs \textbf{codecs}\label{mm__codecs_8c_b669b6dc7c7d10408d8da81b3f1a30d3}
+
+\end{CompactItemize}
+
+
+\subsection{Detailed Description}
+This module contains functions to manipulate Mini\-MIME codecs \ No newline at end of file
diff --git a/main/minimime/mm-docs/latex/mm__contenttype_8c.tex b/main/minimime/mm-docs/latex/mm__contenttype_8c.tex
new file mode 100644
index 000000000..71a88cf62
--- /dev/null
+++ b/main/minimime/mm-docs/latex/mm__contenttype_8c.tex
@@ -0,0 +1,61 @@
+\section{mm\_\-contenttype.c File Reference}
+\label{mm__contenttype_8c}\index{mm_contenttype.c@{mm\_\-contenttype.c}}
+{\tt \#include $<$stdio.h$>$}\par
+{\tt \#include $<$stdlib.h$>$}\par
+{\tt \#include $<$stdarg.h$>$}\par
+{\tt \#include $<$string.h$>$}\par
+{\tt \#include $<$ctype.h$>$}\par
+{\tt \#include $<$assert.h$>$}\par
+{\tt \#include \char`\"{}mm\_\-internal.h\char`\"{}}\par
+{\tt \#include \char`\"{}mm\_\-util.h\char`\"{}}\par
+\subsection*{Data Structures}
+\begin{CompactItemize}
+\item
+struct \textbf{mm\_\-encoding\_\-mappings}
+\end{CompactItemize}
+\subsection*{Functions}
+\begin{Indent}{\bf Functions for manipulating Content-Type objects}\par
+\begin{CompactItemize}
+\item
+mm\_\-content $\ast$ {\bf mm\_\-content\_\-new} (void)
+\item
+void {\bf mm\_\-content\_\-free} (struct mm\_\-content $\ast$ct)
+\item
+int {\bf mm\_\-content\_\-attachparam} (struct mm\_\-content $\ast$ct, struct mm\_\-param $\ast$param)
+\item
+char $\ast$ {\bf mm\_\-content\_\-getparambyname} (struct mm\_\-content $\ast$ct, const char $\ast$name)
+\item
+mm\_\-param $\ast$ \textbf{mm\_\-content\_\-getparamobjbyname} (struct mm\_\-content $\ast$ct, const char $\ast$name)\label{group__contenttype_g1ba63e679d2b49aceb6cfec8a6752581}
+
+\item
+int {\bf mm\_\-content\_\-setmaintype} (struct mm\_\-content $\ast$ct, char $\ast$value, int copy)
+\item
+char $\ast$ {\bf mm\_\-content\_\-getmaintype} (struct mm\_\-content $\ast$ct)
+\item
+char $\ast$ {\bf mm\_\-content\_\-getsubtype} (struct mm\_\-content $\ast$ct)
+\item
+char $\ast$ \textbf{mm\_\-content\_\-gettype} (struct mm\_\-content $\ast$ct)\label{group__contenttype_ga6d8453eb35bd695c4944e53b7040b65}
+
+\item
+int {\bf mm\_\-content\_\-setsubtype} (struct mm\_\-content $\ast$ct, char $\ast$value, int copy)
+\item
+int \textbf{mm\_\-content\_\-settype} (struct mm\_\-content $\ast$ct, const char $\ast$fmt,...)\label{group__contenttype_g878686678ea2ba97aa8edb1206a564d8}
+
+\item
+int {\bf mm\_\-content\_\-iscomposite} (struct mm\_\-content $\ast$ct)
+\item
+int {\bf mm\_\-content\_\-isvalidencoding} (const char $\ast$encoding)
+\item
+int {\bf mm\_\-content\_\-setencoding} (struct mm\_\-content $\ast$ct, const char $\ast$encoding)
+\item
+int {\bf mm\_\-content\_\-getencoding} (struct mm\_\-content $\ast$ct, const char $\ast$encoding)
+\item
+char $\ast$ {\bf mm\_\-content\_\-paramstostring} (struct mm\_\-content $\ast$ct)
+\item
+char $\ast$ {\bf mm\_\-content\_\-tostring} (struct mm\_\-content $\ast$ct)
+\end{CompactItemize}
+\end{Indent}
+
+
+\subsection{Detailed Description}
+This module contains functions for manipulating Content-Type objects. \ No newline at end of file
diff --git a/main/minimime/mm-docs/latex/mm__context_8c.tex b/main/minimime/mm-docs/latex/mm__context_8c.tex
new file mode 100644
index 000000000..78ba141e5
--- /dev/null
+++ b/main/minimime/mm-docs/latex/mm__context_8c.tex
@@ -0,0 +1,44 @@
+\section{mm\_\-context.c File Reference}
+\label{mm__context_8c}\index{mm_context.c@{mm\_\-context.c}}
+{\tt \#include $<$stdio.h$>$}\par
+{\tt \#include $<$stdlib.h$>$}\par
+{\tt \#include $<$stdarg.h$>$}\par
+{\tt \#include $<$string.h$>$}\par
+{\tt \#include $<$assert.h$>$}\par
+{\tt \#include \char`\"{}mm\_\-internal.h\char`\"{}}\par
+\subsection*{Functions}
+\begin{Indent}{\bf Manipulating Mini\-MIME contexts}\par
+\begin{CompactItemize}
+\item
+MM\_\-CTX $\ast$ {\bf mm\_\-context\_\-new} (void)
+\item
+void {\bf mm\_\-context\_\-free} (MM\_\-CTX $\ast$ctx)
+\item
+int {\bf mm\_\-context\_\-attachpart} (MM\_\-CTX $\ast$ctx, struct mm\_\-mimepart $\ast$part)
+\item
+int {\bf mm\_\-context\_\-attachpart\_\-after} (MM\_\-CTX $\ast$ctx, struct mm\_\-mimepart $\ast$part, int pos)
+\item
+int {\bf mm\_\-context\_\-deletepart} (MM\_\-CTX $\ast$ctx, int which, int freemem)
+\item
+int {\bf mm\_\-context\_\-countparts} (MM\_\-CTX $\ast$ctx)
+\item
+mm\_\-mimepart $\ast$ {\bf mm\_\-context\_\-getpart} (MM\_\-CTX $\ast$ctx, int which)
+\item
+int {\bf mm\_\-context\_\-iscomposite} (MM\_\-CTX $\ast$ctx)
+\item
+int {\bf mm\_\-context\_\-haswarnings} (MM\_\-CTX $\ast$ctx)
+\item
+int {\bf mm\_\-context\_\-generateboundary} (MM\_\-CTX $\ast$ctx)
+\item
+int {\bf mm\_\-context\_\-setpreamble} (MM\_\-CTX $\ast$ctx, char $\ast$preamble)
+\item
+char $\ast$ \textbf{mm\_\-context\_\-getpreamble} (MM\_\-CTX $\ast$ctx)\label{group__context_g1ebbdd51106ccdee77ca421f9692bde7}
+
+\item
+int {\bf mm\_\-context\_\-flatten} (MM\_\-CTX $\ast$ctx, char $\ast$$\ast$flat, size\_\-t $\ast$length, int flags)
+\end{CompactItemize}
+\end{Indent}
+
+
+\subsection{Detailed Description}
+Modules for manipulating Mini\-MIME contexts \ No newline at end of file
diff --git a/main/minimime/mm-docs/latex/mm__envelope_8c.tex b/main/minimime/mm-docs/latex/mm__envelope_8c.tex
new file mode 100644
index 000000000..841a6b550
--- /dev/null
+++ b/main/minimime/mm-docs/latex/mm__envelope_8c.tex
@@ -0,0 +1,25 @@
+\section{mm\_\-envelope.c File Reference}
+\label{mm__envelope_8c}\index{mm_envelope.c@{mm\_\-envelope.c}}
+{\tt \#include $<$stdio.h$>$}\par
+{\tt \#include $<$stdlib.h$>$}\par
+{\tt \#include $<$stdarg.h$>$}\par
+{\tt \#include $<$string.h$>$}\par
+{\tt \#include $<$ctype.h$>$}\par
+{\tt \#include $<$assert.h$>$}\par
+{\tt \#include \char`\"{}mm\_\-internal.h\char`\"{}}\par
+{\tt \#include \char`\"{}mm\_\-util.h\char`\"{}}\par
+\subsection*{Functions}
+\begin{Indent}{\bf Accessing and manipulating a message's envelope}\par
+\begin{CompactItemize}
+\item
+int {\bf mm\_\-envelope\_\-getheaders} (MM\_\-CTX $\ast$ctx, char $\ast$$\ast$result, size\_\-t $\ast$length)
+\item
+int {\bf mm\_\-envelope\_\-setheader} (MM\_\-CTX $\ast$ctx, const char $\ast$name, const char $\ast$fmt,...)
+\item
+int {\bf mm\_\-envelope\_\-getrecipients} (MM\_\-CTX $\ast$ctx, char $\ast$$\ast$result, size\_\-t $\ast$length)
+\end{CompactItemize}
+\end{Indent}
+
+
+\subsection{Detailed Description}
+This module contains functions for accessing a message's envelope. This are mainly wrapper functions for easy access. \ No newline at end of file
diff --git a/main/minimime/mm-docs/latex/mm__error_8c.tex b/main/minimime/mm-docs/latex/mm__error_8c.tex
new file mode 100644
index 000000000..47ae03314
--- /dev/null
+++ b/main/minimime/mm-docs/latex/mm__error_8c.tex
@@ -0,0 +1,29 @@
+\section{mm\_\-error.c File Reference}
+\label{mm__error_8c}\index{mm_error.c@{mm\_\-error.c}}
+{\tt \#include $<$stdio.h$>$}\par
+{\tt \#include $<$stdlib.h$>$}\par
+{\tt \#include $<$stdarg.h$>$}\par
+{\tt \#include $<$string.h$>$}\par
+{\tt \#include $<$assert.h$>$}\par
+{\tt \#include $<$errno.h$>$}\par
+{\tt \#include \char`\"{}mm\_\-internal.h\char`\"{}}\par
+{\tt \#include \char`\"{}mm\_\-util.h\char`\"{}}\par
+\subsection*{Functions}
+\begin{CompactItemize}
+\item
+void {\bf mm\_\-error\_\-init} (void)
+\item
+void {\bf mm\_\-error\_\-setmsg} (const char $\ast$fmt,...)
+\item
+void \textbf{mm\_\-error\_\-setlineno} (int lineno)\label{mm__error_8c_190c991d7bb378b6cd6f995ffc3011f7}
+
+\item
+char $\ast$ {\bf mm\_\-error\_\-string} (void)
+\item
+int \textbf{mm\_\-error\_\-lineno} (void)\label{mm__error_8c_c84acacac29f1e6efd10bb3a89eab272}
+
+\end{CompactItemize}
+
+
+\subsection{Detailed Description}
+This module contains functions for Mini\-MIME error information/manipulation \ No newline at end of file
diff --git a/main/minimime/mm-docs/latex/mm__header_8c.tex b/main/minimime/mm-docs/latex/mm__header_8c.tex
new file mode 100644
index 000000000..651a5a4e9
--- /dev/null
+++ b/main/minimime/mm-docs/latex/mm__header_8c.tex
@@ -0,0 +1,63 @@
+\section{mm\_\-header.c File Reference}
+\label{mm__header_8c}\index{mm_header.c@{mm\_\-header.c}}
+{\tt \#include $<$stdio.h$>$}\par
+{\tt \#include $<$stdlib.h$>$}\par
+{\tt \#include $<$stdarg.h$>$}\par
+{\tt \#include $<$string.h$>$}\par
+{\tt \#include $<$ctype.h$>$}\par
+{\tt \#include $<$assert.h$>$}\par
+{\tt \#include \char`\"{}mm\_\-internal.h\char`\"{}}\par
+{\tt \#include \char`\"{}mm\_\-util.h\char`\"{}}\par
+\subsection*{Functions}
+\begin{CompactItemize}
+\item
+mm\_\-mimeheader $\ast$ {\bf mm\_\-mimeheader\_\-new} (void)
+\item
+void {\bf mm\_\-mimeheader\_\-free} (struct mm\_\-mimeheader $\ast$header)
+\item
+mm\_\-mimeheader $\ast$ {\bf mm\_\-mimeheader\_\-generate} (const char $\ast$name, const char $\ast$value)
+\item
+int \textbf{mm\_\-mimeheader\_\-uncomment} (struct mm\_\-mimeheader $\ast$header)\label{mm__header_8c_26657e44385646fde63712d7110492d7}
+
+\item
+int \textbf{mm\_\-mimeheader\_\-uncommentbyname} (struct mm\_\-mimepart $\ast$part, const char $\ast$name)\label{mm__header_8c_2081ee4c43e88d5a318a783069a5d471}
+
+\item
+int \textbf{mm\_\-mimeheader\_\-uncommentall} (struct mm\_\-mimepart $\ast$part)\label{mm__header_8c_9f9bcb0fb26461bd349c15366748ecb7}
+
+\end{CompactItemize}
+
+
+\subsection{Detailed Description}
+This module contains functions for manipulating MIME headers
+
+\subsection{Function Documentation}
+\index{mm_header.c@{mm\_\-header.c}!mm_mimeheader_free@{mm\_\-mimeheader\_\-free}}
+\index{mm_mimeheader_free@{mm\_\-mimeheader\_\-free}!mm_header.c@{mm\_\-header.c}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}void mm\_\-mimeheader\_\-free (struct mm\_\-mimeheader $\ast$ {\em header})}\label{mm__header_8c_61e3e62728f720ac381196ec59303064}
+
+
+Frees a MIME header object
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em header}]The MIME header object which to free \end{description}
+\end{Desc}
+\index{mm_header.c@{mm\_\-header.c}!mm_mimeheader_generate@{mm\_\-mimeheader\_\-generate}}
+\index{mm_mimeheader_generate@{mm\_\-mimeheader\_\-generate}!mm_header.c@{mm\_\-header.c}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}struct mm\_\-mimeheader$\ast$ mm\_\-mimeheader\_\-generate (const char $\ast$ {\em name}, const char $\ast$ {\em value})}\label{mm__header_8c_07a7f7dcebc91aa86f5478e1d84341a1}
+
+
+Creates a new MIME header, but does no checks whatsoever (create as-is) \index{mm_header.c@{mm\_\-header.c}!mm_mimeheader_new@{mm\_\-mimeheader\_\-new}}
+\index{mm_mimeheader_new@{mm\_\-mimeheader\_\-new}!mm_header.c@{mm\_\-header.c}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}struct mm\_\-mimeheader$\ast$ mm\_\-mimeheader\_\-new (void)}\label{mm__header_8c_2f2c5f2f640111caf3096ed46b5986a4}
+
+
+Creates a new MIME header object
+
+\begin{Desc}
+\item[Returns:]A new and initialized MIME header object \end{Desc}
+\begin{Desc}
+\item[See also:]\doxyref{mm\_\-mimeheader\_\-free}{p.}{mm__header_8c_61e3e62728f720ac381196ec59303064}\end{Desc}
+This function creates and initializes a new MIME header object, which must later be freed using \doxyref{mm\_\-mimeheader\_\-free()}{p.}{mm__header_8c_61e3e62728f720ac381196ec59303064} \ No newline at end of file
diff --git a/main/minimime/mm-docs/latex/mm__internal_8h.tex b/main/minimime/mm-docs/latex/mm__internal_8h.tex
new file mode 100644
index 000000000..017f05bc0
--- /dev/null
+++ b/main/minimime/mm-docs/latex/mm__internal_8h.tex
@@ -0,0 +1,45 @@
+\section{mm\_\-internal.h File Reference}
+\label{mm__internal_8h}\index{mm_internal.h@{mm\_\-internal.h}}
+{\tt \#include \char`\"{}mm.h\char`\"{}}\par
+\subsection*{Defines}
+\begin{CompactItemize}
+\item
+\#define \textbf{debugp}(m,...)
+\end{CompactItemize}
+\subsection*{Functions}
+\begin{Indent}{\bf Utility functions}\par
+\begin{CompactItemize}
+\item
+void $\ast$ {\bf xmalloc} (size\_\-t)
+\item
+void $\ast$ {\bf xrealloc} (void $\ast$, size\_\-t)
+\item
+void \textbf{xfree} (void $\ast$)\label{group__util_g35c4383ff0dee2de18985e6edfed1ae6}
+
+\item
+char $\ast$ \textbf{xstrdup} (const char $\ast$)\label{group__util_g2961ae74e91b0b28acdf9822438a581c}
+
+\item
+char $\ast$ {\bf xstrsep} (char $\ast$$\ast$, const char $\ast$)
+\end{CompactItemize}
+\end{Indent}
+
+
+\subsection{Detailed Description}
+Data definitions for Mini\-MIME
+
+\subsection{Define Documentation}
+\index{mm_internal.h@{mm\_\-internal.h}!debugp@{debugp}}
+\index{debugp@{debugp}!mm_internal.h@{mm\_\-internal.h}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}\#define debugp(m, {\em ...})}\label{mm__internal_8h_089dd7bda22f552c35ebdc06a8849c56}
+
+
+\textbf{Value:}
+
+\begin{Code}\begin{verbatim}do { \
+ fprintf(stderr, "%s:%d:: ", __FILE__, __LINE__); \
+ fprintf(stderr, m, ## __VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+ fflush(stderr); \
+} while (0);
+\end{verbatim}\end{Code}
diff --git a/main/minimime/mm-docs/latex/mm__mimepart_8c.tex b/main/minimime/mm-docs/latex/mm__mimepart_8c.tex
new file mode 100644
index 000000000..247887efd
--- /dev/null
+++ b/main/minimime/mm-docs/latex/mm__mimepart_8c.tex
@@ -0,0 +1,69 @@
+\section{mm\_\-mimepart.c File Reference}
+\label{mm__mimepart_8c}\index{mm_mimepart.c@{mm\_\-mimepart.c}}
+{\tt \#include $<$sys/types.h$>$}\par
+{\tt \#include $<$sys/stat.h$>$}\par
+{\tt \#include $<$stdio.h$>$}\par
+{\tt \#include $<$stdlib.h$>$}\par
+{\tt \#include $<$string.h$>$}\par
+{\tt \#include $<$unistd.h$>$}\par
+{\tt \#include $<$fcntl.h$>$}\par
+{\tt \#include $<$ctype.h$>$}\par
+{\tt \#include $<$assert.h$>$}\par
+{\tt \#include \char`\"{}mm\_\-internal.h\char`\"{}}\par
+\subsection*{Functions}
+\begin{Indent}{\bf Creating and destroying MIME parts}\par
+\begin{CompactItemize}
+\item
+mm\_\-mimepart $\ast$ {\bf mm\_\-mimepart\_\-new} (void)
+\item
+mm\_\-mimepart $\ast$ {\bf mm\_\-mimepart\_\-fromfile} (const char $\ast$filename)
+\item
+void {\bf mm\_\-mimepart\_\-free} (struct mm\_\-mimepart $\ast$part)
+\end{CompactItemize}
+\end{Indent}
+\begin{Indent}{\bf Accessing the MIME part's mail header}\par
+\begin{CompactItemize}
+\item
+int {\bf mm\_\-mimepart\_\-attachheader} (struct mm\_\-mimepart $\ast$part, struct mm\_\-mimeheader $\ast$header)
+\item
+int {\bf mm\_\-mimepart\_\-countheaders} (struct mm\_\-mimepart $\ast$part)
+\item
+int {\bf mm\_\-mimepart\_\-countheaderbyname} (struct mm\_\-mimepart $\ast$part, const char $\ast$name)
+\item
+mm\_\-mimeheader $\ast$ {\bf mm\_\-mimepart\_\-getheaderbyname} (struct mm\_\-mimepart $\ast$part, const char $\ast$name, int idx)
+\item
+const char $\ast$ {\bf mm\_\-mimepart\_\-getheadervalue} (struct mm\_\-mimepart $\ast$part, const char $\ast$name, int idx)
+\item
+int {\bf mm\_\-mimepart\_\-headers\_\-start} (struct mm\_\-mimepart $\ast$part, struct mm\_\-mimeheader $\ast$$\ast$id)
+\item
+mm\_\-mimeheader $\ast$ {\bf mm\_\-mimepart\_\-headers\_\-next} (struct mm\_\-mimepart $\ast$part, struct mm\_\-mimeheader $\ast$$\ast$id)
+\end{CompactItemize}
+\end{Indent}
+\begin{Indent}{\bf Accessing and manipulating the MIME part's body}\par
+\begin{CompactItemize}
+\item
+char $\ast$ {\bf mm\_\-mimepart\_\-getbody} (struct mm\_\-mimepart $\ast$part, int opaque)
+\item
+void {\bf mm\_\-mimepart\_\-setbody} (struct mm\_\-mimepart $\ast$part, const char $\ast$data, int opaque)
+\item
+size\_\-t {\bf mm\_\-mimepart\_\-getlength} (struct mm\_\-mimepart $\ast$part)
+\item
+char $\ast$ {\bf mm\_\-mimepart\_\-decode} (struct mm\_\-mimepart $\ast$part)
+\item
+int {\bf mm\_\-mimepart\_\-flatten} (struct mm\_\-mimepart $\ast$part, char $\ast$$\ast$result, size\_\-t $\ast$length, int opaque)
+\item
+int {\bf mm\_\-mimepart\_\-setdefaultcontenttype} (struct mm\_\-mimepart $\ast$part, int composite)
+\end{CompactItemize}
+\end{Indent}
+\begin{Indent}{\bf Accessing the MIME part's Content-Type information}\par
+\begin{CompactItemize}
+\item
+void {\bf mm\_\-mimepart\_\-attachcontenttype} (struct mm\_\-mimepart $\ast$part, struct mm\_\-content $\ast$ct)
+\item
+mm\_\-content $\ast$ {\bf mm\_\-mimepart\_\-gettype} (struct mm\_\-mimepart $\ast$part)
+\end{CompactItemize}
+\end{Indent}
+
+
+\subsection{Detailed Description}
+This module contains functions for manipulating MIME header objects. \ No newline at end of file
diff --git a/main/minimime/mm-docs/latex/mm__mimeutil_8c.tex b/main/minimime/mm-docs/latex/mm__mimeutil_8c.tex
new file mode 100644
index 000000000..5ac2599b6
--- /dev/null
+++ b/main/minimime/mm-docs/latex/mm__mimeutil_8c.tex
@@ -0,0 +1,50 @@
+\section{mm\_\-mimeutil.c File Reference}
+\label{mm__mimeutil_8c}\index{mm_mimeutil.c@{mm\_\-mimeutil.c}}
+{\tt \#include $<$sys/time.h$>$}\par
+{\tt \#include $<$stdio.h$>$}\par
+{\tt \#include $<$stdlib.h$>$}\par
+{\tt \#include $<$string.h$>$}\par
+{\tt \#include $<$time.h$>$}\par
+{\tt \#include $<$assert.h$>$}\par
+{\tt \#include \char`\"{}mm\_\-internal.h\char`\"{}}\par
+\subsection*{Defines}
+\begin{CompactItemize}
+\item
+\#define \textbf{MM\_\-DATE\_\-LENGTH}~50\label{mm__mimeutil_8c_257774e1a30f8190b3d99891be64210a}
+
+\end{CompactItemize}
+\subsection*{Functions}
+\begin{CompactItemize}
+\item
+int {\bf mm\_\-mimeutil\_\-gendate} (char $\ast$$\ast$result)
+\item
+int \textbf{mm\_\-mimeutil\_\-genboundary} (char $\ast$prefix, size\_\-t length, char $\ast$$\ast$result)\label{mm__mimeutil_8c_a72e503ba7ce2552456c6bd5935febe9}
+
+\end{CompactItemize}
+
+
+\subsection{Detailed Description}
+This module contains various MIME related utility functions.
+
+\subsection{Function Documentation}
+\index{mm_mimeutil.c@{mm\_\-mimeutil.c}!mm_mimeutil_gendate@{mm\_\-mimeutil\_\-gendate}}
+\index{mm_mimeutil_gendate@{mm\_\-mimeutil\_\-gendate}!mm_mimeutil.c@{mm\_\-mimeutil.c}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-mimeutil\_\-gendate (char $\ast$$\ast$ {\em result})}\label{mm__mimeutil_8c_a7b7f63b42dfa7a7f907b615aa4cd057}
+
+
+Generates an RFC 2822 conform date string
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em timezone}]Whether to include timezone information \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]A pointer to the actual date string \end{Desc}
+\begin{Desc}
+\item[Note:]The pointer returned must be freed some time\end{Desc}
+This function generates an RFC 2822 conform date string to use in message headers. It allocates memory to hold the string and returns a pointer to it. The generated date is in the format (example):
+
+Thu, 25 December 2003 16:35:22 +0100 (CET)
+
+This function dynamically allocates memory and returns a pointer to it. This memory should be released with free() once not needed anymore. \ No newline at end of file
diff --git a/main/minimime/mm-docs/latex/mm__param_8c.tex b/main/minimime/mm-docs/latex/mm__param_8c.tex
new file mode 100644
index 000000000..a3bc27e19
--- /dev/null
+++ b/main/minimime/mm-docs/latex/mm__param_8c.tex
@@ -0,0 +1,38 @@
+\section{mm\_\-param.c File Reference}
+\label{mm__param_8c}\index{mm_param.c@{mm\_\-param.c}}
+{\tt \#include $<$sys/types.h$>$}\par
+{\tt \#include $<$sys/stat.h$>$}\par
+{\tt \#include $<$stdio.h$>$}\par
+{\tt \#include $<$stdlib.h$>$}\par
+{\tt \#include $<$unistd.h$>$}\par
+{\tt \#include $<$fcntl.h$>$}\par
+{\tt \#include $<$string.h$>$}\par
+{\tt \#include $<$ctype.h$>$}\par
+{\tt \#include $<$assert.h$>$}\par
+{\tt \#include \char`\"{}mm\_\-internal.h\char`\"{}}\par
+{\tt \#include \char`\"{}mm\_\-util.h\char`\"{}}\par
+\subsection*{Functions}
+\begin{Indent}{\bf Functions for manipulating MIME parameters}\par
+{\em MIME parameters are properties attached to certain MIME headers, such as Content-Type and Content-Disposition. MIME parameters have a textual representations as in {\em name=value\/}. They contain important information about the MIME structure of a message, such as the boundary string used, which charset was used to encode the message and so on. This module provides simple to use functions to query or set MIME parameters.
+
+Each MIME header may hold an arbitrary amount of such parameters, which are delimeted by each other with a semicolon. }\begin{CompactItemize}
+\item
+mm\_\-param $\ast$ {\bf mm\_\-param\_\-new} (void)
+\item
+void {\bf mm\_\-param\_\-free} (struct mm\_\-param $\ast$param)
+\item
+mm\_\-param $\ast$ {\bf mm\_\-param\_\-generate} (const char $\ast$name, const char $\ast$value)
+\item
+char $\ast$ {\bf mm\_\-param\_\-setname} (struct mm\_\-param $\ast$param, const char $\ast$name, int copy)
+\item
+char $\ast$ {\bf mm\_\-param\_\-setvalue} (struct mm\_\-param $\ast$param, const char $\ast$value, int copy)
+\item
+const char $\ast$ {\bf mm\_\-param\_\-getname} (struct mm\_\-param $\ast$param)
+\item
+const char $\ast$ {\bf mm\_\-param\_\-getvalue} (struct mm\_\-param $\ast$param)
+\end{CompactItemize}
+\end{Indent}
+
+
+\subsection{Detailed Description}
+Functions to manipulate MIME parameters \ No newline at end of file
diff --git a/main/minimime/mm-docs/latex/mm__parse_8c.tex b/main/minimime/mm-docs/latex/mm__parse_8c.tex
new file mode 100644
index 000000000..36613ad6c
--- /dev/null
+++ b/main/minimime/mm-docs/latex/mm__parse_8c.tex
@@ -0,0 +1,90 @@
+\section{mm\_\-parse.c File Reference}
+\label{mm__parse_8c}\index{mm_parse.c@{mm\_\-parse.c}}
+{\tt \#include $<$sys/types.h$>$}\par
+{\tt \#include $<$sys/stat.h$>$}\par
+{\tt \#include $<$stdio.h$>$}\par
+{\tt \#include $<$stdlib.h$>$}\par
+{\tt \#include $<$unistd.h$>$}\par
+{\tt \#include $<$fcntl.h$>$}\par
+{\tt \#include $<$string.h$>$}\par
+{\tt \#include $<$ctype.h$>$}\par
+{\tt \#include $<$assert.h$>$}\par
+{\tt \#include \char`\"{}mm\_\-internal.h\char`\"{}}\par
+{\tt \#include \char`\"{}mm\_\-util.h\char`\"{}}\par
+{\tt \#include \char`\"{}mimeparser.h\char`\"{}}\par
+{\tt \#include \char`\"{}mimeparser.tab.h\char`\"{}}\par
+\subsection*{Functions}
+\begin{CompactItemize}
+\item
+void {\bf PARSER\_\-initialize} (MM\_\-CTX $\ast$, int)
+\item
+void \textbf{PARSER\_\-setbuffer} (const char $\ast$)\label{mm__parse_8c_92d7d8e20b6def16fcf2649e0d88651f}
+
+\item
+void \textbf{PARSER\_\-setfp} (FILE $\ast$)\label{mm__parse_8c_04446354e4248226578b90007d728a7b}
+
+\item
+int {\bf mm\_\-parse\_\-mem} (MM\_\-CTX $\ast$ctx, const char $\ast$text, int parsemode, int flags)
+\item
+int {\bf mm\_\-parse\_\-file} (MM\_\-CTX $\ast$ctx, const char $\ast$filename, int parsemode, int flags)
+\end{CompactItemize}
+
+
+\subsection{Detailed Description}
+Functions to parse MIME messages
+
+\subsection{Function Documentation}
+\index{mm_parse.c@{mm\_\-parse.c}!mm_parse_file@{mm\_\-parse\_\-file}}
+\index{mm_parse_file@{mm\_\-parse\_\-file}!mm_parse.c@{mm\_\-parse.c}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-parse\_\-file (MM\_\-CTX $\ast$ {\em ctx}, const char $\ast$ {\em filename}, int {\em parsemode}, int {\em flags})}\label{mm__parse_8c_cc9f623682b05f330c46e72e4e9d66cc}
+
+
+Parses a file into a Mini\-MIME context
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ctx}]A valid Mini\-MIME context object \item[{\em filename}]The name of the file to parse \item[{\em parsemode}]The parsemode \item[{\em flags}]The flags to pass to the parser \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]0 on success or -1 on failure \end{Desc}
+\begin{Desc}
+\item[Note:]Sets mm\_\-errno if an error occurs\end{Desc}
+This function parses a MIME message, stored in the filesystem according to the parseflags and stores the results in the Mini\-MIME context specified by ctx.
+
+The following modes can be used to specify how the message should be parsed:
+
+\begin{itemize}
+\item MM\_\-PARSE\_\-STRICT: Do not tolerate MIME violations\item MM\_\-PARSE\_\-LOOSE: Tolerate as much MIME violations as possible\end{itemize}
+
+
+The context needs to be initialized before using \doxyref{mm\_\-context\_\-new()}{p.}{group__context_g919fd41f85534d9c87c256857faa2610} and may be freed using \doxyref{mm\_\-context\_\-free()}{p.}{group__context_g76392d5269e9ef340c2f5f8336f7193b}. \index{mm_parse.c@{mm\_\-parse.c}!mm_parse_mem@{mm\_\-parse\_\-mem}}
+\index{mm_parse_mem@{mm\_\-parse\_\-mem}!mm_parse.c@{mm\_\-parse.c}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}int mm\_\-parse\_\-mem (MM\_\-CTX $\ast$ {\em ctx}, const char $\ast$ {\em text}, int {\em parsemode}, int {\em flags})}\label{mm__parse_8c_58c960b6017f13d4e4ec5f09b3c38495}
+
+
+Parses a NUL-terminated string into a Mini\-MIME context
+
+\begin{Desc}
+\item[Parameters:]
+\begin{description}
+\item[{\em ctx}]A valid Mini\-MIME context object \item[{\em text}]The NUL-terminated string to parse \item[{\em parsemode}]The parsemode \item[{\em flags}]The flags to pass to the parser \end{description}
+\end{Desc}
+\begin{Desc}
+\item[Returns:]0 on success or -1 on failure \end{Desc}
+\begin{Desc}
+\item[Note:]Sets mm\_\-errno if an error occurs\end{Desc}
+This function parses a MIME message, stored in the memory region pointed to by text (must be NUL-terminated) according to the parseflags and stores the results in the Mini\-MIME context specified by ctx.
+
+The following modes can be used to specify how the message should be parsed:
+
+\begin{itemize}
+\item MM\_\-PARSE\_\-STRICT: Do not tolerate MIME violations\item MM\_\-PARSE\_\-LOOSE: Tolerate as much MIME violations as possible\end{itemize}
+
+
+The context needs to be initialized before using \doxyref{mm\_\-context\_\-new()}{p.}{group__context_g919fd41f85534d9c87c256857faa2610} and may be freed using \doxyref{mm\_\-context\_\-free()}{p.}{group__context_g76392d5269e9ef340c2f5f8336f7193b}. \index{mm_parse.c@{mm\_\-parse.c}!PARSER_initialize@{PARSER\_\-initialize}}
+\index{PARSER_initialize@{PARSER\_\-initialize}!mm_parse.c@{mm\_\-parse.c}}
+\subsubsection{\setlength{\rightskip}{0pt plus 5cm}void PARSER\_\-initialize (MM\_\-CTX $\ast$ {\em newctx}, int {\em mode})}\label{mm__parse_8c_187cf71c0f6c2da1384823e3f20aa1a2}
+
+
+Initializes the parser engine. \ No newline at end of file
diff --git a/main/minimime/mm-docs/latex/mm__util_8c.tex b/main/minimime/mm-docs/latex/mm__util_8c.tex
new file mode 100644
index 000000000..929efe9bc
--- /dev/null
+++ b/main/minimime/mm-docs/latex/mm__util_8c.tex
@@ -0,0 +1,38 @@
+\section{mm\_\-util.c File Reference}
+\label{mm__util_8c}\index{mm_util.c@{mm\_\-util.c}}
+{\tt \#include $<$stdio.h$>$}\par
+{\tt \#include $<$stdlib.h$>$}\par
+{\tt \#include $<$string.h$>$}\par
+{\tt \#include $<$time.h$>$}\par
+{\tt \#include $<$assert.h$>$}\par
+{\tt \#include \char`\"{}mm\_\-internal.h\char`\"{}}\par
+\subsection*{Functions}
+\begin{CompactItemize}
+\item
+void $\ast$ {\bf xmalloc} (size\_\-t size)
+\item
+void $\ast$ {\bf xrealloc} (void $\ast$p, size\_\-t size)
+\item
+char $\ast$ \textbf{xstrdup} (const char $\ast$str)\label{mm__util_8c_700bf3013e33311eacdd1f20d13bdc9a}
+
+\item
+void \textbf{xfree} (void $\ast$p)\label{mm__util_8c_91fc771d8aa78ca2ac43244c491da52d}
+
+\item
+char $\ast$ {\bf mm\_\-unquote} (const char $\ast$string)
+\item
+char $\ast$ {\bf mm\_\-uncomment} (const char $\ast$string)
+\item
+char $\ast$ {\bf xstrsep} (char $\ast$$\ast$stringp, const char $\ast$delim)
+\item
+char $\ast$ {\bf mm\_\-stripchars} (char $\ast$input, char $\ast$strip)
+\item
+char $\ast$ {\bf mm\_\-addchars} (char $\ast$input, char $\ast$add, u\_\-int16\_\-t linelength)
+\item
+void \textbf{mm\_\-striptrailing} (char $\ast$$\ast$what, const char $\ast$charset)\label{mm__util_8c_a965d3d1c625253beffd53051b38548e}
+
+\end{CompactItemize}
+
+
+\subsection{Detailed Description}
+This module contains utility functions for the Mini\-MIME library \ No newline at end of file
diff --git a/main/minimime/mm-docs/latex/modules.tex b/main/minimime/mm-docs/latex/modules.tex
new file mode 100644
index 000000000..95e134be3
--- /dev/null
+++ b/main/minimime/mm-docs/latex/modules.tex
@@ -0,0 +1,12 @@
+\section{Mini\-MIME Modules}
+Here is a list of all modules:\begin{CompactList}
+\item \contentsline{section}{Manipulating Mini\-MIME codecs}{\pageref{group__codecs}}{}
+\item \contentsline{section}{Accessing and manipulating Content-Type objects}{\pageref{group__contenttype}}{}
+\item \contentsline{section}{Accessing and manipulating MIME contexts}{\pageref{group__context}}{}
+\item \contentsline{section}{Accessing and manipulating a message's envelope}{\pageref{group__envelope}}{}
+\item \contentsline{section}{Mini\-MIME error functions}{\pageref{group__error}}{}
+\item \contentsline{section}{Accessing and manipulating MIME parts}{\pageref{group__mimepart}}{}
+\item \contentsline{section}{MIME related utility functions}{\pageref{group__mimeutil}}{}
+\item \contentsline{section}{Accessing and manipulating MIME parameters}{\pageref{group__param}}{}
+\item \contentsline{section}{General purpose utility functions}{\pageref{group__util}}{}
+\end{CompactList}
diff --git a/main/minimime/mm-docs/latex/pages.tex b/main/minimime/mm-docs/latex/pages.tex
new file mode 100644
index 000000000..9fdec66bc
--- /dev/null
+++ b/main/minimime/mm-docs/latex/pages.tex
@@ -0,0 +1,5 @@
+\section{Mini\-MIME Related Pages}
+Here is a list of all related documentation pages:\begin{CompactList}
+\item \contentsline{section}{Bug List}{\pageref{bug}}{}
+
+\end{CompactList}
diff --git a/main/minimime/mm-docs/latex/refman.tex b/main/minimime/mm-docs/latex/refman.tex
new file mode 100644
index 000000000..0346dcdc7
--- /dev/null
+++ b/main/minimime/mm-docs/latex/refman.tex
@@ -0,0 +1,62 @@
+\documentclass[a4paper]{book}
+\usepackage{a4wide}
+\usepackage{makeidx}
+\usepackage{fancyhdr}
+\usepackage{graphicx}
+\usepackage{multicol}
+\usepackage{float}
+\usepackage{textcomp}
+\usepackage{alltt}
+\usepackage{doxygen}
+\makeindex
+\setcounter{tocdepth}{1}
+\renewcommand{\footrulewidth}{0.4pt}
+\begin{document}
+\begin{titlepage}
+\vspace*{7cm}
+\begin{center}
+{\Large Mini\-MIME Reference Manual}\\
+\vspace*{1cm}
+{\large Generated by Doxygen 1.5.1}\\
+\vspace*{0.5cm}
+{\small Thu Mar 29 17:59:08 2007}\\
+\end{center}
+\end{titlepage}
+\clearemptydoublepage
+\pagenumbering{roman}
+\tableofcontents
+\clearemptydoublepage
+\pagenumbering{arabic}
+\chapter{Mini\-MIME Module Index}
+\input{modules}
+\chapter{Mini\-MIME File Index}
+\input{files}
+\chapter{Mini\-MIME Page Index}
+\input{pages}
+\chapter{Mini\-MIME Module Documentation}
+\input{group__codecs}
+\include{group__contenttype}
+\include{group__context}
+\include{group__envelope}
+\include{group__error}
+\include{group__mimepart}
+\include{group__mimeutil}
+\include{group__param}
+\include{group__util}
+\chapter{Mini\-MIME File Documentation}
+\input{mm__codecs_8c}
+\include{mm__contenttype_8c}
+\include{mm__context_8c}
+\include{mm__envelope_8c}
+\include{mm__error_8c}
+\include{mm__header_8c}
+\include{mm__internal_8h}
+\include{mm__mimepart_8c}
+\include{mm__mimeutil_8c}
+\include{mm__param_8c}
+\include{mm__parse_8c}
+\include{mm__util_8c}
+\chapter{Mini\-MIME Page Documentation}
+\input{bug}
+\printindex
+\end{document}
diff --git a/main/minimime/mm-docs/refman.pdf b/main/minimime/mm-docs/refman.pdf
new file mode 100644
index 000000000..dc77d05e7
--- /dev/null
+++ b/main/minimime/mm-docs/refman.pdf
Binary files differ
diff --git a/main/minimime/mm.h b/main/minimime/mm.h
new file mode 100644
index 000000000..adaf2db1d
--- /dev/null
+++ b/main/minimime/mm.h
@@ -0,0 +1,368 @@
+/*
+ * $Id$
+ *
+ * MiniMIME - a library for handling MIME messages
+ *
+ * Copyright (C) 2003 Jann Fischer <rezine@mistrust.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _MM_H_INCLUDED
+#define _MM_H_INCLUDED
+
+#include <sys/types.h>
+#include <assert.h>
+#include "mm_queue.h"
+#include "mm_mem.h"
+
+#define MM_MIME_LINELEN 998
+#define MM_BASE64_LINELEN 76
+
+TAILQ_HEAD(mm_mimeheaders, mm_mimeheader);
+TAILQ_HEAD(mm_mimeparts, mm_mimepart);
+TAILQ_HEAD(mm_params, mm_param);
+SLIST_HEAD(mm_codecs, mm_codec);
+SLIST_HEAD(mm_warnings, mm_warning);
+
+/*
+ * Parser modes
+ */
+enum mm_parsemodes
+{
+ /** Parse loosely, accept some MIME quirks */
+ MM_PARSE_LOOSE = 0,
+ /** Parse as strict as possible */
+ MM_PARSE_STRICT
+};
+
+/*
+ * Available parser flags
+ */
+enum mm_parseflags
+{
+ MM_PARSE_NONE = (1L << 0),
+ MM_PARSE_STRIPCOMMENTS = (1L << 1)
+};
+
+/*
+ * Enumeration of MIME encodings
+ */
+enum mm_encoding
+{
+ MM_ENCODING_NONE = 0,
+ MM_ENCODING_BASE64,
+ MM_ENCODING_QUOTEDPRINTABLE,
+ MM_ENCODING_UNKNOWN
+};
+
+/*
+ * Message type
+ */
+enum mm_messagetype
+{
+ /** Flat message */
+ MM_MSGTYPE_FLAT = 0,
+ /** Composite message */
+ MM_MSGTYPE_MULTIPART
+};
+
+/*
+ * Enumeration of error categories
+ */
+enum mm_errors
+{
+ MM_ERROR_NONE = 0,
+ MM_ERROR_UNDEF,
+ MM_ERROR_ERRNO,
+ MM_ERROR_PARSE,
+ MM_ERROR_MIME,
+ MM_ERROR_CODEC,
+ MM_ERROR_PROGRAM
+};
+
+enum mm_warning_ids
+{
+ MM_WARN_NONE = 0,
+ MM_WARN_PARSE,
+ MM_WARN_MIME,
+ MM_WARN_CODEC
+};
+
+enum mm_addressfields {
+ MM_ADDR_TO = 0,
+ MM_ADDR_CC,
+ MM_ADDR_BCC,
+ MM_ADDR_FROM,
+ MM_ADDR_SENDER,
+ MM_ADDR_REPLY_TO
+};
+
+enum mm_flatten_flags {
+ MM_FLATTEN_NONE = 0,
+ MM_FLATTEN_SKIPENVELOPE = (1L << 1),
+ MM_FLATTEN_OPAQUE = (1L << 2),
+ MM_FLATTEN_NOPREAMBLE = (1L << 3)
+};
+
+/*
+ * More information about an error
+ */
+struct mm_error_data
+{
+ int error_id;
+ int error_where;
+ int lineno;
+ char error_msg[128];
+};
+
+extern int mm_errno;
+extern struct mm_error_data mm_error;
+
+enum mm_warning_code
+{
+ MM_WARNING_NONE = 0,
+ MM_WARNING_INVHDR,
+};
+
+/*
+ * A parser warning
+ */
+struct mm_warning
+{
+ enum mm_warning_code warning;
+ u_int32_t lineno;
+ SLIST_ENTRY(mm_warning) next;
+};
+
+/*
+ * Representation of a MiniMIME codec object
+ */
+struct mm_codec
+{
+ enum mm_encoding id;
+ char *encoding;
+
+ char *(*encoder)(char *, u_int32_t);
+ char *(*decoder)(char *);
+
+ SLIST_ENTRY(mm_codec) next;
+};
+
+/*
+ * Representation of a MIME Content-Type parameter
+ */
+struct mm_param
+{
+ char *name;
+ char *value;
+
+ TAILQ_ENTRY(mm_param) next;
+};
+
+/*
+ * Representation of a mail or MIME header field
+ */
+struct mm_mimeheader
+{
+ char *name;
+ char *value;
+
+ struct mm_params params;
+
+ TAILQ_ENTRY(mm_mimeheader) next;
+};
+
+/*
+ * Representation of a MIME Content-Type object
+ */
+struct mm_content
+{
+ char *maintype;
+ char *subtype;
+ char *disposition_type;
+
+ struct mm_params type_params;
+ struct mm_params disposition_params;
+
+ char *encstring;
+ enum mm_encoding encoding;
+};
+
+/*
+ * Representation of a MIME part
+ */
+struct mm_mimepart
+{
+ struct mm_mimeheaders headers;
+
+ size_t opaque_length;
+ char *opaque_body;
+
+ size_t length;
+ char *body;
+
+ struct mm_content *type;
+
+ TAILQ_ENTRY(mm_mimepart) next;
+};
+
+/*
+ * Represantation of a MiniMIME context
+ */
+struct mm_context
+{
+ struct mm_mimeparts parts;
+ enum mm_messagetype messagetype;
+ struct mm_warnings warnings;
+ struct mm_codecs codecs;
+ char *boundary;
+ char *preamble;
+ size_t max_message_size;
+};
+
+typedef struct mm_context MM_CTX;
+typedef struct mm_context mm_ctx_t;
+
+char *mm_unquote(const char *);
+char *mm_uncomment(const char *);
+char *mm_stripchars(char *, char *);
+char *mm_addchars(char *, char *, u_int16_t);
+int mm_gendate(char **);
+void mm_striptrailing(char **, const char *);
+int mm_mimeutil_genboundary(char *, size_t, char **);
+
+int mm_library_init(void);
+int mm_library_isinitialized(void);
+
+int mm_parse_mem(MM_CTX *, const char *, int, int);
+int mm_parse_file(MM_CTX *, const char *, int, int);
+int mm_parse_fileptr(MM_CTX *, FILE *, int, int);
+
+MM_CTX *mm_context_new(void);
+void mm_context_free(MM_CTX *);
+int mm_context_attachpart(MM_CTX *, struct mm_mimepart *);
+int mm_context_deletepart(MM_CTX *, int, int);
+int mm_context_countparts(MM_CTX *);
+struct mm_mimepart *mm_context_getpart(MM_CTX *, int);
+int mm_context_iscomposite(MM_CTX *);
+int mm_context_haswarnings(MM_CTX *);
+int mm_context_flatten(MM_CTX *, char **, size_t *, int);
+
+int mm_envelope_getheaders(MM_CTX *, char **, size_t *);
+int mm_envelope_setheader(MM_CTX *, const char *, const char *, ...);
+
+struct mm_mimeheader *mm_mimeheader_new(void);
+void mm_mimeheader_free(struct mm_mimeheader *);
+struct mm_mimeheader *mm_mimeheader_generate(const char *, const char *);
+int mm_mimeheader_uncomment(struct mm_mimeheader *);
+int mm_mimeheader_uncommentbyname(struct mm_mimepart *, const char *);
+int mm_mimeheader_uncommentall(struct mm_mimepart *);
+int mm_mimeheader_tostring(struct mm_mimeheader *);
+char *mm_mimeheader_getparambyname(struct mm_mimeheader *hdr, const char *name);
+int mm_mimeheader_attachparam(struct mm_mimeheader *hdr, struct mm_param *param);
+
+struct mm_mimepart *mm_mimepart_new(void);
+void mm_mimepart_free(struct mm_mimepart *);
+int mm_mimepart_attachheader(struct mm_mimepart *, struct mm_mimeheader *);
+int mm_mimepart_countheaders(struct mm_mimepart *part);
+int mm_mimepart_countheaderbyname(struct mm_mimepart *, const char *);
+struct mm_mimeheader *mm_mimepart_getheaderbyname(struct mm_mimepart *, const char *, int);
+const char *mm_mimepart_getheadervalue(struct mm_mimepart *, const char *, int);
+int mm_mimepart_headers_start(struct mm_mimepart *, struct mm_mimeheader **);
+struct mm_mimeheader *mm_mimepart_headers_next(struct mm_mimepart *, struct mm_mimeheader **);
+char *mm_mimepart_decode(struct mm_mimepart *);
+struct mm_content *mm_mimepart_getcontent(struct mm_mimepart *);
+size_t mm_mimepart_getlength(struct mm_mimepart *);
+char *mm_mimepart_getbody(struct mm_mimepart *, int);
+void mm_mimepart_attachcontenttype(struct mm_mimepart *, struct mm_content *);
+int mm_mimepart_setdefaultcontenttype(struct mm_mimepart *, int);
+int mm_mimepart_flatten(struct mm_mimepart *, char **, size_t *, int);
+struct mm_mimepart *mm_mimepart_fromfile(const char *);
+
+struct mm_content *mm_content_new(void);
+void mm_content_free(struct mm_content *);
+int mm_content_attachtypeparam(struct mm_content *, struct mm_param *);
+int mm_content_attachdispositionparam(struct mm_content *, struct mm_param *);
+struct mm_content *mm_content_parse(const char *, int);
+char *mm_content_gettypeparambyname(struct mm_content *, const char *);
+char *mm_content_getdispositionparambyname(struct mm_content *, const char *);
+struct mm_param *mm_content_gettypeparamobjbyname(struct mm_content *, const char *);
+struct mm_param *mm_content_getdispositionparamobjbyname(struct mm_content *, const char *);
+int mm_content_setmaintype(struct mm_content *, char *, int);
+int mm_content_setsubtype(struct mm_content *, char *, int);
+int mm_content_settype(struct mm_content *, const char *, ...);
+int mm_content_setdispositiontype(struct mm_content *ct, char *value, int copy);
+char *mm_content_getmaintype(struct mm_content *);
+char *mm_content_getsubtype(struct mm_content *);
+char *mm_content_gettype(struct mm_content *);
+char *mm_content_getdispositiontype(struct mm_content *ct);
+int mm_content_iscomposite(struct mm_content *);
+int mm_content_isvalidencoding(const char *);
+int mm_content_setencoding(struct mm_content *, const char *);
+char *mm_content_typeparamstostring(struct mm_content *);
+char *mm_content_dispositionparamstostring(struct mm_content *);
+char *mm_content_tostring(struct mm_content *);
+
+struct mm_param *mm_param_new(void);
+void mm_param_free(struct mm_param *);
+
+char *mm_flatten_mimepart(struct mm_mimepart *);
+char *mm_flatten_context(MM_CTX *);
+
+int mm_codec_isregistered(const char *);
+int mm_codec_hasdecoder(const char *);
+int mm_codec_hasencoder(const char *);
+int mm_codec_register(const char *, char *(*encoder)(char *, u_int32_t), char *(*decoder)(char *));
+int mm_codec_unregister(const char *);
+int mm_codec_unregisterall(void);
+void mm_codec_registerdefaultcodecs(void);
+
+char *mm_base64_decode(char *);
+char *mm_base64_encode(char *, u_int32_t);
+
+void mm_error_init(void);
+void mm_error_setmsg(const char *, ...);
+void mm_error_setlineno(int lineno);
+char *mm_error_string(void);
+int mm_error_lineno(void);
+
+void mm_warning_add(MM_CTX *, int, const char *, ...);
+struct mm_warning *mm_warning_next(MM_CTX *, struct mm_warning **);
+
+#ifndef HAVE_STRLCPY
+size_t strlcpy(char *, const char *, size_t);
+#endif /* ! HAVE_STRLCPY */
+#ifndef HAVE_STRLCAT
+size_t strlcat(char *, const char *, size_t);
+#endif /* ! HAVE_STRLCAT */
+
+#define MM_ISINIT() do { \
+ assert(mm_library_isinitialized() == 1); \
+} while (0);
+
+#endif /* ! _MM_H_INCLUDED */
diff --git a/main/minimime/mm_base64.c b/main/minimime/mm_base64.c
new file mode 100644
index 000000000..86d7f30c8
--- /dev/null
+++ b/main/minimime/mm_base64.c
@@ -0,0 +1,210 @@
+/*
+ * Copyright (C) 2003 Jann Fischer <jfi@openbsd.de>
+ * All rights reserved.
+ *
+ * XXX: This piece of software is not nearly MIME compatible as it should be.
+ *
+ * This is based on third-party code, see the copyright notice below.
+ *
+ */
+
+/* $Id$ */
+
+/***********************************************************
+ Copyright 1998 by Carnegie Mellon University
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Carnegie Mellon
+University not be used in advertising or publicity pertaining to
+distribution of the software without specific, written prior
+permission.
+
+CARNEGIE MELLON UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO
+THIS SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND
+FITNESS, IN NO EVENT SHALL CARNEGIE MELLON UNIVERSITY BE LIABLE FOR
+ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT
+OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+******************************************************************/
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+
+#include "mm_internal.h"
+
+#define XX 127
+
+static int _mm_base64_decode(char *);
+static char *_mm_base64_encode(char *, u_int32_t);
+
+/*
+ * Tables for encoding/decoding base64
+ */
+static const char basis_64[] =
+ "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+static const char index_64[256] = {
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,62, XX,XX,XX,63,
+ 52,53,54,55, 56,57,58,59, 60,61,XX,XX, XX,XX,XX,XX,
+ XX, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,10, 11,12,13,14,
+ 15,16,17,18, 19,20,21,22, 23,24,25,XX, XX,XX,XX,XX,
+ XX,26,27,28, 29,30,31,32, 33,34,35,36, 37,38,39,40,
+ 41,42,43,44, 45,46,47,48, 49,50,51,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+ XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX, XX,XX,XX,XX,
+};
+#define CHAR64(c) (index_64[(unsigned char)(c)])
+
+/*
+ * mm_base64_decode()
+ *
+ * Decodes the data pointed to by 'data' from the BASE64 encoding to the data
+ * format it was encoded from. Returns a pointer to a string on success or
+ * NULL on error. The string returned needs to be freed by the caller at some
+ * later point.
+ *
+ */
+char *
+mm_base64_decode(char *data)
+{
+ char *buf;
+
+ assert(data != NULL);
+
+ buf = mm_stripchars(data, "\r\n");
+ assert(buf != NULL);
+
+ _mm_base64_decode(buf);
+ assert(buf != NULL);
+ return(buf);
+}
+
+/*
+ * mm_base64_encode()
+ *
+ * Encodes the data pointed to by 'data', which is of the length specified in
+ * 'len' to the BASE64 format. Returns a pointer to a string containing the
+ * BASE64 encoding, whose lines are broken at the MIME recommended linelength
+ * of 76 characters. If an error occured, returns NULL. The string returned
+ * needs to be freed by the caller at some later point.
+ *
+ */
+char *
+mm_base64_encode(char *data, u_int32_t len) {
+ char *buf;
+ char *ret;
+
+ assert(data != NULL);
+
+ buf = _mm_base64_encode(data, len);
+ assert(buf != NULL);
+
+ ret = mm_addchars(buf, "\r\n", MM_BASE64_LINELEN);
+ xfree(buf);
+ assert(ret != NULL);
+ return ret;
+}
+
+/*
+ * Decode in-place the base64 data in 'input'. Returns the length
+ * of the decoded data, or -1 if there was an error.
+ */
+static int
+_mm_base64_decode(char *input)
+{
+ u_int32_t len = 0;
+ unsigned char *output = (unsigned char *)input;
+ int c1, c2, c3, c4;
+
+ while (*input) {
+ c1 = *input++;
+ if (CHAR64(c1) == XX) return -1;
+ c2 = *input++;
+ if (CHAR64(c2) == XX) return -1;
+ c3 = *input++;
+ if (c3 != '=' && CHAR64(c3) == XX) return -1;
+ c4 = *input++;
+ if (c4 != '=' && CHAR64(c4) == XX) return -1;
+ *output++ = (CHAR64(c1) << 2) | (CHAR64(c2) >> 4);
+ ++len;
+ if (c3 == '=') break;
+ *output++ = ((CHAR64(c2) << 4) & 0xf0) | (CHAR64(c3) >> 2);
+ ++len;
+ if (c4 == '=') break;
+ *output++ = ((CHAR64(c3) << 6) & 0xc0) | CHAR64(c4);
+ ++len;
+ }
+ *output = 0;
+
+ return len;
+}
+
+/*
+ * Encode the given binary string of length 'len' and return Base64
+ * in a char buffer. It allocates the space for buffer.
+ * caller must free the space.
+ */
+static char *
+_mm_base64_encode(char *data, u_int32_t len)
+{
+ char *buf;
+ u_int32_t buflen;
+ int c1;
+ int c2;
+ int c3;
+ u_int32_t maxbuf;
+
+ buflen = 0;
+
+#ifdef RUBBISH
+ maxbuf = len*4/3 + 1; /* size after expantion */
+#endif
+ maxbuf = len*2 + 20; /* size after expantion */
+
+ buf = (char *)xmalloc(maxbuf);
+
+ while (len && buflen < (maxbuf - 6)) {
+
+ c1 = (unsigned char)*data++;
+ buf[buflen++] = basis_64[c1>>2];
+
+ if (--len == 0) c2 = 0;
+ else c2 = (unsigned char)*data++;
+ buf[buflen++] = basis_64[((c1 & 0x3)<< 4) | ((c2 & 0xF0) >> 4)];
+
+ if (len == 0) {
+ buf[buflen++] = '=';
+ buf[buflen++] = '=';
+ break;
+ }
+
+ if (--len == 0) c3 = 0;
+ else c3 = (unsigned char)*data++;
+
+ buf[buflen++] = basis_64[((c2 & 0xF) << 2) | ((c3 & 0xC0) >>6)];
+ if (len == 0) {
+ buf[buflen++] = '=';
+
+ break;
+ }
+
+ --len;
+ buf[buflen++] = basis_64[c3 & 0x3F];
+ }
+
+ buf[buflen]=0;
+ return buf;
+}
diff --git a/main/minimime/mm_codecs.c b/main/minimime/mm_codecs.c
new file mode 100644
index 000000000..28603e513
--- /dev/null
+++ b/main/minimime/mm_codecs.c
@@ -0,0 +1,250 @@
+/*
+ * $Id$
+ *
+ * MiniMIME - a library for handling MIME messages
+ *
+ * Copyright (C) 2003 Jann Fischer <rezine@mistrust.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <assert.h>
+
+#include "mm_internal.h"
+#include "mm_util.h"
+
+extern struct mm_codecs codecs;
+
+/** @file mm_codecs.c
+ *
+ * This module contains functions to manipulate MiniMIME codecs
+ *
+ */
+
+/** @defgroup codecs Manipulating MiniMIME codecs */
+
+/** @{
+ * @name Codec manipulation
+ */
+
+/**
+ * Looks up whether a context has an decoder installed for a given encoding
+ *
+ * @param encoding The encoding specifier to look up
+ * @return 1 if a decoder is installed or 0 if not
+ * @ingroup codecs
+ */
+int
+mm_codec_hasdecoder(const char *encoding)
+{
+ struct mm_codec *codec;
+
+ assert(encoding != NULL);
+
+ SLIST_FOREACH(codec, &codecs, next) {
+ assert(codec->encoding != NULL);
+ if (!strcasecmp(codec->encoding, encoding)) {
+ if (codec->decoder != NULL)
+ return 1;
+ else
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Looks up whether a context has an encoder installed for a given encoding
+ *
+ * @param ctx A valid MIME context
+ * @param encoding The encoding specifier to look up
+ * @return 1 if an encoder is installed or 0 if not
+ * @ingroup codecs
+ */
+int
+mm_codec_hasencoder(const char *encoding)
+{
+ struct mm_codec *codec;
+
+ assert(encoding != NULL);
+
+ SLIST_FOREACH(codec, &codecs, next) {
+ assert(codec->encoding != NULL);
+ if (!strcasecmp(codec->encoding, encoding)) {
+ if (codec->encoder != NULL)
+ return 1;
+ else
+ return 0;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Looks up whether a codec for a given encoding is installed to a context
+ *
+ * @param encoding The encoding specifier to look up
+ * @return 1 if a codec was found or 0 if not
+ * @ingroup codecs
+ */
+int
+mm_codec_isregistered(const char *encoding)
+{
+ struct mm_codec *codec;
+
+ assert(encoding != NULL);
+
+ SLIST_FOREACH(codec, &codecs, next) {
+ if (!strcasecmp(codec->encoding, encoding)) {
+ return 1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Registers a codec with the MiniMIME library
+ *
+ * @param encoding The encoding specifier for which to register the codec
+ * @param encoder The encoder function for this encoding
+ * @param decoder The decoder function for this encoding
+ * @return 1 if successfull or 0 if not
+ * @ingroup codecs
+ *
+ * This function registers a codec for a given MiniMIME context. The codec
+ * may provide an decoder, an encoder or both (but not none). If there is
+ * a codec already installed for this encoding, the function will puke.
+ */
+int
+mm_codec_register(const char *encoding,
+ char *(*encoder)(char *data, u_int32_t i),
+ char *(*decoder)(char *data))
+{
+ struct mm_codec *codec;
+
+ assert(encoding != NULL);
+
+ assert(mm_codec_isregistered(encoding) != 1);
+
+ codec = (struct mm_codec *)xmalloc(sizeof(struct mm_codec));
+
+ codec->encoding = xstrdup(encoding);
+ codec->encoder = encoder;
+ codec->decoder = decoder;
+
+ if (SLIST_EMPTY(&codecs)) {
+ SLIST_INSERT_HEAD(&codecs, codec, next);
+ return 1;
+ } else {
+ struct mm_codec *lcodec, *tcodec;
+ tcodec = NULL;
+ SLIST_FOREACH(lcodec, &codecs, next) {
+ if (lcodec != NULL)
+ tcodec = lcodec;
+ }
+ assert(tcodec != NULL);
+ SLIST_INSERT_AFTER(tcodec, codec, next);
+ return 1;
+ }
+
+ return 0;
+}
+
+/**
+ * Unregisters a MiniMIME codec
+ *
+ * @param encoding The encoding specifier which to unregister
+ * @return 0 if unregistered successfully, or -1 if there was no such codec
+ * @ingroup codecs
+ */
+int
+mm_codec_unregister(const char *encoding)
+{
+ struct mm_codec *codec;
+
+ assert(encoding != NULL);
+
+ SLIST_FOREACH(codec, &codecs, next) {
+ if (!strcasecmp(codec->encoding, encoding)) {
+ xfree(codec->encoding);
+ xfree(codec);
+ codec = NULL;
+ return 0;
+ }
+ }
+
+ return -1;
+}
+
+/**
+ * Unregisters all codecs within a context
+ *
+ * @param ctx A valid MiniMIME context
+ * @return 0 if all codecs were unregistered successfully or -1 if an error
+ * occured.
+ * @note Foobar
+ */
+int
+mm_codec_unregisterall(void)
+{
+ struct mm_codec *codec;
+
+ SLIST_FOREACH(codec, &codecs, next) {
+ if (mm_codec_unregister(codec->encoding) == -1) {
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * Registers the default codecs to a MiniMIME context
+ *
+ * This functions registers the codecs for the following encodings to a
+ * MiniMIME context:
+ *
+ * - Base64
+ * - (TODO:) Quoted-Printable
+ */
+void
+mm_codec_registerdefaultcodecs(void)
+{
+ mm_codec_register("base64", mm_base64_encode, mm_base64_decode);
+}
+
+
+/** @} */
diff --git a/main/minimime/mm_contenttype.c b/main/minimime/mm_contenttype.c
new file mode 100644
index 000000000..ff978df85
--- /dev/null
+++ b/main/minimime/mm_contenttype.c
@@ -0,0 +1,757 @@
+/*
+ * $Id$
+ *
+ * MiniMIME - a library for handling MIME messages
+ *
+ * Copyright (C) 2003 Jann Fischer <rezine@mistrust.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "mm_internal.h"
+#include "mm_util.h"
+
+/* This file is documented using Doxygen */
+
+/**
+ * @file mm_contenttype.c
+ *
+ * This module contains functions for manipulating Content-Type objects.
+ */
+
+/** @defgroup contenttype Accessing and manipulating Content-Type objects */
+
+struct mm_encoding_mappings {
+ const char *idstring;
+ int type;
+};
+
+static struct mm_encoding_mappings mm_content_enctypes[] = {
+ { "Base64", MM_ENCODING_BASE64 },
+ { "Quoted-Printable", MM_ENCODING_QUOTEDPRINTABLE },
+ { NULL, - 1},
+};
+
+static const char *mm_composite_maintypes[] = {
+ "multipart",
+ "message",
+ NULL,
+};
+
+static const char *mm_composite_encodings[] = {
+ "7bit",
+ "8bit",
+ "binary",
+ NULL,
+};
+
+/** @{
+ * @name Functions for manipulating Content objects
+ */
+
+/**
+ * Creates a new object to hold a Content representation.
+ * The allocated memory must later be freed using mm_content_free()
+ *
+ * @return An object representing a MIME Content-Type
+ * @see mm_content_free
+ * @ingroup contenttype
+ */
+struct mm_content *
+mm_content_new(void)
+{
+ struct mm_content *ct;
+
+ ct = (struct mm_content *)xmalloc(sizeof(struct mm_content));
+
+ ct->maintype = NULL;
+ ct->subtype = NULL;
+
+ TAILQ_INIT(&ct->type_params);
+ TAILQ_INIT(&ct->disposition_params);
+
+ ct->encoding = MM_ENCODING_NONE;
+ ct->encstring = NULL;
+
+ return ct;
+}
+
+/**
+ * Releases all memory associated with an Content object
+ *
+ * @param ct A Content-Type object
+ * @return Nothing
+ * @ingroup contenttype
+ */
+void
+mm_content_free(struct mm_content *ct)
+{
+ struct mm_param *param;
+
+ assert(ct != NULL);
+
+ if (ct->maintype != NULL) {
+ xfree(ct->maintype);
+ ct->maintype = NULL;
+ }
+ if (ct->subtype != NULL) {
+ xfree(ct->subtype);
+ ct->subtype = NULL;
+ }
+ if (ct->encstring != NULL) {
+ xfree(ct->encstring);
+ ct->encstring = NULL;
+ }
+
+ TAILQ_FOREACH(param, &ct->type_params, next) {
+ TAILQ_REMOVE(&ct->type_params, param, next);
+ mm_param_free(param);
+ }
+ TAILQ_FOREACH(param, &ct->disposition_params, next) {
+ TAILQ_REMOVE(&ct->disposition_params, param, next);
+ mm_param_free(param);
+ }
+
+ xfree(ct);
+}
+
+/**
+ * Attaches a content-type parameter to a Content object
+ *
+ * @param ct The target Content object
+ * @param param The Content-Type parameter which to attach
+ * @return 0 on success and -1 on failure
+ * @ingroup contenttype
+ */
+int
+mm_content_attachtypeparam(struct mm_content *ct, struct mm_param *param)
+{
+ assert(ct != NULL);
+ assert(param != NULL);
+
+ if (TAILQ_EMPTY(&ct->type_params)) {
+ TAILQ_INSERT_HEAD(&ct->type_params, param, next);
+ } else {
+ TAILQ_INSERT_TAIL(&ct->type_params, param, next);
+ }
+
+ return 0;
+}
+
+
+/**
+ * Attaches a content-disposition parameter to a Content-Disposition object
+ *
+ * @param ct The target Content object
+ * @param param The Content-Type parameter which to attach
+ * @return 0 on success and -1 on failure
+ * @ingroup contenttype
+ */
+int
+mm_content_attachdispositionparam(struct mm_content *ct, struct mm_param *param)
+{
+ assert(ct != NULL);
+ assert(param != NULL);
+
+ if (TAILQ_EMPTY(&ct->disposition_params)) {
+ TAILQ_INSERT_HEAD(&ct->disposition_params, param, next);
+ } else {
+ TAILQ_INSERT_TAIL(&ct->disposition_params, param, next);
+ }
+
+ return 0;
+}
+
+
+/**
+ * Gets a Content-Type parameter value from a Content object.
+ *
+ * @param ct the Content object
+ * @param name the name of the parameter to retrieve
+ * @return The value of the parameter on success or a NULL pointer on failure
+ * @ingroup contenttype
+ */
+char *
+mm_content_gettypeparambyname(struct mm_content *ct, const char *name)
+{
+ struct mm_param *param;
+
+ assert(ct != NULL);
+
+ TAILQ_FOREACH(param, &ct->type_params, next) {
+ if (!strcasecmp(param->name, name)) {
+ return param->value;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Gets a Content-Disposition parameter value from a Content object.
+ *
+ * @param ct the Content object
+ * @param name the name of the parameter to retrieve
+ * @return The value of the parameter on success or a NULL pointer on failure
+ * @ingroup contenttype
+ */
+char *
+mm_content_getdispositionparambyname(struct mm_content *ct, const char *name)
+{
+ struct mm_param *param;
+
+ assert(ct != NULL);
+
+ TAILQ_FOREACH(param, &ct->disposition_params, next) {
+ if (!strcasecmp(param->name, name)) {
+ return param->value;
+ }
+ }
+
+ return NULL;
+}
+
+struct mm_param *
+mm_content_gettypeparamobjbyname(struct mm_content *ct, const char *name)
+{
+ struct mm_param *param;
+
+ assert(ct != NULL);
+
+ TAILQ_FOREACH(param, &ct->type_params, next) {
+ if (!strcasecmp(param->name, name)) {
+ return param;
+ }
+ }
+
+ return NULL;
+}
+
+struct mm_param *
+mm_content_getdispositionparamobjbyname(struct mm_content *ct, const char *name)
+{
+ struct mm_param *param;
+
+ assert(ct != NULL);
+
+ TAILQ_FOREACH(param, &ct->disposition_params, next) {
+ if (!strcasecmp(param->name, name)) {
+ return param;
+ }
+ }
+
+ return NULL;
+}
+
+/**
+ * Sets the MIME main Content-Type for a MIME Content object
+ *
+ * @param ct The MIME Content object
+ * @param value The value which to set the main type to
+ * @param copy Whether to make a copy of the value (original value must be
+ * freed afterwards to prevent memory leaks).
+ */
+int
+mm_content_setmaintype(struct mm_content *ct, char *value, int copy)
+{
+ assert(ct != NULL);
+ assert(value != NULL);
+
+ if (copy) {
+ /**
+ * @bug The xfree() call could lead to undesirable results.
+ * Do we really need it?
+ */
+ if (ct->maintype != NULL) {
+ xfree(ct->maintype);
+ }
+ ct->maintype = xstrdup(value);
+ } else {
+ ct->maintype = value;
+ }
+
+ return 0;
+}
+
+/**
+ * Retrieves the main MIME Content-Type stored in a Content object
+ *
+ * @param ct A valid Content object
+ * @returns A pointer to the string representing the main type
+ * @ingroup contenttype
+ */
+char *
+mm_content_getmaintype(struct mm_content *ct)
+{
+ assert(ct != NULL);
+ assert(ct->maintype != NULL);
+
+ return ct->maintype;
+}
+
+/**
+ * Sets the MIME Content-Disposition type for a MIME Content object
+ *
+ * @param ct The MIME Content object
+ * @param value The value which to set the main type to
+ * @param copy Whether to make a copy of the value (original value must be
+ * freed afterwards to prevent memory leaks).
+ */
+int
+mm_content_setdispositiontype(struct mm_content *ct, char *value, int copy)
+{
+ assert(ct != NULL);
+ assert(value != NULL);
+
+ if (copy) {
+ /**
+ * @bug The xfree() call could lead to undesirable results.
+ * Do we really need it?
+ */
+ if (ct->disposition_type != NULL) {
+ xfree(ct->disposition_type);
+ }
+ ct->disposition_type = xstrdup(value);
+ } else {
+ ct->disposition_type = value;
+ }
+
+ return 0;
+}
+
+/**
+ * Retrieves the Content-Disposition MIME type stored in a Content object
+ *
+ * @param ct A valid Content-Type object
+ * @returns A pointer to the string representing the main type
+ * @ingroup contenttype
+ */
+char *
+mm_content_getdispositiontype(struct mm_content *ct)
+{
+ assert(ct != NULL);
+ assert(ct->disposition_type != NULL);
+
+ return ct->disposition_type;
+}
+
+/**
+ * Retrieves the sub MIME Content-Type stored in a Content object
+ *
+ * @param ct A valid Content-Type object
+ * @return A pointer to the string holding the current sub MIME type
+ * @ingroup contenttype
+ */
+char *
+mm_content_getsubtype(struct mm_content *ct)
+{
+ assert(ct != NULL);
+ assert(ct->subtype != NULL);
+
+ return ct->subtype;
+}
+
+/**
+ * Sets the MIME sub Content-Type for a MIME Content object
+ *
+ * @param ct The MIME Content-Type object
+ * @param value The value which to set the sub type to
+ * @param copy Whether to make a copy of the value (original value must be
+ * freed afterwards to prevent memory leaks).
+ */
+int
+mm_content_setsubtype(struct mm_content *ct, char *value, int copy)
+{
+ assert(ct != NULL);
+ assert(value != NULL);
+
+ if (copy) {
+ /**
+ * @bug The xfree() call could lead to undesirable results.
+ * Do we really need it?
+ */
+ if (ct->subtype != NULL) {
+ xfree(ct->subtype);
+ }
+ ct->subtype = xstrdup(value);
+ } else {
+ ct->subtype = value;
+ }
+
+ return 0;
+}
+
+int
+mm_content_settype(struct mm_content *ct, const char *fmt, ...)
+{
+ char *maint, *subt;
+ char buf[512], *parse;
+ va_list ap;
+
+ mm_errno = MM_ERROR_NONE;
+
+ va_start(ap, fmt);
+ /* Make sure no truncation occurs */
+ if (vsnprintf(buf, sizeof buf, fmt, ap) > sizeof buf) {
+ mm_errno = MM_ERROR_ERRNO;
+ mm_error_setmsg("Input string too long");
+ return -1;
+ }
+ va_end(ap);
+
+ parse = buf;
+ maint = strsep(&parse, "/");
+ if (maint == NULL) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("Invalid type specifier: %s", buf);
+ return -1;
+ }
+ ct->maintype = xstrdup(maint);
+
+ subt = strsep(&parse, "");
+ if (subt == NULL) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("Invalid type specifier: %s", buf);
+ return -1;
+ }
+ ct->subtype = xstrdup(subt);
+
+ return 0;
+}
+
+/**
+ * Checks whether the Content-Type represents a composite message or not
+ *
+ * @param ct A valid Content-Type object
+ * @returns 1 if the Content-Type object represents a composite message or
+ * 0 if not.
+ */
+int
+mm_content_iscomposite(struct mm_content *ct)
+{
+ int i;
+
+ for (i = 0; mm_composite_maintypes[i] != NULL; i++) {
+ if (!strcasecmp(ct->maintype, mm_composite_maintypes[i])) {
+ return 1;
+ }
+ }
+
+ /* Not found */
+ return 0;
+}
+
+/**
+ * Verifies whether a string represents a valid encoding or not.
+ *
+ * @param encoding The string to verify
+ * @return 1 if the encoding string is valid or 0 if not
+ *
+ */
+int
+mm_content_isvalidencoding(const char *encoding)
+{
+ int i;
+
+ for (i = 0; mm_composite_encodings[i] != NULL; i++) {
+ if (!strcasecmp(encoding, mm_composite_encodings[i])) {
+ return 1;
+ }
+ }
+
+ /* Not found */
+ return 0;
+}
+
+/**
+ * Set the encoding of a MIME entitity according to a mapping table
+ *
+ * @param ct A valid content type object
+ * @param encoding A string representing the content encoding
+ * @return 0 if successfull or -1 if not (i.e. unknown content encoding)
+ */
+int
+mm_content_setencoding(struct mm_content *ct, const char *encoding)
+{
+ int i;
+
+ assert(ct != NULL);
+ assert(encoding != NULL);
+
+ for (i = 0; mm_content_enctypes[i].idstring != NULL; i++) {
+ if (!strcasecmp(mm_content_enctypes[i].idstring, encoding)) {
+ ct->encoding = mm_content_enctypes[i].type;
+ ct->encstring = xstrdup(encoding);
+ return 0;
+ }
+ }
+
+ /* If we didn't find a mapping, set the encoding to unknown */
+ ct->encoding = MM_ENCODING_UNKNOWN;
+ ct->encstring = NULL;
+ return 1;
+}
+
+/**
+ * Gets the numerical ID of a content encoding identifier
+ *
+ * @param ct A valid Content Type object
+ * @param encoding A string representing the content encoding identifier
+ * @return The numerical ID of the content encoding
+ */
+int
+mm_content_getencoding(struct mm_content *ct, const char *encoding)
+{
+ int i;
+
+ assert(ct != NULL);
+
+ for (i = 0; mm_content_enctypes[i].idstring != NULL; i++) {
+ if (!strcasecmp(mm_content_enctypes[i].idstring, encoding)) {
+ return mm_content_enctypes[i].type;
+ }
+ }
+
+ /* Not found */
+ return MM_ENCODING_UNKNOWN;
+}
+
+/**
+ * Constructs a MIME conform string of Content-Type parameters.
+ *
+ * @param ct A valid Content Type object
+ * @return A pointer to a string representing the Content-Type parameters
+ * in MIME terminology, or NULL if either the Content-Type object
+ * is invalid, has no parameters or no memory could be allocated.
+ *
+ * This function constructs a MIME conform string including all the parameters
+ * associated with the given Content-Type object. It should NOT be used if
+ * you need an opaque copy of the current MIME part (e.g. for PGP purposes).
+ */
+char *
+mm_content_typeparamstostring(struct mm_content *ct)
+{
+ size_t size, new_size;
+ struct mm_param *param;
+ char *param_string, *cur_param;
+ char *buf;
+
+ size = 1;
+ param_string = NULL;
+ cur_param = NULL;
+
+ param_string = (char *) xmalloc(size);
+ *param_string = '\0';
+
+ /* Concatenate all Content-Type parameters attached to the current
+ * Content-Type object to a single string.
+ */
+ TAILQ_FOREACH(param, &ct->type_params, next) {
+ if (asprintf(&cur_param, "; %s=\"%s\"", param->name,
+ param->value) == -1) {
+ goto cleanup;
+ }
+
+ new_size = size + strlen(cur_param) + 1;
+
+ if (new_size < 0 || new_size > 1000) {
+ size = 0;
+ goto cleanup;
+ }
+
+ buf = (char *) xrealloc(param_string, new_size);
+ if (buf == NULL) {
+ size = 0;
+ goto cleanup;
+ }
+
+ param_string = buf;
+ size = new_size;
+ strlcat(param_string, cur_param, size);
+
+ xfree(cur_param);
+ cur_param = NULL;
+ }
+
+ return param_string;
+
+cleanup:
+ if (param_string != NULL) {
+ xfree(param_string);
+ param_string = NULL;
+ }
+ if (cur_param != NULL) {
+ xfree(cur_param);
+ cur_param = NULL;
+ }
+ return NULL;
+}
+
+/**
+ * Constructs a MIME conformant string of Content-Disposition parameters.
+ *
+ * @param ct A valid Content object
+ * @return A pointer to a string representing the Content-Disposition parameters
+ * in MIME terminology, or NULL if either the Content object
+ * is invalid, has no Disposition parameters or no memory could be allocated.
+ *
+ * This function constructs a MIME conforming string including all the parameters
+ * associated with the given Content-Disposition object. It should NOT be used if
+ * you need an opaque copy of the current MIME part (e.g. for PGP purposes).
+ */
+char *
+mm_content_dispositionparamstostring(struct mm_content *ct)
+{
+ size_t size, new_size;
+ struct mm_param *param;
+ char *param_string, *cur_param;
+ char *buf;
+
+ size = 1;
+ param_string = NULL;
+ cur_param = NULL;
+
+ param_string = (char *) xmalloc(size);
+ *param_string = '\0';
+
+ /* Concatenate all Content-Disposition parameters attached to the current
+ * Content object to a single string.
+ */
+ TAILQ_FOREACH(param, &ct->disposition_params, next) {
+ if (asprintf(&cur_param, "; %s=\"%s\"", param->name,
+ param->value) == -1) {
+ goto cleanup;
+ }
+
+ new_size = size + strlen(cur_param) + 1;
+
+ if (new_size < 0 || new_size > 1000) {
+ size = 0;
+ goto cleanup;
+ }
+
+ buf = (char *) xrealloc(param_string, new_size);
+ if (buf == NULL) {
+ size = 0;
+ goto cleanup;
+ }
+
+ param_string = buf;
+ size = new_size;
+ strlcat(param_string, cur_param, size);
+
+ xfree(cur_param);
+ cur_param = NULL;
+ }
+
+ return param_string;
+
+cleanup:
+ if (param_string != NULL) {
+ xfree(param_string);
+ param_string = NULL;
+ }
+ if (cur_param != NULL) {
+ xfree(cur_param);
+ cur_param = NULL;
+ }
+ return NULL;
+}
+
+/**
+ * Creates a Content-Type header according to the object given
+ *
+ * @param ct A valid Content-Type object
+ *
+ */
+char *
+mm_content_tostring(struct mm_content *ct)
+{
+ char *paramstring;
+ char *buf;
+ char *headerstring;
+ size_t size;
+
+ paramstring = NULL;
+ headerstring = NULL;
+ buf = NULL;
+
+ if (ct == NULL) {
+ return NULL;
+ }
+ if (ct->maintype == NULL || ct->subtype == NULL) {
+ return NULL;
+ }
+
+ size = strlen(ct->maintype) + strlen(ct->subtype) + 2;
+ headerstring = (char *)xmalloc(size);
+ snprintf(headerstring, size, "%s/%s", ct->maintype, ct->subtype);
+
+ paramstring = mm_content_typeparamstostring(ct);
+ if (paramstring == NULL) {
+ goto cleanup;
+ }
+
+ size += strlen(paramstring) + strlen("Content-Type: ") + 1;
+ buf = (char *)malloc(size);
+ if (buf == NULL) {
+ goto cleanup;
+ }
+
+ snprintf(buf, size, "Content-Type: %s%s", headerstring, paramstring);
+
+ xfree(headerstring);
+ xfree(paramstring);
+
+ headerstring = NULL;
+ paramstring = NULL;
+
+ return buf;
+
+cleanup:
+ if (paramstring != NULL) {
+ xfree(paramstring);
+ paramstring = NULL;
+ }
+ if (headerstring != NULL) {
+ xfree(headerstring);
+ headerstring = NULL;
+ }
+ if (buf != NULL) {
+ xfree(buf);
+ buf = NULL;
+ }
+ return NULL;
+}
+
+/** @} */
diff --git a/main/minimime/mm_context.c b/main/minimime/mm_context.c
new file mode 100644
index 000000000..e655b925a
--- /dev/null
+++ b/main/minimime/mm_context.c
@@ -0,0 +1,604 @@
+/*
+ * $Id$
+ *
+ * MiniMIME - a library for handling MIME messages
+ *
+ * Copyright (C) 2003 Jann Fischer <rezine@mistrust.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <assert.h>
+
+#include "mm_internal.h"
+
+/** @file mm_context.c
+ *
+ * Modules for manipulating MiniMIME contexts
+ */
+
+/** @defgroup context Accessing and manipulating MIME contexts
+ *
+ * Each message in MiniMIME is represented by a so called ``context''. A
+ * context holds all necessary information given about a MIME message, such
+ * as the envelope, all MIME parts etc.
+ */
+
+/** @{
+ * @name Manipulating MiniMIME contexts
+ */
+
+/**
+ * Creates a new MiniMIME context object.
+ *
+ * @return a new MiniMIME context object
+ * @see mm_context_free
+ *
+ * This function creates a new MiniMIME context, which will hold a message.
+ * The memory needed is allocated dynamically and should later be free'd
+ * using mm_context_free().
+ *
+ * Before a context can be created, the MiniMIME library needs to be
+ * initialized properly using mm_library_init().
+ *
+ */
+MM_CTX *
+mm_context_new(void)
+{
+ MM_CTX *ctx;
+
+ MM_ISINIT();
+
+ ctx = (MM_CTX *)xmalloc(sizeof(MM_CTX));
+ ctx->messagetype = MM_MSGTYPE_FLAT; /* This is the default */
+ ctx->boundary = NULL;
+ ctx->preamble = xstrdup("This is a message in MIME format, generated "
+ "by MiniMIME 0.1");
+
+ TAILQ_INIT(&ctx->parts);
+ SLIST_INIT(&ctx->warnings);
+
+ return ctx;
+}
+
+/**
+ * Releases a MiniMIME context object
+ *
+ * @param ctx A valid MiniMIME context
+ * @see mm_context_new
+ *
+ * This function releases all memory associated with MiniMIME context object
+ * that was created using mm_context_new(). It will also release all memory
+ * used for the MIME parts attached, and their specific properties (such as
+ * Content-Type information, headers, and the body data).
+ */
+void
+mm_context_free(MM_CTX *ctx)
+{
+ struct mm_mimepart *part;
+ struct mm_warning *warning, *nxt;
+
+ assert(ctx != NULL);
+
+ TAILQ_FOREACH(part, &ctx->parts, next) {
+ TAILQ_REMOVE(&ctx->parts, part, next);
+ mm_mimepart_free(part);
+ }
+
+ if (ctx->boundary != NULL) {
+ xfree(ctx->boundary);
+ ctx->boundary = NULL;
+ }
+
+ if (ctx->preamble != NULL) {
+ xfree(ctx->preamble);
+ ctx->preamble = NULL;
+ }
+
+ for (warning = SLIST_FIRST(&ctx->warnings);
+ warning != SLIST_END(&ctx->warnings);
+ warning = nxt) {
+ nxt = SLIST_NEXT(warning, next);
+ SLIST_REMOVE(&ctx->warnings, warning, mm_warning, next);
+ xfree(warning);
+ warning = NULL;
+ }
+
+ xfree(ctx);
+ ctx = NULL;
+}
+
+/**
+ * Attaches a MIME part object to a MiniMIME context.
+ *
+ * @param ctx the MiniMIME context
+ * @param part the MIME part object to attach
+ * @return 0 on success or -1 on failure. Sets mm_errno on failure.
+ *
+ * This function attaches a MIME part to a context, appending it to the end
+ * of the message.
+ *
+ * The MIME part should be initialized before attaching it using
+ * mm_mimepart_new().
+ */
+int
+mm_context_attachpart(MM_CTX *ctx, struct mm_mimepart *part)
+{
+ assert(ctx != NULL);
+ assert(part != NULL);
+
+ if (TAILQ_EMPTY(&ctx->parts)) {
+ TAILQ_INSERT_HEAD(&ctx->parts, part, next);
+ } else {
+ TAILQ_INSERT_TAIL(&ctx->parts, part, next);
+ }
+
+ return 0;
+}
+
+/**
+ * Attaches a MIME part object to a MiniMIME context at a given position
+ *
+ * @param ctx A valid MiniMIME context
+ * @param part The MIME part object to attach
+ * @param pos After which part to attach the object
+ * @return 0 on success or -1 if the given position is invalid
+ * @see mm_context_attachpart
+ *
+ * This function attaches a MIME part object after a given position in the
+ * specified context. If the position is invalid (out of range), the part
+ * will not get attached to the message and the function returns -1. If
+ * the index was in range, the MIME part will get attached after the MIME
+ * part at the given position, moving any possible following MIME parts one
+ * down the hierarchy.
+ */
+int
+mm_context_attachpart_after(MM_CTX *ctx, struct mm_mimepart *part, int pos)
+{
+ struct mm_mimepart *p;
+ int where;
+
+ where = 0;
+ p = NULL;
+
+ TAILQ_FOREACH(part, &ctx->parts, next) {
+ if (where == pos) {
+ p = part;
+ }
+ }
+
+ if (p == NULL) {
+ return(-1);
+ }
+
+ TAILQ_INSERT_AFTER(&ctx->parts, p, part, next);
+
+ return(0);
+}
+
+/**
+ * Deletes a MIME part object from a MiniMIME context
+ *
+ * @param ctx A valid MiniMIME context object
+ * @param which The number of the MIME part object to delete
+ * @param freemem Whether to free the memory associated with the MIME part
+ * object
+ * @return 0 on success or -1 on failure. Sets mm_errno on failure.
+ *
+ * This function deletes a MIME part from a given context. The MIME part to
+ * delete is specified as numerical index by the parameter ``which''. If the
+ * parameter ``freemem'' is set to anything greater than 0, the memory that
+ * is associated will be free'd by using mm_mimepart_free(), otherwise the
+ * memory is left untouched (if you still have a pointer to the MIME part
+ * around).
+ */
+int
+mm_context_deletepart(MM_CTX *ctx, int which, int freemem)
+{
+ struct mm_mimepart *part;
+ int cur;
+
+ assert(ctx != NULL);
+ assert(which >= 0);
+
+ cur = 0;
+
+ TAILQ_FOREACH(part, &ctx->parts, next) {
+ if (cur == which) {
+ TAILQ_REMOVE(&ctx->parts, part, next);
+ if (freemem)
+ mm_mimepart_free(part);
+ return 0;
+ }
+ cur++;
+ }
+
+ return -1;
+}
+
+/**
+ * Counts the number of attached MIME part objects in a given MiniMIME context
+ *
+ * @param ctx The MiniMIME context
+ * @returns The number of attached MIME part objects
+ */
+int
+mm_context_countparts(MM_CTX *ctx)
+{
+ int count;
+ struct mm_mimepart *part;
+
+ assert(ctx != NULL);
+
+ count = 0;
+
+ if (TAILQ_EMPTY(&ctx->parts)) {
+ return 0;
+ } else {
+ TAILQ_FOREACH(part, &ctx->parts, next) {
+ count++;
+ }
+ }
+
+ assert(count > -1);
+
+ return count;
+}
+
+/**
+ * Gets a specified MIME part object from a MimeMIME context
+ *
+ * @param ctx The MiniMIME context
+ * @param which The number of the MIME part object to retrieve
+ * @returns The requested MIME part object on success or a NULL pointer if
+ * there is no such part.
+ */
+struct mm_mimepart *
+mm_context_getpart(MM_CTX *ctx, int which)
+{
+ struct mm_mimepart *part;
+ int cur;
+
+ assert(ctx != NULL);
+
+ cur = 0;
+
+ TAILQ_FOREACH(part, &ctx->parts, next) {
+ if (cur == which) {
+ return part;
+ }
+ cur++;
+ }
+
+ return NULL;
+}
+
+/**
+ * Checks whether a given context represents a composite (multipart) message
+ *
+ * @param ctx A valid MiniMIME context object
+ * @return 1 if the context is a composite message or 0 if it's flat
+ *
+ */
+int
+mm_context_iscomposite(MM_CTX *ctx)
+{
+ if (ctx->messagetype == MM_MSGTYPE_MULTIPART) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+/**
+ * Checks whether there are any warnings associated with a given context
+ *
+ * @param ctx A valid MiniMIME context
+ * @return 1 if there are warnings associated with the context, otherwise 0
+ */
+int
+mm_context_haswarnings(MM_CTX *ctx)
+{
+ if (SLIST_EMPTY(&ctx->warnings)) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+/**
+ * Generates a generic boundary string for a given context
+ *
+ * @param ctx A valid MiniMIME context
+ * @return 0 on success or -1 on failure
+ *
+ * This function generates a default boundary string for the given context.
+ * If there is already a boundary for the context, the memory will be free()'d.
+ */
+int
+mm_context_generateboundary(MM_CTX *ctx)
+{
+ char *boundary;
+ struct mm_mimepart *part;
+ struct mm_param *param;
+
+ if (mm_mimeutil_genboundary("++MiniMIME++", 20, &boundary) == -1) {
+ return(-1);
+ }
+
+ if (ctx->boundary != NULL) {
+ xfree(ctx->boundary);
+ ctx->boundary = NULL;
+ }
+
+ /* If we already have an envelope, make sure that we also justify the
+ * "boundary" parameter of the envelope.
+ */
+ part = mm_context_getpart(ctx, 0);
+ if (part == NULL) {
+ return(0);
+ }
+ if (part->type != NULL) {
+ param = mm_content_gettypeparamobjbyname(part->type, "boundary");
+ if (param == NULL) {
+ param = mm_param_new();
+ param->name = xstrdup("boundary");
+ param->value = xstrdup(boundary);
+ mm_content_attachtypeparam(part->type, param);
+ } else {
+ if (param->value != NULL) {
+ xfree(param->value);
+ param->value = NULL;
+ }
+ param->value = xstrdup(boundary);
+ }
+ }
+
+ ctx->boundary = boundary;
+ return(0);
+}
+
+/**
+ * Sets a preamble for the given MiniMIME context
+ *
+ * @param ctx A valid MiniMIME context
+ * @param preamble The preamble to set
+ * @return 0 on success or -1 on failure
+ *
+ * This function sets the MIME preamble (the text between the end of envelope
+ * headers and the beginning of the first MIME part) for a given context
+ * object. If preamble is a NULL-pointer then the preamble will be deleted,
+ * and the currently associated memory will be free automagically.
+ */
+int
+mm_context_setpreamble(MM_CTX *ctx, char *preamble)
+{
+ if (ctx == NULL)
+ return(-1);
+
+ if (preamble == NULL) {
+ if (ctx->preamble != NULL) {
+ xfree(ctx->preamble);
+ }
+ ctx->preamble = NULL;
+ } else {
+ ctx->preamble = xstrdup(preamble);
+ }
+ return(0);
+}
+
+char *
+mm_context_getpreamble(MM_CTX *ctx)
+{
+ if (ctx == NULL)
+ return(NULL);
+
+ return(ctx->preamble);
+}
+
+/**
+ * Creates an ASCII message of the specified context
+ *
+ * @param ctx A valid MiniMIME context object
+ * @param flat Where to store the message
+ * @param flags Flags that affect the flattening process
+ *
+ * This function ``flattens'' a MiniMIME context, that is, it creates an ASCII
+ * represantation of the message the context contains. The flags can be a
+ * bitwise combination of the following constants:
+ *
+ * - MM_FLATTEN_OPAQUE : use opaque MIME parts when flattening
+ * - MM_FLATTEN_SKIPENVELOPE : do not flatten the envelope part
+ *
+ * Great care is taken to not produce invalid MIME output.
+ */
+int
+mm_context_flatten(MM_CTX *ctx, char **flat, size_t *length, int flags)
+{
+ struct mm_mimepart *part;
+ char *message;
+ char *flatpart;
+ char *buf;
+ char *envelope_headers;
+ size_t message_size;
+ size_t tmp_size;
+ char envelope;
+
+ mm_errno = MM_ERROR_NONE;
+ envelope = 1;
+
+ message = NULL;
+ message_size = 0;
+
+ if (ctx->boundary == NULL) {
+ if (mm_context_iscomposite(ctx)) {
+ mm_context_generateboundary(ctx);
+ }
+ }
+
+ TAILQ_FOREACH(part, &ctx->parts, next) {
+ if (envelope) {
+ if (flags & MM_FLATTEN_SKIPENVELOPE) {
+ envelope = 0;
+ if ((message = (char *) malloc(1)) == NULL) {
+ mm_errno = MM_ERROR_ERRNO;
+ goto cleanup;
+ }
+ *message = '\0';
+ continue;
+ }
+
+ if (part->type == NULL && mm_context_countparts(ctx) > 1) {
+ if (mm_mimepart_setdefaultcontenttype(part, 1)
+ == -1) {
+ goto cleanup;
+ }
+ if (mm_context_generateboundary(ctx) == -1) {
+ goto cleanup;
+ }
+ ctx->messagetype = MM_MSGTYPE_MULTIPART;
+ }
+
+ if (mm_envelope_getheaders(ctx, &envelope_headers,
+ &tmp_size) == -1) {
+ return -1;
+ }
+
+ message = envelope_headers;
+ message_size = tmp_size;
+ envelope = 0;
+
+ if (ctx->preamble != NULL
+ && mm_context_iscomposite(ctx)
+ && !(flags & MM_FLATTEN_NOPREAMBLE)) {
+ tmp_size += strlen(ctx->preamble)
+ + (strlen("\r\n") * 2);
+ buf = (char *)xrealloc(message, tmp_size);
+ if (buf == NULL) {
+ goto cleanup;
+ }
+ message_size += tmp_size;
+ message = buf;
+ strlcat(message, "\r\n", message_size);
+ strlcat(message, ctx->preamble, message_size);
+ strlcat(message, "\r\n", message_size);
+ }
+ } else {
+ /* Enforce Content-Type if none exist */
+ if (part->type == NULL) {
+ if (mm_mimepart_setdefaultcontenttype(part, 0)
+ == -1) {
+ goto cleanup;
+ }
+ }
+
+ /* Append a boundary if necessary */
+ if (ctx->boundary != NULL) {
+ tmp_size = strlen(ctx->boundary) +
+ (strlen("\r\n") * 2) + strlen("--");
+
+ if (tmp_size < 1) {
+ return(-1);
+ }
+ if (message_size + tmp_size < 1) {
+ return(-1);
+ }
+
+ buf = (char *)xrealloc(message, message_size
+ + tmp_size);
+ if (buf == NULL) {
+ goto cleanup;
+ }
+ message_size += tmp_size;
+ message = buf;
+ strlcat(message, "\r\n", message_size);
+ strlcat(message, "--", message_size);
+ strlcat(message, ctx->boundary, message_size);
+ strlcat(message, "\r\n", message_size);
+ }
+
+ if (mm_mimepart_flatten(part, &flatpart, &tmp_size,
+ (flags & MM_FLATTEN_OPAQUE)) == -1) {
+ goto cleanup;
+ }
+
+ if (tmp_size < 1) {
+ goto cleanup;
+ }
+
+ buf = (char *) xrealloc(message, message_size
+ + tmp_size);
+ if (buf == NULL) {
+ goto cleanup;
+ }
+
+ message_size += tmp_size;
+ message = buf;
+
+ strlcat(message, flatpart, message_size);
+ xfree(flatpart);
+ flatpart = NULL;
+ }
+ }
+
+ /* Append end boundary */
+ if (ctx->boundary != NULL && mm_context_iscomposite(ctx)) {
+ tmp_size = strlen(ctx->boundary) + (strlen("\r\n") * 2)
+ + (strlen("--") * 2);
+ buf = (char *)xrealloc(message, message_size + tmp_size);
+ if (buf == NULL) {
+ goto cleanup;
+ }
+
+ message_size += tmp_size;
+ message = buf;
+ if (message[strlen(message)-1] != 13)
+ strlcat(message, "\r", message_size);
+ strlcat(message, "\n", message_size);
+ strlcat(message, "--", message_size);
+ strlcat(message, ctx->boundary, message_size);
+ strlcat(message, "--", message_size);
+ strlcat(message, "\r\n", message_size);
+ }
+
+ *flat = message;
+ *length = message_size;
+
+ return 0;
+
+cleanup:
+ if (message != NULL) {
+ xfree(message);
+ message = NULL;
+ }
+ return -1;
+}
+
+/** @} */
diff --git a/main/minimime/mm_envelope.c b/main/minimime/mm_envelope.c
new file mode 100644
index 000000000..e94bc475d
--- /dev/null
+++ b/main/minimime/mm_envelope.c
@@ -0,0 +1,269 @@
+/*
+ * $Id$
+ *
+ * MiniMIME - a library for handling MIME messages
+ *
+ * Copyright (C) 2003 Jann Fischer <rezine@mistrust.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "mm_internal.h"
+#include "mm_util.h"
+
+/** @file mm_envelope.c
+ *
+ * This module contains functions for accessing a message's envelope. This
+ * are mainly wrapper functions for easy access.
+ */
+
+/** @defgroup envelope Accessing and manipulating a message's envelope
+ */
+
+/** @{
+ * @name Accessing and manipulating a message's envelope
+ */
+
+/**
+ * Gets an ASCII representation of all envelope headers
+ *
+ * @param ctx A valid MiniMIME context
+ * @param result Where to store the resulting ASCII headers
+ * @param length Where to store the length of the result
+ * @returns 0 on success or -1 on failure.
+ * @note Sets mm_errno on failure
+ *
+ * This is mainly a convinience function. It constructs an ASCII representation
+ * from all of the message's envelope headers and stores the result in headers.
+ * Memory is allocated dynamically, and the total length of the result is
+ * stored in length. This function takes care that the output is MIME conform,
+ * and folds long lines according to the MIME standard at position 78 of the
+ * string. It also nicely formats all MIME related header fields, such as
+ * the Content-Type header.
+ *
+ * Since the memory needed to store the result is allocated dynamically, one
+ * should take care of freeing it again when it's not needed anymore. If an
+ * error occurs, *result will be set to NULL, *length will be set to zero
+ * and mm_errno will be set to a reasonable value.
+ *
+ */
+int
+mm_envelope_getheaders(MM_CTX *ctx, char **result, size_t *length)
+{
+ struct mm_mimepart *part;
+ struct mm_mimeheader *hdr;
+ char *buf, *hdrbuf;
+ size_t headers_length, tmp_length;
+
+ headers_length = 1;
+ buf = NULL;
+
+ part = mm_context_getpart(ctx, 0);
+ if (part == NULL) {
+ return -1;
+ }
+
+ /* Initialize our buffer */
+ if ((buf = (char *)xmalloc(headers_length)) == NULL) {
+ mm_errno = MM_ERROR_ERRNO;
+ goto cleanup;
+ }
+ *buf = '\0';
+
+ /* Store each envelope header */
+ TAILQ_FOREACH(hdr, &part->headers, next) {
+ tmp_length = strlen(hdr->name) + strlen(hdr->value)
+ + strlen(": \r\n");
+ hdrbuf = (char *) xrealloc(buf, headers_length + tmp_length);
+ if (hdrbuf == NULL) {
+ mm_errno = MM_ERROR_ERRNO;
+ goto cleanup;
+ }
+
+ headers_length += tmp_length;
+ buf = hdrbuf;
+
+ strlcat(buf, hdr->name, headers_length);
+ strlcat(buf, ": ", headers_length);
+ strlcat(buf, hdr->value, headers_length);
+ strlcat(buf, "\r\n", headers_length);
+ }
+
+ /* Construct and store MIME headers */
+ if (part->type != NULL) {
+ char *typebuf;
+ typebuf = mm_content_tostring(part->type);
+ if (typebuf == NULL) {
+ goto cleanup;
+ }
+ tmp_length = strlen(typebuf) + strlen("\r\n");
+
+ hdrbuf = (char *) xrealloc(buf, headers_length + tmp_length);
+ if (hdrbuf == NULL) {
+ mm_errno = MM_ERROR_ERRNO;
+ goto cleanup;
+ }
+
+ headers_length += tmp_length;
+ buf = hdrbuf;
+
+ strlcat(buf, typebuf, headers_length);
+ strlcat(buf, "\r\n", headers_length);
+ }
+
+ *result = buf;
+ *length = headers_length;
+
+ return 0;
+
+cleanup:
+ if (buf != NULL) {
+ xfree(buf);
+ buf = NULL;
+ }
+ *result = NULL;
+ *length = 0;
+ return -1;
+}
+
+/**
+ * Sets a header field in the envelope
+ *
+ * @param ctx A valid MiniMIME context
+ * @param name The name of the header field to set
+ * @param fmt A format string specifying the value of the header field
+ * @return 0 on success or -1 on failure
+ *
+ * This function generates a new MIME header and attaches it to the first
+ * MIME part (the envelope) found in the given context. If no part is
+ * attached already, the function will return an error. The function will
+ * store a copy of ``name'' as the header's name field, and dynamically
+ * allocate the memory needed to build the format string.
+ */
+int
+mm_envelope_setheader(MM_CTX *ctx, const char *name, const char *fmt, ...)
+{
+ va_list ap;
+ char *buf;
+ struct mm_mimeheader *hdr;
+ struct mm_mimepart *part;
+
+ part = mm_context_getpart(ctx, 0);
+ if (part == NULL) {
+ return(-1);
+ }
+
+ hdr = mm_mimeheader_new();
+ if (hdr == NULL) {
+ return(-1);
+ }
+
+ hdr->name = xstrdup(name);
+
+ va_start(ap, fmt);
+ if (vasprintf(&buf, fmt, ap) == -1) {
+ goto cleanup;
+ }
+ va_end(ap);
+
+ hdr->value = buf;
+
+ if (mm_mimepart_attachheader(part, hdr) == -1) {
+ goto cleanup;
+ }
+
+ return(0);
+
+cleanup:
+ if (hdr != NULL) {
+ if (hdr->name != NULL) {
+ xfree(hdr->name);
+ hdr->name = NULL;
+ }
+ if (hdr->value != NULL) {
+ xfree(hdr->value);
+ hdr->value = NULL;
+ }
+ }
+ return(-1);
+}
+
+/**
+ * Gets the list of recipients for a MIME message
+ *
+ * @param ctx A valid MiniMIME context
+ * @param result Where to store the result
+ * @param length Where to store the length of the result
+ * @returns 0 on success or -1 on error
+ * @note Sets mm_errno on error
+ *
+ * This functions gets the list of recipients for a given MIME message. It
+ * does so by concatenating the "From" and "Cc" header fields, and storing
+ * the results in recipients. The memory needed to store the result is
+ * allocated dynamically, and the total length of the result is stored in
+ * length.
+ *
+ * One should take care to free() the result once it's not needed anymore.
+ */
+int
+mm_envelope_getrecipients(MM_CTX *ctx, char **result, size_t *length)
+{
+ struct mm_mimepart *part;
+ struct mm_mimeheader *to, *cc;
+ size_t recipients_length;
+
+ part = mm_context_getpart(ctx, 0);
+ if (part == NULL) {
+ return -1;
+ }
+
+ to = mm_mimepart_getheaderbyname(part, "From", 0);
+ cc = mm_mimepart_getheaderbyname(part, "Cc", 0);
+
+ if (to == NULL || cc == NULL) {
+ *result = NULL;
+ *length = 0;
+ return -1;
+ }
+
+ if (to != NULL) {
+ recipients_length += strlen(to->value);
+ }
+ if (cc != NULL) {
+ recipients_length += strlen(cc->value);
+ }
+
+ return 0;
+}
+
+/** @} */
diff --git a/main/minimime/mm_error.c b/main/minimime/mm_error.c
new file mode 100644
index 000000000..5b27bf724
--- /dev/null
+++ b/main/minimime/mm_error.c
@@ -0,0 +1,123 @@
+/*
+ * $Id$
+ *
+ * MiniMIME - a library for handling MIME messages
+ *
+ * Copyright (C) 2003 Jann Fischer <rezine@mistrust.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "mm_internal.h"
+#include "mm_util.h"
+
+/** @file mm_error.c
+ *
+ * This module contains functions for MiniMIME error information/manipulation
+ */
+
+/** @defgroup error MiniMIME error functions */
+
+/**
+ * Initializes the global error object
+ *
+ * @ingroup error
+ *
+ * This function initializes the global error object mm_error. This must be
+ * done when the library is initialized, and is automatically called from
+ * mm_init_library().
+ */
+void
+mm_error_init(void)
+{
+ mm_error.error_id = 0;
+ mm_error.error_where = 0;
+ mm_error.lineno = 0;
+ memset(&mm_error.error_msg, '\0', sizeof(mm_error.error_msg));
+}
+
+/**
+ * Sets a descriptive error message
+ *
+ * @param fmt The error message as format string
+ * @ingroup error
+ *
+ * This function is called from the various MiniMIME modules in case an
+ * error occured. Should never be called by the user.
+ */
+void
+mm_error_setmsg(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(mm_error.error_msg, sizeof(mm_error.error_msg), fmt, ap);
+ va_end(ap);
+
+}
+
+void
+mm_error_setlineno(int lineno)
+{
+ mm_error.lineno = lineno;
+}
+
+/**
+ * Retrieves the current error message
+ *
+ * @return The currently set error message
+ * @ingroup error
+ *
+ * This function can be used to retrieve a descriptive error message for the
+ * current error, much like strerror() function of libc. When this function
+ * is called without an error being set, it returns the string "No error".
+ * The string returned does not need to be freed, since it is not dynamically
+ * allocated by the library.
+ */
+char *
+mm_error_string(void)
+{
+ if (mm_errno != MM_ERROR_ERRNO && mm_error.error_msg[0] == '\0') {
+ return "No error";
+ } else if (mm_errno == MM_ERROR_ERRNO) {
+ return strerror(errno);
+ } else {
+ return mm_error.error_msg;
+ }
+}
+
+int
+mm_error_lineno(void)
+{
+ return mm_error.lineno;
+}
diff --git a/main/minimime/mm_header.c b/main/minimime/mm_header.c
new file mode 100644
index 000000000..827c19cac
--- /dev/null
+++ b/main/minimime/mm_header.c
@@ -0,0 +1,213 @@
+/*
+ * $Id$
+ *
+ * MiniMIME - a library for handling MIME messages
+ *
+ * Copyright (C) 2003 Jann Fischer <rezine@mistrust.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "mm_internal.h"
+#include "mm_util.h"
+
+/** @file mm_header.c
+ *
+ * This module contains functions for manipulating MIME headers
+ */
+
+/**
+ * Creates a new MIME header object
+ *
+ * @return A new and initialized MIME header object
+ * @see mm_mimeheader_free
+ *
+ * This function creates and initializes a new MIME header object, which must
+ * later be freed using mm_mimeheader_free()
+ */
+struct mm_mimeheader *
+mm_mimeheader_new(void)
+{
+ struct mm_mimeheader *header;
+
+ header = (struct mm_mimeheader *)xmalloc(sizeof(struct mm_mimeheader));
+
+ header->name = NULL;
+ header->value = NULL;
+ TAILQ_INIT(&header->params);
+
+ return header;
+}
+
+/**
+ * Frees a MIME header object
+ *
+ * @param header The MIME header object which to free
+ */
+void
+mm_mimeheader_free(struct mm_mimeheader *header)
+{
+ struct mm_param *param;
+ assert(header != NULL);
+
+ if (header->name != NULL) {
+ xfree(header->name);
+ header->name = NULL;
+ }
+ if (header->value != NULL) {
+ xfree(header->value);
+ header->value = NULL;
+ }
+
+ TAILQ_FOREACH(param, &header->params, next) {
+ TAILQ_REMOVE(&header->params, param, next);
+ mm_param_free(param);
+ }
+xfree(header);
+ header = NULL;
+}
+
+/**
+ * Creates a new MIME header, but does no checks whatsoever (create as-is)
+ */
+struct mm_mimeheader *
+mm_mimeheader_generate(const char *name, const char *value)
+{
+ struct mm_mimeheader *header;
+
+ header = mm_mimeheader_new();
+
+ header->name = xstrdup(name);
+ header->value = xstrdup(value);
+
+ return header;
+}
+
+/**
+ * Attaches a parameter to a MimeHeader object
+ *
+ * @param hdr The target MimeHeader object
+ * @param param The parameter to attach
+ * @return 0 on success and -1 on failure
+ * @ingroup mimeheader
+ */
+int
+mm_mimeheader_attachparam(struct mm_mimeheader *hdr, struct mm_param *param)
+{
+ assert(hdr != NULL);
+ assert(param != NULL);
+
+ if (TAILQ_EMPTY(&hdr->params)) {
+ TAILQ_INSERT_HEAD(&hdr->params, param, next);
+ } else {
+ TAILQ_INSERT_TAIL(&hdr->params, param, next);
+ }
+
+ return 0;
+}
+
+
+/**
+ * Gets a parameter value from a MimeHeader object.
+ *
+ * @param hdr the MimeHeader object
+ * @param name the name of the parameter to retrieve
+ * @return The value of the parameter on success or a NULL pointer on failure
+ * @ingroup mimeheader
+ */
+char *
+mm_mimeheader_getparambyname(struct mm_mimeheader *hdr, const char *name)
+{
+ struct mm_param *param;
+
+ assert(hdr != NULL);
+
+ TAILQ_FOREACH(param, &hdr->params, next) {
+ if (!strcasecmp(param->name, name)) {
+ return param->value;
+ }
+ }
+
+ return NULL;
+}
+
+int
+mm_mimeheader_uncomment(struct mm_mimeheader *header)
+{
+ char *new;
+
+ assert(header != NULL);
+ assert(header->name != NULL);
+ assert(header->value != NULL);
+
+ new = mm_uncomment(header->value);
+ if (new == NULL)
+ return -1;
+
+ xfree(header->value);
+ header->value = new;
+
+ return 0;
+}
+
+int
+mm_mimeheader_uncommentbyname(struct mm_mimepart *part, const char *name)
+{
+ struct mm_mimeheader *header;
+
+ TAILQ_FOREACH(header, &part->headers, next) {
+ if (!strcasecmp(header->name, name)) {
+ return mm_mimeheader_uncomment(header);
+ }
+ }
+
+ /* Not found */
+ return -1;
+}
+
+int
+mm_mimeheader_uncommentall(struct mm_mimepart *part)
+{
+ struct mm_mimeheader *header;
+ int ret, r;
+
+ ret = 0;
+
+ TAILQ_FOREACH(header, &part->headers, next) {
+ if ((r = mm_mimeheader_uncomment(header)) == -1) {
+ ret = -1;
+ }
+ }
+
+ return ret;
+}
diff --git a/main/minimime/mm_init.c b/main/minimime/mm_init.c
new file mode 100644
index 000000000..2ec37db6b
--- /dev/null
+++ b/main/minimime/mm_init.c
@@ -0,0 +1,65 @@
+/*
+ * $Id$
+ *
+ * MiniMIME - a library for handling MIME messages
+ *
+ * Copyright (C) 2003 Jann Fischer <rezine@mistrust.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <assert.h>
+
+#include "mm_internal.h"
+
+int mm_errno;
+struct mm_error_data mm_error;
+static int mm_initialized;
+struct mm_codecs codecs;
+
+int
+mm_library_init(void)
+{
+ assert(mm_initialized != 1);
+
+ mm_errno = MM_ERROR_NONE;
+ mm_initialized = 1;
+
+ SLIST_INIT(&codecs);
+
+ mm_error_init();
+
+ return 0;
+}
+
+int
+mm_library_isinitialized(void)
+{
+ return mm_initialized;
+}
diff --git a/main/minimime/mm_internal.h b/main/minimime/mm_internal.h
new file mode 100644
index 000000000..155591487
--- /dev/null
+++ b/main/minimime/mm_internal.h
@@ -0,0 +1,65 @@
+/*
+ * $Id$
+ *
+ * MiniMIME - a library for handling MIME messages
+ *
+ * Copyright (C) 2003 Jann Fischer <rezine@mistrust.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/** @file mm_internal.h
+ * Data definitions for MiniMIME
+ */
+#ifndef _MM_INTERNAL_H_INCLUDED
+#define _MM_INTERNAL_H_INCLUDED
+
+#include "mm.h"
+
+#define debugp(m, ...) do { \
+ fprintf(stderr, "%s:%d:: ", __FILE__, __LINE__); \
+ fprintf(stderr, m, ## __VA_ARGS__); \
+ fprintf(stderr, "\n"); \
+ fflush(stderr); \
+} while (0);
+
+/**
+ * @{
+ * @name Utility functions
+ */
+#ifndef __HAVE_LEAK_DETECTION
+void *xmalloc(size_t);
+void *xrealloc(void *, size_t);
+void xfree(void *);
+char *xstrdup(const char *);
+#endif
+
+char *xstrsep(char **, const char *);
+
+/* THIS FILE IS INTENTIONALLY LEFT BLANK */
+
+#endif /* ! _MM_INTERNAL_H_INCLUDED */
diff --git a/main/minimime/mm_mem.c b/main/minimime/mm_mem.c
new file mode 100644
index 000000000..91ad3b987
--- /dev/null
+++ b/main/minimime/mm_mem.c
@@ -0,0 +1,171 @@
+/*
+ * $Id$
+ *
+ * MiniMIME - a library for handling MIME messages
+ *
+ * Copyright (C) 2003 Jann Fischer <rezine@mistrust.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <err.h>
+#include <assert.h>
+
+#include "mm_internal.h"
+
+#ifdef __HAVE_LEAK_DETECTION
+# include "mm_mem.h"
+
+static struct MM_chunks chunks;
+
+void *
+MM_malloc(size_t size, char *filename, int line)
+{
+ struct MM_mem_chunk *chunk;
+ void *pointer;
+
+ pointer = malloc(size);
+ if (pointer == NULL)
+ err(1, "malloc");
+
+ chunk = (struct MM_mem_chunk *)malloc(sizeof(struct MM_mem_chunk));
+ if (chunk == NULL)
+ err(1, "malloc");
+
+ chunk->address = pointer;
+ chunk->size = size;
+ chunk->filename = filename;
+ chunk->line = line;
+
+ TAILQ_INSERT_TAIL(&chunks, chunk, next);
+
+ return pointer;
+}
+
+char *
+MM_strdup(const char *s, char *filename, int line)
+{
+ char *r;
+
+ r = (char *)MM_malloc(strlen(s)+1, filename, line);
+ strlcpy(r, s, strlen(s) + 1);
+ if (strlen(r) != strlen(s)) {
+ debugp("%d:%d", strlen(s), strlen(r));
+ }
+ return r;
+
+}
+
+void *
+MM_realloc(void *p, size_t new_size, char *filename, int line)
+{
+ void *r;
+ void *a;
+ struct MM_mem_chunk *chunk;
+ struct MM_mem_chunk *last;
+
+ a = p;
+ chunk = NULL;
+ last = NULL;
+
+ assert(new_size > 0);
+
+ TAILQ_FOREACH(chunk, &chunks, next) {
+ if (chunk->address == p) {
+ last = chunk;
+ }
+ }
+
+ if (last == NULL) {
+ debugp("MM_realloc: did not find chunk at %p (%s:%d) "
+ ", creating new", p, filename, line);
+ return MM_malloc(new_size, filename, line);
+ }
+
+ r = realloc(p, new_size);
+ if (r == NULL)
+ return NULL;
+
+ last->address = r;
+ last->size = new_size;
+ last->filename = filename;
+ last->line = line;
+
+ return r;
+}
+
+void
+MM_free(void *pointer, char *filename, int line, char *name)
+{
+ struct MM_mem_chunk *chunk, *nxt;
+
+ for (chunk = TAILQ_FIRST(&chunks); chunk != TAILQ_END(&chunks);
+ chunk = nxt) {
+ nxt = TAILQ_NEXT(&chunks, next);
+ if (chunk->address == pointer) {
+ TAILQ_REMOVE(&chunks, chunk, next);
+ free(chunk->address);
+ free(chunk);
+ return;
+ }
+ }
+
+ debugp("FREE: did not find storage %s (at %p), %s:%d", name, pointer,
+ filename, line);
+}
+
+void
+MM_leakd_flush(void)
+{
+ debugp("flushing memory informations");
+ while (!TAILQ_EMPTY(&chunks))
+ SLIST_REMOVE_HEAD(&chunks, next);
+}
+
+void
+MM_leakd_printallocated(void)
+{
+ struct MM_mem_chunk *chunk;
+ debugp("printing dynamic memory allocations");
+ TAILQ_FOREACH(chunk, &chunks, next) {
+ debugp(" chunk: %p (alloc'ed at %s:%d, size %d)\n",
+ chunk->address, chunk->filename, chunk->line, chunk->size);
+ }
+}
+
+void
+MM_leakd_init(void)
+{
+ TAILQ_INIT(&chunks);
+}
+
+#endif /* !__HAVE_LEAK_DETECTOR */
diff --git a/main/minimime/mm_mem.h b/main/minimime/mm_mem.h
new file mode 100644
index 000000000..5b00e4bee
--- /dev/null
+++ b/main/minimime/mm_mem.h
@@ -0,0 +1,32 @@
+#ifndef __MEM_H
+#define __MEM_H
+
+#ifdef __HAVE_LEAK_DETECTION
+
+#define NAMEOF(v) #v
+#define xmalloc(x) MM_malloc(x, __FILE__, __LINE__)
+#define xfree(x) MM_free(x, __FILE__, __LINE__, NAMEOF(x))
+#define xstrdup(x) MM_strdup(x, __FILE__, __LINE__)
+#define xrealloc(x, y) MM_realloc(x, y, __FILE__, __LINE__)
+
+TAILQ_HEAD(MM_chunks, MM_mem_chunk);
+
+struct MM_mem_chunk {
+ void *address;
+ const char *filename;
+ u_int32_t line;
+ size_t size;
+
+ TAILQ_ENTRY(MM_mem_chunk) next;
+};
+
+void *MM_malloc(size_t, char *, int);
+void *MM_realloc(void *, size_t, char *, int);
+void MM_free(void *, char *, int, char *);
+char *MM_strdup(const char *, char *, int);
+void MM_leakd_init(void);
+void MM_leakd_printallocated(void);
+void MM_leakd_flush(void);
+
+#endif /* __HAVE_LEAK_DETECTION */
+#endif /* ! HAVE_MEM_H */
diff --git a/main/minimime/mm_mimepart.c b/main/minimime/mm_mimepart.c
new file mode 100644
index 000000000..3d2287427
--- /dev/null
+++ b/main/minimime/mm_mimepart.c
@@ -0,0 +1,657 @@
+/*
+ * $Id$
+ *
+ * MiniMIME - a library for handling MIME messages
+ *
+ * Copyright (C) 2003 Jann Fischer <rezine@mistrust.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "mm_internal.h"
+
+/** @file mm_mimepart.c
+ *
+ * This module contains functions for manipulating MIME header objects.
+ */
+
+/** @defgroup mimepart Accessing and manipulating MIME parts
+ *
+ * MIME parts, also called entities, represent the structure of a MIME
+ * message. ``Normal'' internet messages have only a single part, and
+ * are called ``flat'' messages. Multipart messages have more then one
+ * part, and each MIME part can have it's own subset of headers.
+ *
+ * Provided here are functions to easily access all informations from
+ * a MIME part, including their specific headers and bodies.
+ */
+
+/** @{
+ * @name Creating and destroying MIME parts
+ */
+
+/**
+ * Allocates memory for a new mm_mimepart structure and initializes it.
+ *
+ * @return A pointer to a struct of type mm_mimeheader or NULL on failure
+ * @see mm_mimepart_free
+ * @note The memory must be freed by using mm_mimepart_free() later on.
+ */
+struct mm_mimepart *
+mm_mimepart_new(void)
+{
+ struct mm_mimepart *part;
+
+ part = (struct mm_mimepart *)xmalloc(sizeof(struct mm_mimepart));
+
+ TAILQ_INIT(&part->headers);
+
+ part->opaque_length = 0;
+ part->opaque_body = NULL;
+
+ part->length = 0;
+ part->body = NULL;
+
+ part->type = NULL;
+
+ return part;
+}
+
+/**
+ * Creates a MIME part from a file
+ *
+ * @param filename The name of the file to create the MIME part from
+ * @return A pointer to a new MIME part object
+ *
+ * This function creates a new MIME part object from a file. The object should
+ * be freed using mm_mimepart_free() later on. This function does NOT set the
+ * Content-Type and neither does any encoding work.
+ */
+struct mm_mimepart *
+mm_mimepart_fromfile(const char *filename)
+{
+ int fd;
+ char *data;
+ size_t r;
+ struct stat st;
+ struct mm_mimepart *part;
+
+ mm_errno = MM_ERROR_NONE;
+
+ if ((fd = open(filename, O_RDONLY)) == -1) {
+ mm_errno = MM_ERROR_ERRNO;
+ return NULL;
+ }
+
+ if ((stat(filename, &st)) == -1) {
+ mm_errno = MM_ERROR_ERRNO;
+ close(fd);
+ return NULL;
+ }
+
+ data = xmalloc(st.st_size);
+ r = read(fd, data, st.st_size);
+ if (r != st.st_size) {
+ mm_errno = MM_ERROR_ERRNO;
+ close(fd);
+ return(NULL);
+ }
+
+ data[r] = '\0';
+ close(fd);
+
+ part = mm_mimepart_new();
+ part->length = r;
+ part->body = data;
+
+ return part;
+}
+
+
+/**
+ * Frees all memory allocated by a mm_mimepart object.
+ *
+ * @param part A pointer to an allocated mm_mimepart object
+ * @see mm_mimepart_new
+ */
+void
+mm_mimepart_free(struct mm_mimepart *part)
+{
+ struct mm_mimeheader *header;
+
+ assert(part != NULL);
+
+ TAILQ_FOREACH(header, &part->headers, next) {
+ mm_mimeheader_free(header);
+ TAILQ_REMOVE(&part->headers, header, next);
+ }
+
+ if (part->opaque_body != NULL) {
+ xfree(part->opaque_body);
+ part->opaque_body = NULL;
+ part->body = NULL;
+ } else if (part->body != NULL) {
+ xfree(part->body);
+ part->body = NULL;
+ }
+
+ if (part->type != NULL) {
+ mm_content_free(part->type);
+ part->type = NULL;
+ }
+
+ xfree(part);
+ part = NULL;
+}
+
+/** @} */
+
+/** @{
+ * @name Accessing the MIME part's mail header
+ */
+
+/**
+ * Attaches a mm_mimeheader object to a MIME part
+ *
+ * @param part A valid MIME part object
+ * @param header A valid MIME header object
+ * @return 0 if successfull or -1 if the header could not be attached
+ */
+int
+mm_mimepart_attachheader(struct mm_mimepart *part, struct mm_mimeheader *header)
+{
+ assert(part != NULL);
+ assert(header != NULL);
+
+ if (TAILQ_EMPTY(&part->headers)) {
+ TAILQ_INSERT_HEAD(&part->headers, header, next);
+ } else {
+ TAILQ_INSERT_TAIL(&part->headers, header, next);
+ }
+
+ return(0);
+}
+
+/**
+ * Retrieves the number of MIME headers available in a MIME part
+ *
+ * @param part A valid MIME part object
+ * @return The number of MIME headers within the MIME part
+ */
+int
+mm_mimepart_countheaders(struct mm_mimepart *part)
+{
+ int found;
+ struct mm_mimeheader *header;
+
+ assert(part != NULL);
+
+ found = 0;
+
+ TAILQ_FOREACH(header, &part->headers, next) {
+ found++;
+ }
+
+ return found;
+}
+
+/**
+ * Retrieves the number of MIME headers with a given name in a MIME part
+ *
+ * @param part A valid MIME part object
+ * @param name The name of the MIME header which to count for
+ * @return The number of MIME headers within the MIME part
+ */
+int
+mm_mimepart_countheaderbyname(struct mm_mimepart *part, const char *name)
+{
+ int found;
+ struct mm_mimeheader *header;
+
+ assert(part != NULL);
+
+ found = 0;
+
+ TAILQ_FOREACH(header, &part->headers, next) {
+ if (strcasecmp(header->name, name) == 0) {
+ found++;
+ }
+ }
+
+ return found;
+}
+
+/**
+ * Get a MIME header object from a MIME part
+ *
+ * @param part A valid MIME part object
+ * @param name The name of the MIME header which to retrieve
+ * @param idx Which header field to get (in case of multiple headers of the
+ * same name).
+ * @return A pointer to the requested MIME header on success, or NULL if there
+ * either isn't a header with the requested name or idx is out of
+ * range.
+ */
+struct mm_mimeheader *
+mm_mimepart_getheaderbyname(struct mm_mimepart *part, const char *name, int idx)
+{
+ struct mm_mimeheader *header;
+ int curidx;
+
+ curidx = 0;
+
+ TAILQ_FOREACH(header, &part->headers, next) {
+ if (!strcasecmp(header->name, name)) {
+ if (curidx == idx)
+ return header;
+ else
+ curidx++;
+ }
+ }
+
+ /* Not found */
+ return NULL;
+}
+
+/**
+ * Gets the value of a MIME header object
+ *
+ * @param part A valid MIME part object
+ * @param name The name of the header field to get the value from
+ * @param idx The index of the header field to get, in case there are multiple
+ * headers with the same name.
+ * @return A pointer to the requested value on success, or NULL if there either
+ * isn't a header with the requested name or idx is out of range.
+ *
+ */
+const char *
+mm_mimepart_getheadervalue(struct mm_mimepart *part, const char *name, int idx)
+{
+ struct mm_mimeheader *header;
+
+ header = mm_mimepart_getheaderbyname(part, name, idx);
+ if (header == NULL)
+ return NULL;
+ else
+ return header->value;
+}
+
+/**
+ * Initializes a header loop for a given MIME part
+ *
+ * @param part A valid MIME part object
+ * @param id The address of a MIME header object (to allow reentrance)
+ * @return 0 on success or -1 on failure
+ * @see mm_mimepart_headers_next
+ *
+ * Looping through headers can be done in the following way:
+ *
+ * @code
+ * struct mm_mimeheader *header, *lheader;
+ *
+ * mm_mimepart_headers_start(part, &lheader);
+ *
+ * while ((header = mm_mimepart_headers_next(part, &lheader)) != NULL) {
+ * printf("%s: %s\n", header->name, header->value);
+ * }
+ *
+ * @endcode
+ *
+ * For convienience, the macro mm_mimepart_headers_foreach() can be used to
+ * loop through headers in a one-shot manner.
+ */
+int
+mm_mimepart_headers_start(struct mm_mimepart *part, struct mm_mimeheader **id)
+{
+ assert(part != NULL);
+
+ if (TAILQ_EMPTY(&part->headers)) {
+ return -1;
+ }
+ *id = NULL;
+ return 0;
+}
+
+/**
+ * Returns the next MIME header of a given MIME part object
+ *
+ * @param part A valid MIME part object
+ * @param id A previously initialized MIME header object
+ * @return A pointer to the MIME header object or NULL if end of headers was
+ * reached.
+ * @see mm_mimepart_headers_start
+ */
+struct mm_mimeheader *
+mm_mimepart_headers_next(struct mm_mimepart *part, struct mm_mimeheader **id)
+{
+ struct mm_mimeheader *header;
+
+ assert(part != NULL);
+
+ if (*id == NULL) {
+ header = TAILQ_FIRST(&part->headers);
+ } else {
+ header = TAILQ_NEXT(*id, next);
+ }
+ *id = header;
+
+ return header;
+}
+
+/** @} */
+
+/** @{
+ * @name Accessing and manipulating the MIME part's body
+ */
+
+/**
+ * Gets the pointer to the MIME part's body data
+ *
+ * @param part A valid MIME part object
+ * @param opaque Whether to get the opaque part or not
+ * @return A pointer to the MIME part's body
+ * @see mm_mimepart_setbody
+ *
+ */
+char *
+mm_mimepart_getbody(struct mm_mimepart *part, int opaque)
+{
+ assert(part != NULL);
+
+ if (opaque)
+ return part->opaque_body;
+ else
+ return part->body;
+}
+
+/**
+ * Sets the MIME part's body data
+ *
+ * @param part A valid MIME part object
+ * @param data A pointer to the data which to set
+ * @see mm_mimepart_getbody
+ *
+ * This functions sets the body data for a given MIME part. The string pointed
+ * to by data must be NUL-terminated. The data is copied into the MIME part's
+ * body, and thus, the memory pointed to by data can be freed after the
+ * operation.
+ */
+void
+mm_mimepart_setbody(struct mm_mimepart *part, const char *data, int opaque)
+{
+ assert(part != NULL);
+ assert(data != NULL);
+
+ if (opaque) {
+ part->opaque_body = xstrdup(data);
+ part->body = part->opaque_body;
+ } else {
+ part->body = xstrdup(data);
+ }
+ part->length = strlen(data);
+}
+
+/**
+ * Gets the length of a given MIME part object
+ *
+ * @param part A valid MIME part object
+ * @returns The size of the part's body in byte.
+ *
+ * This function returns the total length of the given MIME part's body. The
+ * length does not include the headers of the MIME parts. If the function
+ * returns 0, no body part is set currently.
+ */
+size_t
+mm_mimepart_getlength(struct mm_mimepart *part)
+{
+ assert(part != NULL);
+
+ return part->length;
+}
+
+
+/**
+ * Decodes a MIME part according to it's encoding using MiniMIME codecs
+ *
+ * @param A valid MIME part object
+ * @return 0 if the MIME part could be successfully decoded or -1 if not
+ * @note Sets mm_errno on error
+ *
+ * This function decodes the body of a MIME part with a registered decoder
+ * according to it's Content-Transfer-Encoding header field.
+ */
+char *
+mm_mimepart_decode(struct mm_mimepart *part)
+{
+ extern struct mm_codecs codecs;
+ struct mm_codec *codec;
+ void *decoded;
+
+ assert(part != NULL);
+ assert(part->type != NULL);
+
+ decoded = NULL;
+
+ /* No encoding associated */
+ if (part->type->encstring == NULL)
+ return NULL;
+
+ /* Loop through codecs and find a suitable one */
+ SLIST_FOREACH(codec, &codecs, next) {
+ if (!strcasecmp(part->type->encstring, codec->encoding)) {
+ decoded = codec->decoder((char *)part->body);
+ break;
+ }
+ }
+
+ return decoded;
+}
+
+/**
+ * Creates an ASCII representation of the given MIME part
+ *
+ * @param part A valid MIME part object
+ * @param result Where to store the result
+ * @param length Where to store the length of the result
+ * @param opaque Whether to use the opaque MIME part
+ * @returtn 0 on success or -1 on error.
+ * @see mm_context_flatten
+ *
+ * This function creates an ASCII representation of a given MIME part. It will
+ * dynamically allocate the memory needed and stores the result in the memory
+ * region pointed to by result. The length of the result will be stored in
+ * length. If opaque is set to 1, mm_mimepart_flatten will store an opaque
+ * version of the MIME part in result, which means no headers will be created
+ * or sanitized. This is particulary useful if the part is digitally signed by
+ * e.g. PGP, and the signature spans the header fields of the part in question.
+ *
+ */
+int
+mm_mimepart_flatten(struct mm_mimepart *part, char **result, size_t *length,
+ int opaque)
+{
+ size_t part_length;
+ char *buf;
+ char *ct_hdr;
+
+ *result = NULL;
+ *length = 0;
+ buf = NULL;
+ ct_hdr = NULL;
+ part_length = 0;
+
+ if (opaque && part->opaque_body != NULL) {
+ part_length = strlen(part->opaque_body);
+ *result = xstrdup(part->opaque_body);
+ *length = part_length;
+ return(0);
+ } else {
+ if (part->type == NULL) {
+ return(-1);
+ }
+
+ ct_hdr = mm_content_tostring(part->type);
+ if (ct_hdr == NULL) {
+ return(-1);
+ }
+
+ part_length += strlen(ct_hdr) + 2;
+ part_length += strlen("\r\n") * 2;
+ part_length += strlen(part->body);
+
+ if (part_length < 0) {
+ goto cleanup;
+ }
+
+ buf = (char *) xmalloc(part_length);
+ if (buf == NULL) {
+ goto cleanup;
+ }
+
+ snprintf(buf, part_length,
+ "%s\r\n\r\n%s\r\n",
+ ct_hdr,
+ part->body);
+
+ xfree(ct_hdr);
+ ct_hdr = NULL;
+
+ *result = buf;
+ *length = part_length;
+ }
+
+ return(0);
+
+cleanup:
+ if (ct_hdr != NULL) {
+ xfree(ct_hdr);
+ ct_hdr = NULL;
+ }
+ if (buf != NULL) {
+ xfree(buf);
+ buf = NULL;
+ }
+
+ *result = NULL;
+ *length = 0;
+
+ return -1;
+}
+
+/**
+ * Sets the default Content-Type for a given MIME part
+ *
+ * @param part A valid MIME part object
+ * @param part Whether the Content-Type should be for composite or not
+ * @return 0 on success or -1 on failure
+ *
+ * This function sets a default Content-Type according to RFC 2045 with a value
+ * of "text/plain; charset="us-ascii"". This function should only be used if
+ * the MIME part in question does not have a valid Content-Type specification.
+ */
+int
+mm_mimepart_setdefaultcontenttype(struct mm_mimepart *part, int composite)
+{
+ struct mm_content *type;
+ struct mm_param *param;
+
+ if (part == NULL) {
+ return(-1);
+ }
+
+ if (part->type != NULL) {
+ mm_content_free(part->type);
+ part->type = NULL;
+ }
+
+ type = mm_content_new();
+ if (composite) {
+ type->maintype = xstrdup("multipart");
+ type->subtype = xstrdup("mixed");
+ } else {
+ type->maintype = xstrdup("text");
+ type->subtype = xstrdup("plain");
+ param = mm_param_new();
+ param->name = xstrdup("charset");
+ param->value = xstrdup("us-ascii");
+ mm_content_attachtypeparam(type, param);
+ }
+
+ mm_mimepart_attachcontenttype(part, type);
+
+ return (0);
+}
+
+/** @{
+ * @name Accessing the MIME part's Content-Type information
+ */
+
+/**
+ * Attaches a context type object to a MIME part
+ *
+ * @param part A valid MIME part object
+ * @param ct The content type object to attach
+ * @return Nothing
+ *
+ * This function attaches a Content-Type object to a MIME part. It does not
+ * care whether the Content-Type suites the actual content in the MIME part,
+ * so the programmer should take care of that.
+ */
+void
+mm_mimepart_attachcontenttype(struct mm_mimepart *part, struct mm_content *ct)
+{
+ part->type = ct;
+}
+
+/**
+ * Gets the Content-Type of a given MIME part object
+ *
+ * @param part A valid MIME part object
+ * @return The Content-Type object of the specified MIME part
+ *
+ * This function returns a pointer to the Content-Type object of the given
+ * MIME part. This pointer might be set to NULL, indicating that there is
+ * no Content-Type object for the given MIME part currently.
+ */
+struct mm_content *
+mm_mimepart_getcontent(struct mm_mimepart *part)
+{
+ assert(part != NULL);
+
+ return part->type;
+}
+
+/** @} */
diff --git a/main/minimime/mm_mimeutil.c b/main/minimime/mm_mimeutil.c
new file mode 100644
index 000000000..4e52a6acf
--- /dev/null
+++ b/main/minimime/mm_mimeutil.c
@@ -0,0 +1,136 @@
+/*
+ * $Id$
+ *
+ * MiniMIME - a library for handling MIME messages
+ *
+ * Copyright (C) 2004 Jann Fischer <rezine@mistrust.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/time.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <assert.h>
+
+#include "mm_internal.h"
+
+#define MM_DATE_LENGTH 50
+
+static const char boundary_charset[] =
+ "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.=";
+
+/** @file mm_mimeutil.c
+ *
+ * This module contains various MIME related utility functions.
+ */
+
+/** @defgroup mimeutil MIME related utility functions */
+
+/**
+ * Generates an RFC 2822 conform date string
+ *
+ * @param timezone Whether to include timezone information
+ * @returns A pointer to the actual date string
+ * @note The pointer returned must be freed some time
+ *
+ * This function generates an RFC 2822 conform date string to use in message
+ * headers. It allocates memory to hold the string and returns a pointer to
+ * it. The generated date is in the format (example):
+ *
+ * Thu, 25 December 2003 16:35:22 +0100 (CET)
+ *
+ * This function dynamically allocates memory and returns a pointer to it.
+ * This memory should be released with free() once not needed anymore.
+ */
+int
+mm_mimeutil_gendate(char **result)
+{
+ time_t curtime;
+ struct tm *curtm;
+
+ if (result != NULL) {
+ curtime = time(NULL);
+ curtm = localtime(&curtime);
+ if ((*result = (char *) malloc(MM_DATE_LENGTH)) == NULL) {
+ return(-1);
+ }
+ return(strftime(*result, MM_DATE_LENGTH,
+ "%a, %d %b %G %T %z (%Z)", curtm));
+ } else {
+ return(-1);
+ }
+}
+
+
+int
+mm_mimeutil_genboundary(char *prefix, size_t length, char **result)
+{
+ size_t total;
+ size_t preflen;
+ struct timeval curtm;
+ int i;
+ int pos;
+
+ total = 0;
+ preflen = 0;
+
+ if (result == NULL) {
+ return(-1);
+ }
+ *result = NULL;
+
+ gettimeofday(&curtm, NULL);
+ srandom(curtm.tv_usec);
+
+ if (prefix != NULL) {
+ total = strlen(prefix);
+ preflen = total;
+ }
+
+ total += length;
+
+ if ((*result = (char *) xmalloc(total + 1)) == NULL) {
+ mm_errno = MM_ERROR_ERRNO;
+ return(-1);
+ }
+
+ *result = '\0';
+
+ if (prefix != NULL) {
+ strlcat(*result, prefix, total);
+ }
+
+ for (i = 0; i < length - 1; i++) {
+ pos = random() % strlen(boundary_charset);
+ *result[i + preflen] = boundary_charset[pos];
+ }
+ *result[total] = '\0';
+
+ return (0);
+}
diff --git a/main/minimime/mm_param.c b/main/minimime/mm_param.c
new file mode 100644
index 000000000..8877c3e13
--- /dev/null
+++ b/main/minimime/mm_param.c
@@ -0,0 +1,215 @@
+/*
+ * $Id$
+ *
+ * MiniMIME - a library for handling MIME messages
+ *
+ * Copyright (C) 2003 Jann Fischer <rezine@mistrust.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "mm_internal.h"
+#include "mm_util.h"
+
+/**
+ * @file mm_param.c
+ *
+ * Functions to manipulate MIME parameters
+ */
+
+/** @defgroup param Accessing and manipulating MIME parameters */
+
+/** @{
+ *
+ * @name Functions for manipulating MIME parameters
+ *
+ * MIME parameters are properties attached to certain MIME headers, such as
+ * Content-Type and Content-Disposition. MIME parameters have a textual
+ * representations as in <i>name=value</i>. They contain important information
+ * about the MIME structure of a message, such as the boundary string used,
+ * which charset was used to encode the message and so on. This module
+ * provides simple to use functions to query or set MIME parameters.
+ *
+ * Each MIME header may hold an arbitrary amount of such parameters, which
+ * are delimeted by each other with a semicolon.
+ */
+
+/**
+ * Creates a new object to hold a MIME parameter.
+ *
+ * @return An object representing a MIME parameter
+ * @see mm_param_free
+ * @note The allocated memory must later be freed using mm_param_free()
+ */
+struct mm_param *
+mm_param_new(void)
+{
+ struct mm_param *param;
+
+ param = (struct mm_param *)xmalloc(sizeof(struct mm_param));
+
+ param->name = NULL;
+ param->value = NULL;
+
+ return param;
+}
+
+/**
+ * Releases all memory associated with a MIME parameter object.
+ *
+ * @param param A valid MIME parameter object to be freed
+ * @return Nothing
+ * @see mm_param_new
+ */
+void
+mm_param_free(struct mm_param *param)
+{
+ assert(param != NULL);
+
+ if (param->name != NULL) {
+ xfree(param->name);
+ param->name = NULL;
+ }
+ if (param->value != NULL) {
+ xfree(param->value);
+ param->value = NULL;
+ }
+ xfree(param);
+}
+
+/**
+ * Generates a new Content-Type parameter with the given name and value
+ *
+ * @param name The name of the MIME parameter
+ * @param value The value of the MIME parameter
+ * @returns A new MIME parameter object
+ * @see mm_param_free
+ * @see mm_param_new
+ *
+ * This function generates a new MIME parameter, with the name
+ * and value given as the arguments. The needed memory for the operation
+ * is allocated dynamically. It stores a copy of name and value in the
+ * actual object, so the memory holding the arguments can safely be
+ * freed after successfull return of this function.
+ */
+struct mm_param *
+mm_param_generate(const char *name, const char *value)
+{
+ struct mm_param *param;
+
+ param = mm_param_new();
+
+ param->name = xstrdup(name);
+ param->value = xstrdup(value);
+
+ return param;
+}
+
+/**
+ * Sets the name of the given MIME parameter
+ *
+ * @param param A valid MIME parameter object
+ * @param name The new name of the parameter
+ * @param copy If set to > 0, copy the value stored in name
+ * @returns The address of the previous name for passing to free()
+ */
+char *
+mm_param_setname(struct mm_param *param, const char *name, int copy)
+{
+ char *retadr;
+ assert(param != NULL);
+
+ retadr = param->name;
+
+ if (copy)
+ param->name = xstrdup(name);
+ else
+ param->name = (char *)name;
+
+ return retadr;
+}
+
+/**
+ * Sets the value of the given MIME parameter
+ *
+ * @param param A valid MIME parameter object
+ * @param name The new value for the parameter
+ * @param copy If set to > 0, copy the value stored in value
+ * @returns The address of the previous value for passing to free()
+ */
+char *
+mm_param_setvalue(struct mm_param *param, const char *value, int copy)
+{
+ char *retadr;
+ assert(param != NULL);
+
+ retadr = param->value;
+
+ if (copy)
+ param->value = xstrdup(value);
+ else
+ param->value = (char *)value;
+
+ return retadr;
+}
+
+/**
+ * Gets the name of a MIME parameter object
+ *
+ * @param param A valid MIME parameter object
+ * @returns The name of the MIME parameter
+ */
+const char *
+mm_param_getname(struct mm_param *param)
+{
+ assert(param != NULL);
+ return param->name;
+}
+
+/**
+ * Gets the value of a MIME parameter object
+ *
+ * @param param A valid MIME parameter object
+ * @returns The value of the MIME parameter
+ */
+const char *
+mm_param_getvalue(struct mm_param *param)
+{
+ assert(param != NULL);
+ return param->value;
+}
+
+/** @} */
diff --git a/main/minimime/mm_parse.c b/main/minimime/mm_parse.c
new file mode 100644
index 000000000..5080f5bc1
--- /dev/null
+++ b/main/minimime/mm_parse.c
@@ -0,0 +1,181 @@
+/*
+ * $Id$
+ *
+ * MiniMIME - a library for handling MIME messages
+ *
+ * Copyright (C) 2003 Jann Fischer <rezine@mistrust.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "mm_internal.h"
+#include "mm_util.h"
+
+#include "mimeparser.h"
+#include "mimeparser.tab.h"
+
+int yyparse (struct parser_state *pstate, void *yyscanner);
+void PARSER_initialize(struct parser_state *, void *);
+void PARSER_setbuffer(const char *);
+void PARSER_setfp(FILE *,void *yyscanner);
+
+/** @file mm_parse.c
+ *
+ * Functions to parse MIME messages
+ */
+
+/**
+ * Parses a NUL-terminated string into a MiniMIME context
+ *
+ * @param ctx A valid MiniMIME context object
+ * @param text The NUL-terminated string to parse
+ * @param parsemode The parsemode
+ * @param flags The flags to pass to the parser
+ * @returns 0 on success or -1 on failure
+ * @note Sets mm_errno if an error occurs
+ *
+ * This function parses a MIME message, stored in the memory region pointed to
+ * by text (must be NUL-terminated) according to the parseflags and stores the
+ * results in the MiniMIME context specified by ctx.
+ *
+ * The following modes can be used to specify how the message should be
+ * parsed:
+ *
+ * - MM_PARSE_STRICT: Do not tolerate MIME violations
+ * - MM_PARSE_LOOSE: Tolerate as much MIME violations as possible
+ *
+ * The context needs to be initialized before using mm_context_new() and may
+ * be freed using mm_context_free().
+ */
+int
+mm_parse_mem(MM_CTX *ctx, const char *text, int parsemode, int flags)
+{
+ void *yyscanner;
+ int res;
+ struct parser_state pstate;
+ typedef void *yyscan_t;
+ int mimeparser_yylex_init (yyscan_t* scanner);
+ int mimeparser_yylex_destroy (yyscan_t yyscanner );
+
+ pstate.ctx = ctx;
+ pstate.parsemode = parsemode;
+
+ mimeparser_yylex_init(&yyscanner);
+ PARSER_initialize(&pstate, yyscanner);
+
+ PARSER_setbuffer(text);
+ PARSER_setfp(NULL,yyscanner);
+
+ res = mimeparser_yyparse(&pstate,yyscanner);
+ mimeparser_yylex_destroy(yyscanner);
+ return res;
+}
+
+/**
+ * Parses a file into a MiniMIME context
+ *
+ * @param ctx A valid MiniMIME context object
+ * @param filename The name of the file to parse
+ * @param parsemode The parsemode
+ * @param flags The flags to pass to the parser
+ * @returns 0 on success or -1 on failure
+ * @note Sets mm_errno if an error occurs
+ *
+ * This function parses a MIME message, stored in the filesystem according to
+ * the parseflags and stores the results in the MiniMIME context specified by
+ * ctx.
+ *
+ * The following modes can be used to specify how the message should be
+ * parsed:
+ *
+ * - MM_PARSE_STRICT: Do not tolerate MIME violations
+ * - MM_PARSE_LOOSE: Tolerate as much MIME violations as possible
+ *
+ * The context needs to be initialized before using mm_context_new() and may
+ * be freed using mm_context_free().
+ */
+typedef void *yyscan_t;
+int
+mm_parse_file(MM_CTX *ctx, const char *filename, int parsemode, int flags)
+{
+ FILE *fp;
+ int res;
+ void *yyscanner;
+ struct parser_state pstate;
+ int mimeparser_yylex_init (yyscan_t* scanner);
+ int mimeparser_yylex_destroy (yyscan_t yyscanner );
+
+ mimeparser_yylex_init(&yyscanner);
+
+ if ((fp = fopen(filename, "r")) == NULL) {
+ mm_errno = MM_ERROR_ERRNO;
+ return -1;
+ }
+
+ PARSER_setfp(fp,yyscanner);
+ PARSER_initialize(&pstate, yyscanner);
+
+ pstate.ctx = ctx;
+ pstate.parsemode = parsemode;
+
+ res = mimeparser_yyparse(&pstate,yyscanner);
+ mimeparser_yylex_destroy(yyscanner);
+ fclose(fp);
+ return res;
+}
+
+int
+mm_parse_fileptr(MM_CTX *ctx, FILE *f, int parsemode, int flags)
+{
+ int res;
+ void *yyscanner;
+ struct parser_state pstate;
+ int mimeparser_yylex_init (yyscan_t* scanner);
+ int mimeparser_yylex_destroy (yyscan_t yyscanner );
+
+ mimeparser_yylex_init(&yyscanner);
+
+ PARSER_setfp(f, yyscanner);
+ PARSER_initialize(&pstate, yyscanner);
+
+ pstate.ctx = ctx;
+ pstate.parsemode = parsemode;
+
+ res = mimeparser_yyparse(&pstate,yyscanner);
+ mimeparser_yylex_destroy(yyscanner);
+
+ return res;
+}
diff --git a/main/minimime/mm_queue.h b/main/minimime/mm_queue.h
new file mode 100644
index 000000000..893e2fae2
--- /dev/null
+++ b/main/minimime/mm_queue.h
@@ -0,0 +1,508 @@
+/* $OpenBSD: queue.h,v 1.25 2004/04/08 16:08:21 henning Exp $ */
+/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+/*
+ * This file defines five types of data structures: singly-linked lists,
+ * lists, simple queues, tail queues, and circular queues.
+ *
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction. Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so elements can only be removed from the
+ * head of the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * Singly-linked List definitions.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List access methods.
+ */
+#define SLIST_FIRST(head) ((head)->slh_first)
+#define SLIST_END(head) NULL
+#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+#define SLIST_FOREACH(var, head, field) \
+ for((var) = SLIST_FIRST(head); \
+ (var) != SLIST_END(head); \
+ (var) = SLIST_NEXT(var, field))
+
+#define SLIST_FOREACH_PREVPTR(var, varp, head, field) \
+ for ((varp) = &SLIST_FIRST((head)); \
+ ((var) = *(varp)) != SLIST_END(head); \
+ (varp) = &SLIST_NEXT((var), field))
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_INIT(head) { \
+ SLIST_FIRST(head) = SLIST_END(head); \
+}
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ (elm)->field.sle_next = (slistelm)->field.sle_next; \
+ (slistelm)->field.sle_next = (elm); \
+} while (0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.sle_next = (head)->slh_first; \
+ (head)->slh_first = (elm); \
+} while (0)
+
+#define SLIST_REMOVE_NEXT(head, elm, field) do { \
+ (elm)->field.sle_next = (elm)->field.sle_next->field.sle_next; \
+} while (0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ (head)->slh_first = (head)->slh_first->field.sle_next; \
+} while (0)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ if ((head)->slh_first == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = (head)->slh_first; \
+ while( curelm->field.sle_next != (elm) ) \
+ curelm = curelm->field.sle_next; \
+ curelm->field.sle_next = \
+ curelm->field.sle_next->field.sle_next; \
+ } \
+} while (0)
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List access methods
+ */
+#define LIST_FIRST(head) ((head)->lh_first)
+#define LIST_END(head) NULL
+#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+#define LIST_FOREACH(var, head, field) \
+ for((var) = LIST_FIRST(head); \
+ (var)!= LIST_END(head); \
+ (var) = LIST_NEXT(var, field))
+
+/*
+ * List functions.
+ */
+#define LIST_INIT(head) do { \
+ LIST_FIRST(head) = LIST_END(head); \
+} while (0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
+ (listelm)->field.le_next->field.le_prev = \
+ &(elm)->field.le_next; \
+ (listelm)->field.le_next = (elm); \
+ (elm)->field.le_prev = &(listelm)->field.le_next; \
+} while (0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ (elm)->field.le_next = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &(elm)->field.le_next; \
+} while (0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.le_next = (head)->lh_first) != NULL) \
+ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+ (head)->lh_first = (elm); \
+ (elm)->field.le_prev = &(head)->lh_first; \
+} while (0)
+
+#define LIST_REMOVE(elm, field) do { \
+ if ((elm)->field.le_next != NULL) \
+ (elm)->field.le_next->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = (elm)->field.le_next; \
+} while (0)
+
+#define LIST_REPLACE(elm, elm2, field) do { \
+ if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
+ (elm2)->field.le_next->field.le_prev = \
+ &(elm2)->field.le_next; \
+ (elm2)->field.le_prev = (elm)->field.le_prev; \
+ *(elm2)->field.le_prev = (elm2); \
+} while (0)
+
+/*
+ * Simple queue definitions.
+ */
+#define SIMPLEQ_HEAD(name, type) \
+struct name { \
+ struct type *sqh_first; /* first element */ \
+ struct type **sqh_last; /* addr of last next element */ \
+}
+
+#define SIMPLEQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).sqh_first }
+
+#define SIMPLEQ_ENTRY(type) \
+struct { \
+ struct type *sqe_next; /* next element */ \
+}
+
+/*
+ * Simple queue access methods.
+ */
+#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
+#define SIMPLEQ_END(head) NULL
+#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
+#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
+
+#define SIMPLEQ_FOREACH(var, head, field) \
+ for((var) = SIMPLEQ_FIRST(head); \
+ (var) != SIMPLEQ_END(head); \
+ (var) = SIMPLEQ_NEXT(var, field))
+
+/*
+ * Simple queue functions.
+ */
+#define SIMPLEQ_INIT(head) do { \
+ (head)->sqh_first = NULL; \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (0)
+
+#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (head)->sqh_first = (elm); \
+} while (0)
+
+#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.sqe_next = NULL; \
+ *(head)->sqh_last = (elm); \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (0)
+
+#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (listelm)->field.sqe_next = (elm); \
+} while (0)
+
+#define SIMPLEQ_REMOVE_HEAD(head, elm, field) do { \
+ if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (0)
+
+/*
+ * Tail queue definitions.
+ */
+#define TAILQ_HEAD(name, type) \
+struct name { \
+ struct type *tqh_first; /* first element */ \
+ struct type **tqh_last; /* addr of last next element */ \
+}
+
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+
+#define TAILQ_ENTRY(type) \
+struct { \
+ struct type *tqe_next; /* next element */ \
+ struct type **tqe_prev; /* address of previous next element */ \
+}
+
+/*
+ * tail queue access methods
+ */
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+#define TAILQ_END(head) NULL
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+/* XXX */
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+#define TAILQ_EMPTY(head) \
+ (TAILQ_FIRST(head) == TAILQ_END(head))
+
+#define TAILQ_FOREACH(var, head, field) \
+ for((var) = TAILQ_FIRST(head); \
+ (var) != TAILQ_END(head); \
+ (var) = TAILQ_NEXT(var, field))
+
+#define TAILQ_FOREACH_REVERSE(var, head, headname, field) \
+ for((var) = TAILQ_LAST(head, headname); \
+ (var) != TAILQ_END(head); \
+ (var) = TAILQ_PREV(var, headname, field))
+
+/*
+ * Tail queue functions.
+ */
+#define TAILQ_INIT(head) do { \
+ (head)->tqh_first = NULL; \
+ (head)->tqh_last = &(head)->tqh_first; \
+} while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
+ (head)->tqh_first->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (head)->tqh_first = (elm); \
+ (elm)->field.tqe_prev = &(head)->tqh_first; \
+} while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.tqe_next = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+ (elm)->field.tqe_next->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (listelm)->field.tqe_next = (elm); \
+ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ (elm)->field.tqe_next = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ if (((elm)->field.tqe_next) != NULL) \
+ (elm)->field.tqe_next->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_REPLACE(head, elm, elm2, field) do { \
+ if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
+ (elm2)->field.tqe_next->field.tqe_prev = \
+ &(elm2)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm2)->field.tqe_next; \
+ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
+ *(elm2)->field.tqe_prev = (elm2); \
+} while (0)
+
+/*
+ * Circular queue definitions.
+ */
+#define CIRCLEQ_HEAD(name, type) \
+struct name { \
+ struct type *cqh_first; /* first element */ \
+ struct type *cqh_last; /* last element */ \
+}
+
+#define CIRCLEQ_HEAD_INITIALIZER(head) \
+ { CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
+
+#define CIRCLEQ_ENTRY(type) \
+struct { \
+ struct type *cqe_next; /* next element */ \
+ struct type *cqe_prev; /* previous element */ \
+}
+
+/*
+ * Circular queue access methods
+ */
+#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
+#define CIRCLEQ_LAST(head) ((head)->cqh_last)
+#define CIRCLEQ_END(head) ((void *)(head))
+#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
+#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
+#define CIRCLEQ_EMPTY(head) \
+ (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
+
+#define CIRCLEQ_FOREACH(var, head, field) \
+ for((var) = CIRCLEQ_FIRST(head); \
+ (var) != CIRCLEQ_END(head); \
+ (var) = CIRCLEQ_NEXT(var, field))
+
+#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
+ for((var) = CIRCLEQ_LAST(head); \
+ (var) != CIRCLEQ_END(head); \
+ (var) = CIRCLEQ_PREV(var, field))
+
+/*
+ * Circular queue functions.
+ */
+#define CIRCLEQ_INIT(head) do { \
+ (head)->cqh_first = CIRCLEQ_END(head); \
+ (head)->cqh_last = CIRCLEQ_END(head); \
+} while (0)
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ (elm)->field.cqe_next = (listelm)->field.cqe_next; \
+ (elm)->field.cqe_prev = (listelm); \
+ if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (listelm)->field.cqe_next->field.cqe_prev = (elm); \
+ (listelm)->field.cqe_next = (elm); \
+} while (0)
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
+ (elm)->field.cqe_next = (listelm); \
+ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
+ if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (listelm)->field.cqe_prev->field.cqe_next = (elm); \
+ (listelm)->field.cqe_prev = (elm); \
+} while (0)
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.cqe_next = (head)->cqh_first; \
+ (elm)->field.cqe_prev = CIRCLEQ_END(head); \
+ if ((head)->cqh_last == CIRCLEQ_END(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (head)->cqh_first->field.cqe_prev = (elm); \
+ (head)->cqh_first = (elm); \
+} while (0)
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.cqe_next = CIRCLEQ_END(head); \
+ (elm)->field.cqe_prev = (head)->cqh_last; \
+ if ((head)->cqh_first == CIRCLEQ_END(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (head)->cqh_last->field.cqe_next = (elm); \
+ (head)->cqh_last = (elm); \
+} while (0)
+
+#define CIRCLEQ_REMOVE(head, elm, field) do { \
+ if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \
+ (head)->cqh_last = (elm)->field.cqe_prev; \
+ else \
+ (elm)->field.cqe_next->field.cqe_prev = \
+ (elm)->field.cqe_prev; \
+ if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \
+ (head)->cqh_first = (elm)->field.cqe_next; \
+ else \
+ (elm)->field.cqe_prev->field.cqe_next = \
+ (elm)->field.cqe_next; \
+} while (0)
+
+#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
+ if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
+ CIRCLEQ_END(head)) \
+ (head).cqh_last = (elm2); \
+ else \
+ (elm2)->field.cqe_next->field.cqe_prev = (elm2); \
+ if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
+ CIRCLEQ_END(head)) \
+ (head).cqh_first = (elm2); \
+ else \
+ (elm2)->field.cqe_prev->field.cqe_next = (elm2); \
+} while (0)
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/main/minimime/mm_util.c b/main/minimime/mm_util.c
new file mode 100644
index 000000000..94150d40b
--- /dev/null
+++ b/main/minimime/mm_util.c
@@ -0,0 +1,412 @@
+/*
+ * $Id$
+ *
+ * MiniMIME - a library for handling MIME messages
+ *
+ * Copyright (C) 2003 Jann Fischer <rezine@mistrust.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <time.h>
+#include <assert.h>
+
+#include "mm_internal.h"
+
+/** @file mm_util.c
+ *
+ * This module contains utility functions for the MiniMIME library
+ */
+
+/** @defgroup util General purpose utility functions */
+
+#ifndef __HAVE_LEAK_DETECTION
+/**
+ * Allocates a block of memory
+ *
+ * @param size The size of the memory region to allocate
+ * @return A pointer to the allocated memory region
+ * @ingroup util
+ *
+ * xmalloc() calls abort() if either the size argument is negative or the
+ * requested memory amount could not be allocated via an assert() call.
+ */
+void *
+xmalloc(size_t size)
+{
+ void *p;
+
+ assert(size > 0);
+ p = malloc(size);
+ assert(p != NULL);
+
+ return p;
+}
+
+/**
+ * realloc() wrapper
+ *
+ * @param p Pointer to a memory region which should be reallocated
+ * @param size The new size of the memory region
+ * @return A pointer to the reallocated memory region
+ * @ingroup util
+ *
+ * xrealloc() is a wrapper around realloc() which calls abort() if either the
+ * size argument is negative or the requested memory amount could not be
+ * allocated.
+ */
+void *
+xrealloc(void *p, size_t size)
+{
+ void *n;
+
+ assert(size > 0);
+ n = realloc(p, size);
+ assert(n != NULL);
+
+ return n;
+}
+
+char *
+xstrdup(const char *str)
+{
+ char *p;
+
+ assert(str != NULL);
+ p = strdup(str);
+ assert(p != NULL);
+
+ return p;
+}
+
+void
+xfree(void *p)
+{
+ assert(p != NULL);
+ free(p);
+ p = NULL;
+ assert(p == NULL);
+}
+#endif /* ! __HAVE_LEAK_DETECTION */
+
+/**
+ * Unquotes a string
+ *
+ * @param string The quoted string to unquote
+ * @return A pointer to the unquoted string
+ * @ingroup util
+ *
+ * This function unquotes a string. That is, it returns a pointer to a newly
+ * allocated memory region in which the unquoted string is stored. Only
+ * leading and trailing double-qoutes are removed. The string needs to be
+ * freed when it is not needed anymore.
+ */
+char *
+mm_unquote(const char *string)
+{
+ char *ret;
+
+ if (string[0] != '\"' || string[strlen(string)-1] != '\"')
+ return xstrdup(string);
+
+ ret = xstrdup(string + 1);
+ ret[strlen(ret)-1] = '\0';
+
+ return ret;
+}
+
+
+/**
+ * Removes MIME comments from a string
+ *
+ * @param string The string to uncomment
+ * @return A pointer to the uncommented string or NULL on error. Sets mm_errno.
+ * @ingroup util
+ *
+ * This function removes MIME comments from a string (included in parantheses).
+ * It returns a pointer to a newly allocated memory region in which the
+ * uncommented string is stored. The returned string needs to be freed when
+ * it's not used anymore.
+ */
+char *
+mm_uncomment(const char *string)
+{
+ char *buf, *new, *orig, *token;
+ size_t new_size;
+ int found;
+ int open;
+
+ assert(string != NULL);
+
+ new_size = strlen(string) + 1;
+ new = NULL;
+ buf = NULL;
+ orig = NULL;
+ found = 0;
+ open = 0;
+ mm_errno = MM_ERROR_NONE;
+
+ buf = xstrdup(string);
+ orig = buf;
+
+ while (*buf != '\0') {
+ if (*buf == '(') {
+ open++;
+ new_size--;
+ found++;
+ } else if (*buf == ')') {
+ open--;
+ new_size--;
+ } else {
+ if (open)
+ new_size--;
+ }
+ buf++;
+ }
+
+ if (open != 0) {
+ mm_errno = MM_ERROR_PARSE;
+ mm_error_setmsg("Uncommenting: parantheses are unbalanced");
+ goto cleanup;
+ }
+
+ if (!found) {
+ new = orig;
+ return orig;
+ }
+
+ new = xmalloc(new_size + 1);
+ *new = '\0';
+ buf = orig;
+ token = buf;
+
+ /* Tokenize our string by parentheses, and copy the portions which are
+ * not commented to our destination.
+ */
+ open = 0;
+ while (*buf != '\0') {
+ if (*buf == '(') {
+ if (!open) {
+ *buf = '\0';
+ strlcat(new, token, new_size);
+ token = buf+1;
+ }
+ open++;
+ }
+ if (*buf == ')') {
+ open--;
+ token = buf + 1;
+ }
+ buf++;
+ }
+
+ strlcat(new, token, new_size);
+
+cleanup:
+ if (orig != NULL) {
+ xfree(orig);
+ orig = NULL;
+ }
+
+ if (mm_errno != MM_ERROR_NONE) {
+ if (new != NULL) {
+ xfree(new);
+ new = NULL;
+ }
+ return NULL;
+ } else {
+ return new;
+ }
+}
+
+/**
+ * separate strings
+ *
+ * @param stringp A pointer to the string being splitted
+ * @param delim The delimeter string
+ * @ingroup util
+ *
+ * This function works similar to strsep(), with the difference that delim is
+ * treated as a whole.
+ */
+char *
+xstrsep(char **stringp, const char *delim)
+{
+ char *p;
+ char *s;
+ char *r;
+
+ if (*stringp == NULL || *stringp == '\0')
+ return NULL;
+
+ p = *stringp;
+
+ if ((s = strstr(p, delim)) == NULL) {
+ r = p;
+ while (*p != '\0')
+ p++;
+ *stringp = NULL;
+ return r;
+ } else {
+ r = p;
+ p += strlen(p) - strlen(s);
+ *p = '\0';
+ *stringp = p + strlen(delim);
+ return r;
+ }
+}
+
+/**
+ * Strips a given character set from a string
+ *
+ * @param input The string which to strip
+ * @param strip The character set to strip off
+ * @return A copy of the original string with all chars stripped
+ * @ingroup util
+ */
+char *
+mm_stripchars(char *input, char *strip)
+{
+ char *output, *orig;
+ int i, j, chars;
+
+ assert(input != NULL);
+ assert(strip != '\0');
+
+ chars = 0;
+ orig = input;
+
+ while (*orig != '\0') {
+ for (i = 0; i < strlen(strip); i++) {
+ if (*orig == strip[i]) {
+ chars++;
+ break;
+ }
+ }
+ orig++;
+ }
+
+ /* If we have not found any char in the input, return a dup of the orig
+ string */
+ if (chars == 0)
+ return(xstrdup(input));
+
+ output = (char *)xmalloc(strlen(input) - chars);
+ orig = output;
+
+ for (i = 0; i < strlen(input); i++) {
+ int stripc;
+ stripc = 0;
+ for (j = 0; j < strlen(strip); j++) {
+ if (input[i] == strip[j]) {
+ stripc = 1;
+ break;
+ }
+ }
+ if (stripc == 0) {
+ *output = input[i];
+ output++;
+ }
+ }
+
+ *output = '\0';
+
+ return(orig);
+}
+
+/**
+ * Adds characters to a string at given positions
+ *
+ * @param input The string to which to add characters
+ * @param add The character string to add
+ * @param linelength The position where to add the character
+ * @return A copy of the string with characters added
+ * @ingroup util
+ *
+ * This function adds the characters add at each linelength positions and
+ * returns this new string.
+ */
+char *
+mm_addchars(char *input, char *add, u_int16_t linelength)
+{
+ u_int32_t len;
+ u_int32_t i;
+ u_int32_t l;
+ u_int32_t j;
+ u_int16_t addcrlf;
+ char *output;
+ char *orig;
+
+ len = strlen(input);
+ if (len <= linelength)
+ return(xstrdup(input));
+
+ addcrlf = len / linelength;
+
+ output = (char *)xmalloc(len + (addcrlf * strlen(add)));
+ orig = output;
+
+ for (i = 0, l = 0; i < len; i++, l++) {
+ if (l == linelength) {
+ for (j = 0; j < strlen(add); j++) {
+ *output = add[j];
+ output++;
+ }
+ l = 0;
+ }
+ *output = input[i];
+ output++;
+ }
+
+ *output = '\0';
+ output = orig;
+
+ return(orig);
+}
+
+void
+mm_striptrailing(char **what, const char *charset)
+{
+ size_t eos, i, hit;
+ char *str;
+
+ str = *what;
+ for (eos = strlen(str)-1; eos >= 0; eos--) {
+ hit = 0;
+ for (i = 0; i < strlen(charset); i++) {
+ if (str[eos] == charset[i]) {
+ str[eos] = '\0';
+ hit = 1;
+ break;
+ }
+ }
+ if (!hit)
+ break;
+ }
+}
diff --git a/main/minimime/mm_util.h b/main/minimime/mm_util.h
new file mode 100644
index 000000000..b7058657d
--- /dev/null
+++ b/main/minimime/mm_util.h
@@ -0,0 +1,50 @@
+/*
+ * $Id$
+ *
+ * MiniMIME - a library for handling MIME messages
+ *
+ * Copyright (C) 2003 Jann Fischer <rezine@mistrust.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#ifndef __MM_UTIL_H
+#define __MM_UTIL_H
+
+#define STRIP_TRAILING(str, charset) do { \
+ size_t eos, i, hit; \
+ for (eos = strlen(str); eos > 0; eos--) { \
+ hit = 0; \
+ for (i = 0; i <= strlen(charset); i++) { \
+ if (str[eos] == charset[i]) {\
+ str[eos] = '\0'; \
+ hit = 1; \
+ break; \
+ } \
+ } \
+ if (!hit) \
+ break; \
+ } \
+} while (0);
+
+#endif /* ! __MM_UTIL_H */
diff --git a/main/minimime/mm_warnings.c b/main/minimime/mm_warnings.c
new file mode 100644
index 000000000..c9b8a7daf
--- /dev/null
+++ b/main/minimime/mm_warnings.c
@@ -0,0 +1,99 @@
+/*
+ * $Id$
+ *
+ * MiniMIME - a library for handling MIME messages
+ *
+ * Copyright (C) 2003 Jann Fischer <rezine@mistrust.net>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the author nor the names of the contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY JANN FISCHER AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL JANN FISCHER OR THE VOICES IN HIS HEAD
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#include <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <ctype.h>
+#include <assert.h>
+
+#include "mm_internal.h"
+
+/**
+ * Attaches a warning message to a context
+ *
+ * @param ctx A valid MiniMIME context object
+ * @param type The type of the warning
+ * @param fmt The warning message as format string
+ */
+void
+mm_warning_add(MM_CTX *ctx, int type, const char *fmt, ...)
+{
+ struct mm_warning *warning;
+ char buf[1024];
+ va_list ap;
+
+ assert(ctx != NULL);
+
+ va_start(ap, fmt);
+ vsnprintf(buf, sizeof buf, fmt, ap);
+ va_end(ap);
+
+ warning = (struct mm_warning *)xmalloc(sizeof(struct mm_warning));
+ warning->message = xstrdup(buf);
+ warning->type = type;
+
+ if (SLIST_EMPTY(&ctx->warnings)) {
+ SLIST_INSERT_HEAD(&ctx->warnings, warning, next);
+ } else {
+ struct mm_warning *last, *after;
+
+ after = NULL;
+
+ SLIST_FOREACH(last, &ctx->warnings, next) {
+ if (last != NULL) {
+ after = last;
+ }
+ }
+
+ assert(after != NULL);
+
+ SLIST_INSERT_AFTER(after, warning, next);
+ }
+}
+
+struct mm_warning *
+mm_warning_next(MM_CTX *ctx, struct mm_warning **last)
+{
+ struct mm_warning *warning;
+
+ if (*last == NULL) {
+ warning = SLIST_FIRST(&ctx->warnings);
+ } else {
+ warning = SLIST_NEXT(*last, next);
+ }
+
+ *last = warning;
+ return warning;
+}
diff --git a/main/minimime/mytest_files/ast_postdata b/main/minimime/mytest_files/ast_postdata
new file mode 100644
index 000000000..c3776c6f4
--- /dev/null
+++ b/main/minimime/mytest_files/ast_postdata
@@ -0,0 +1,38 @@
+MyHeader1: blah1
+MyHeader2: blah2
+MyHeader3: blah3
+MyHeader4: blah4
+Content-Type: multipart/form-data; boundary=---------------------------175757342718946221771693683144
+
+-----------------------------175757342718946221771693683144
+Content-Disposition: form-data; name="MAX_FILE_SIZE"
+
+30000
+-----------------------------175757342718946221771693683144
+Content-Disposition: form-data; name="userfile"; filename="BUGS"
+Content-Type: application/octet-stream
+
+Asterisk Bug Tracking Information
+=================================
+
+To learn about and report Asterisk bugs, please visit
+the official Asterisk Bug Tracker at:
+
+ http://bugs.digium.com
+
+For more information on using the bug tracker, or to
+learn how you can contribute by acting as a bug marshall
+please see:
+
+ http://www.asterisk.org/developers/bug-guidelines
+
+If you would like to submit a feature request, please
+resist the temptation to post it to the bug tracker.
+Feature requests should be posted to the asterisk-dev
+mailing list, located at:
+
+ http://lists.digium.com
+
+Thank you!
+
+-----------------------------175757342718946221771693683144--
diff --git a/main/minimime/mytest_files/ast_postdata2 b/main/minimime/mytest_files/ast_postdata2
new file mode 100644
index 000000000..8f91e7a51
--- /dev/null
+++ b/main/minimime/mytest_files/ast_postdata2
Binary files differ
diff --git a/main/minimime/mytest_files/ast_postdata3.gz b/main/minimime/mytest_files/ast_postdata3.gz
new file mode 100644
index 000000000..d8d3894ad
--- /dev/null
+++ b/main/minimime/mytest_files/ast_postdata3.gz
Binary files differ
diff --git a/main/minimime/mytest_files/mytest.c b/main/minimime/mytest_files/mytest.c
new file mode 100644
index 000000000..ccbeddc85
--- /dev/null
+++ b/main/minimime/mytest_files/mytest.c
@@ -0,0 +1,71 @@
+#include <stdlib.h>
+#include <stdio.h>
+
+#include "mm.h"
+
+int main(int argc, char *argv[])
+{
+ const char *filename = "mytest_files/ast_postdata3";
+ MM_CTX *ctx;
+ struct mm_mimepart *part;
+ struct mm_content *cont;
+
+ int res = 0;
+ const char *disp;
+ int i;
+
+ mm_library_init();
+ mm_codec_registerdefaultcodecs();
+
+ printf("\nThe test should run 2 times with the same results.\n\n");
+
+ for (i = 0; i < 2; i++) {
+ printf("\nTest run #%d ...\n", i + 1);
+
+ if (!(ctx = mm_context_new())) {
+ printf("Failed to create MiniMIME context!\n\n");
+ break;
+ }
+
+ res = mm_parse_file(ctx, filename, MM_PARSE_LOOSE, 0);
+ if (res == -1) {
+ printf("Error parsing file %s\n\n", filename);
+ mm_context_free(ctx);
+ break;
+ }
+
+ res = mm_context_countparts(ctx);
+ if (res != 3) {
+ printf("This file should have 3 parts, but parser says %d\n\n", res);
+ res = -1;
+ mm_context_free(ctx);
+ break;
+ }
+
+ /* Part 2 is the file */
+ if (!(part = mm_context_getpart(ctx, 2))) {
+ printf("Failed to get a reference to part 2 of the MIME data\n\n");
+ res = -1;
+ mm_context_free(ctx);
+ break;
+ }
+
+ /* This is where the problems are demonstrated. */
+ cont = mm_mimepart_getcontent(part);
+
+ if ((disp = mm_content_getdispositiontype(cont)))
+ printf("SUCCESS: Got the Content-Disposition: %s\n", disp);
+ else
+ printf("FAILURE: Could not get the Content-Disposition value!\n");
+
+ res = mm_mimepart_getlength(part);
+ if (res == 1279)
+ printf("SUCCESS: Got the correct value for the body length: %d\n\n", res);
+ else
+ printf("FAILURE: The parser says this MIME part has %d length, but it should be 1279\n\n", res);
+
+ mm_context_free(ctx);
+ }
+
+ exit(res);
+}
diff --git a/main/minimime/strlcat.c b/main/minimime/strlcat.c
new file mode 100644
index 000000000..2d2da0413
--- /dev/null
+++ b/main/minimime/strlcat.c
@@ -0,0 +1,70 @@
+/* $OpenBSD: strlcat.c,v 1.9 2003/03/14 14:35:29 millert Exp $ */
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$OpenBSD: strlcat.c,v 1.9 2003/03/14 14:35:29 millert Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left). At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+size_t
+strlcat(char *dst, const char *src, size_t siz)
+{
+ register char *d = dst;
+ register const char *s = src;
+ register size_t n = siz;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (n-- != 0 && *d != '\0')
+ d++;
+ dlen = d - dst;
+ n = siz - dlen;
+
+ if (n == 0)
+ return(dlen + strlen(s));
+ while (*s != '\0') {
+ if (n != 1) {
+ *d++ = *s;
+ n--;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return(dlen + (s - src)); /* count does not include NUL */
+}
diff --git a/main/minimime/strlcpy.c b/main/minimime/strlcpy.c
new file mode 100644
index 000000000..94785a309
--- /dev/null
+++ b/main/minimime/strlcpy.c
@@ -0,0 +1,66 @@
+/* $OpenBSD: strlcpy.c,v 1.6 2003/03/14 14:35:29 millert Exp $ */
+
+/*
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#if defined(LIBC_SCCS) && !defined(lint)
+static char *rcsid = "$OpenBSD: strlcpy.c,v 1.6 2003/03/14 14:35:29 millert Exp $";
+#endif /* LIBC_SCCS and not lint */
+
+#include <sys/types.h>
+#include <string.h>
+
+/*
+ * Copy src to string dst of size siz. At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+size_t
+strlcpy(char *dst, const char *src, size_t siz)
+{
+ register char *d = dst;
+ register const char *s = src;
+ register size_t n = siz;
+
+ /* Copy as many bytes as will fit */
+ if (n != 0 && --n != 0) {
+ do {
+ if ((*d++ = *s++) == 0)
+ break;
+ } while (--n != 0);
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0) {
+ if (siz != 0)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++)
+ ;
+ }
+
+ return(s - src - 1); /* count does not include NUL */
+}
diff --git a/main/minimime/sys/CVS/Entries b/main/minimime/sys/CVS/Entries
new file mode 100644
index 000000000..138d3a245
--- /dev/null
+++ b/main/minimime/sys/CVS/Entries
@@ -0,0 +1,2 @@
+/mm_queue.h/1.1.1.1/Mon May 3 22:06:00 2004//
+D
diff --git a/main/minimime/sys/CVS/Repository b/main/minimime/sys/CVS/Repository
new file mode 100644
index 000000000..b81e7fdb9
--- /dev/null
+++ b/main/minimime/sys/CVS/Repository
@@ -0,0 +1 @@
+minimime/src/sys
diff --git a/main/minimime/sys/CVS/Root b/main/minimime/sys/CVS/Root
new file mode 100644
index 000000000..4c379009c
--- /dev/null
+++ b/main/minimime/sys/CVS/Root
@@ -0,0 +1 @@
+:pserver:anonymous@cvs.minimime.berlios.de:/cvsroot/minimime
diff --git a/main/minimime/sys/mm_queue.h b/main/minimime/sys/mm_queue.h
new file mode 100644
index 000000000..c85bb240c
--- /dev/null
+++ b/main/minimime/sys/mm_queue.h
@@ -0,0 +1,503 @@
+/* $OpenBSD: queue.h,v 1.22 2001/06/23 04:39:35 angelos Exp $ */
+/* $NetBSD: queue.h,v 1.11 1996/05/16 05:17:14 mycroft Exp $ */
+
+/*
+ * Copyright (c) 1991, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors.
+ * 4. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ *
+ * @(#)queue.h 8.5 (Berkeley) 8/20/94
+ */
+
+#ifndef _SYS_QUEUE_H_
+#define _SYS_QUEUE_H_
+
+/*
+ * This file defines five types of data structures: singly-linked lists,
+ * lists, simple queues, tail queues, and circular queues.
+ *
+ *
+ * A singly-linked list is headed by a single forward pointer. The elements
+ * are singly linked for minimum space and pointer manipulation overhead at
+ * the expense of O(n) removal for arbitrary elements. New elements can be
+ * added to the list after an existing element or at the head of the list.
+ * Elements being removed from the head of the list should use the explicit
+ * macro for this purpose for optimum efficiency. A singly-linked list may
+ * only be traversed in the forward direction. Singly-linked lists are ideal
+ * for applications with large datasets and few or no removals or for
+ * implementing a LIFO queue.
+ *
+ * A list is headed by a single forward pointer (or an array of forward
+ * pointers for a hash table header). The elements are doubly linked
+ * so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before
+ * or after an existing element or at the head of the list. A list
+ * may only be traversed in the forward direction.
+ *
+ * A simple queue is headed by a pair of pointers, one the head of the
+ * list and the other to the tail of the list. The elements are singly
+ * linked to save space, so elements can only be removed from the
+ * head of the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the
+ * list. A simple queue may only be traversed in the forward direction.
+ *
+ * A tail queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or
+ * after an existing element, at the head of the list, or at the end of
+ * the list. A tail queue may be traversed in either direction.
+ *
+ * A circle queue is headed by a pair of pointers, one to the head of the
+ * list and the other to the tail of the list. The elements are doubly
+ * linked so that an arbitrary element can be removed without a need to
+ * traverse the list. New elements can be added to the list before or after
+ * an existing element, at the head of the list, or at the end of the list.
+ * A circle queue may be traversed in either direction, but has a more
+ * complex end of list detection.
+ *
+ * For details on the use of these macros, see the queue(3) manual page.
+ */
+
+/*
+ * Singly-linked List definitions.
+ */
+#define SLIST_HEAD(name, type) \
+struct name { \
+ struct type *slh_first; /* first element */ \
+}
+
+#define SLIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define SLIST_ENTRY(type) \
+struct { \
+ struct type *sle_next; /* next element */ \
+}
+
+/*
+ * Singly-linked List access methods.
+ */
+#define SLIST_FIRST(head) ((head)->slh_first)
+#define SLIST_END(head) NULL
+#define SLIST_EMPTY(head) (SLIST_FIRST(head) == SLIST_END(head))
+#define SLIST_NEXT(elm, field) ((elm)->field.sle_next)
+
+#define SLIST_FOREACH(var, head, field) \
+ for((var) = SLIST_FIRST(head); \
+ (var) != SLIST_END(head); \
+ (var) = SLIST_NEXT(var, field))
+
+/*
+ * Singly-linked List functions.
+ */
+#define SLIST_INIT(head) { \
+ SLIST_FIRST(head) = SLIST_END(head); \
+}
+
+#define SLIST_INSERT_AFTER(slistelm, elm, field) do { \
+ (elm)->field.sle_next = (slistelm)->field.sle_next; \
+ (slistelm)->field.sle_next = (elm); \
+} while (0)
+
+#define SLIST_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.sle_next = (head)->slh_first; \
+ (head)->slh_first = (elm); \
+} while (0)
+
+#define SLIST_REMOVE_HEAD(head, field) do { \
+ (head)->slh_first = (head)->slh_first->field.sle_next; \
+} while (0)
+
+#define SLIST_REMOVE(head, elm, type, field) do { \
+ if ((head)->slh_first == (elm)) { \
+ SLIST_REMOVE_HEAD((head), field); \
+ } \
+ else { \
+ struct type *curelm = (head)->slh_first; \
+ while( curelm->field.sle_next != (elm) ) \
+ curelm = curelm->field.sle_next; \
+ curelm->field.sle_next = \
+ curelm->field.sle_next->field.sle_next; \
+ } \
+} while (0)
+
+/*
+ * List definitions.
+ */
+#define LIST_HEAD(name, type) \
+struct name { \
+ struct type *lh_first; /* first element */ \
+}
+
+#define LIST_HEAD_INITIALIZER(head) \
+ { NULL }
+
+#define LIST_ENTRY(type) \
+struct { \
+ struct type *le_next; /* next element */ \
+ struct type **le_prev; /* address of previous next element */ \
+}
+
+/*
+ * List access methods
+ */
+#define LIST_FIRST(head) ((head)->lh_first)
+#define LIST_END(head) NULL
+#define LIST_EMPTY(head) (LIST_FIRST(head) == LIST_END(head))
+#define LIST_NEXT(elm, field) ((elm)->field.le_next)
+
+#define LIST_FOREACH(var, head, field) \
+ for((var) = LIST_FIRST(head); \
+ (var)!= LIST_END(head); \
+ (var) = LIST_NEXT(var, field))
+
+/*
+ * List functions.
+ */
+#define LIST_INIT(head) do { \
+ LIST_FIRST(head) = LIST_END(head); \
+} while (0)
+
+#define LIST_INSERT_AFTER(listelm, elm, field) do { \
+ if (((elm)->field.le_next = (listelm)->field.le_next) != NULL) \
+ (listelm)->field.le_next->field.le_prev = \
+ &(elm)->field.le_next; \
+ (listelm)->field.le_next = (elm); \
+ (elm)->field.le_prev = &(listelm)->field.le_next; \
+} while (0)
+
+#define LIST_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.le_prev = (listelm)->field.le_prev; \
+ (elm)->field.le_next = (listelm); \
+ *(listelm)->field.le_prev = (elm); \
+ (listelm)->field.le_prev = &(elm)->field.le_next; \
+} while (0)
+
+#define LIST_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.le_next = (head)->lh_first) != NULL) \
+ (head)->lh_first->field.le_prev = &(elm)->field.le_next;\
+ (head)->lh_first = (elm); \
+ (elm)->field.le_prev = &(head)->lh_first; \
+} while (0)
+
+#define LIST_REMOVE(elm, field) do { \
+ if ((elm)->field.le_next != NULL) \
+ (elm)->field.le_next->field.le_prev = \
+ (elm)->field.le_prev; \
+ *(elm)->field.le_prev = (elm)->field.le_next; \
+} while (0)
+
+#define LIST_REPLACE(elm, elm2, field) do { \
+ if (((elm2)->field.le_next = (elm)->field.le_next) != NULL) \
+ (elm2)->field.le_next->field.le_prev = \
+ &(elm2)->field.le_next; \
+ (elm2)->field.le_prev = (elm)->field.le_prev; \
+ *(elm2)->field.le_prev = (elm2); \
+} while (0)
+
+/*
+ * Simple queue definitions.
+ */
+#define SIMPLEQ_HEAD(name, type) \
+struct name { \
+ struct type *sqh_first; /* first element */ \
+ struct type **sqh_last; /* addr of last next element */ \
+}
+
+#define SIMPLEQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).sqh_first }
+
+#define SIMPLEQ_ENTRY(type) \
+struct { \
+ struct type *sqe_next; /* next element */ \
+}
+
+/*
+ * Simple queue access methods.
+ */
+#define SIMPLEQ_FIRST(head) ((head)->sqh_first)
+#define SIMPLEQ_END(head) NULL
+#define SIMPLEQ_EMPTY(head) (SIMPLEQ_FIRST(head) == SIMPLEQ_END(head))
+#define SIMPLEQ_NEXT(elm, field) ((elm)->field.sqe_next)
+
+#define SIMPLEQ_FOREACH(var, head, field) \
+ for((var) = SIMPLEQ_FIRST(head); \
+ (var) != SIMPLEQ_END(head); \
+ (var) = SIMPLEQ_NEXT(var, field))
+
+/*
+ * Simple queue functions.
+ */
+#define SIMPLEQ_INIT(head) do { \
+ (head)->sqh_first = NULL; \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (0)
+
+#define SIMPLEQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.sqe_next = (head)->sqh_first) == NULL) \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (head)->sqh_first = (elm); \
+} while (0)
+
+#define SIMPLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.sqe_next = NULL; \
+ *(head)->sqh_last = (elm); \
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+} while (0)
+
+#define SIMPLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.sqe_next = (listelm)->field.sqe_next) == NULL)\
+ (head)->sqh_last = &(elm)->field.sqe_next; \
+ (listelm)->field.sqe_next = (elm); \
+} while (0)
+
+#define SIMPLEQ_REMOVE_HEAD(head, elm, field) do { \
+ if (((head)->sqh_first = (elm)->field.sqe_next) == NULL) \
+ (head)->sqh_last = &(head)->sqh_first; \
+} while (0)
+
+/*
+ * Tail queue definitions.
+ */
+#define TAILQ_HEAD(name, type) \
+struct name { \
+ struct type *tqh_first; /* first element */ \
+ struct type **tqh_last; /* addr of last next element */ \
+}
+
+#define TAILQ_HEAD_INITIALIZER(head) \
+ { NULL, &(head).tqh_first }
+
+#define TAILQ_ENTRY(type) \
+struct { \
+ struct type *tqe_next; /* next element */ \
+ struct type **tqe_prev; /* address of previous next element */ \
+}
+
+/*
+ * tail queue access methods
+ */
+#define TAILQ_FIRST(head) ((head)->tqh_first)
+#define TAILQ_END(head) NULL
+#define TAILQ_NEXT(elm, field) ((elm)->field.tqe_next)
+#define TAILQ_LAST(head, headname) \
+ (*(((struct headname *)((head)->tqh_last))->tqh_last))
+/* XXX */
+#define TAILQ_PREV(elm, headname, field) \
+ (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
+#define TAILQ_EMPTY(head) \
+ (TAILQ_FIRST(head) == TAILQ_END(head))
+
+#define TAILQ_FOREACH(var, head, field) \
+ for((var) = TAILQ_FIRST(head); \
+ (var) != TAILQ_END(head); \
+ (var) = TAILQ_NEXT(var, field))
+
+#define TAILQ_FOREACH_REVERSE(var, head, field, headname) \
+ for((var) = TAILQ_LAST(head, headname); \
+ (var) != TAILQ_END(head); \
+ (var) = TAILQ_PREV(var, headname, field))
+
+/*
+ * Tail queue functions.
+ */
+#define TAILQ_INIT(head) do { \
+ (head)->tqh_first = NULL; \
+ (head)->tqh_last = &(head)->tqh_first; \
+} while (0)
+
+#define TAILQ_INSERT_HEAD(head, elm, field) do { \
+ if (((elm)->field.tqe_next = (head)->tqh_first) != NULL) \
+ (head)->tqh_first->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (head)->tqh_first = (elm); \
+ (elm)->field.tqe_prev = &(head)->tqh_first; \
+} while (0)
+
+#define TAILQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.tqe_next = NULL; \
+ (elm)->field.tqe_prev = (head)->tqh_last; \
+ *(head)->tqh_last = (elm); \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)\
+ (elm)->field.tqe_next->field.tqe_prev = \
+ &(elm)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm)->field.tqe_next; \
+ (listelm)->field.tqe_next = (elm); \
+ (elm)->field.tqe_prev = &(listelm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_INSERT_BEFORE(listelm, elm, field) do { \
+ (elm)->field.tqe_prev = (listelm)->field.tqe_prev; \
+ (elm)->field.tqe_next = (listelm); \
+ *(listelm)->field.tqe_prev = (elm); \
+ (listelm)->field.tqe_prev = &(elm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_REMOVE(head, elm, field) do { \
+ if (((elm)->field.tqe_next) != NULL) \
+ (elm)->field.tqe_next->field.tqe_prev = \
+ (elm)->field.tqe_prev; \
+ else \
+ (head)->tqh_last = (elm)->field.tqe_prev; \
+ *(elm)->field.tqe_prev = (elm)->field.tqe_next; \
+} while (0)
+
+#define TAILQ_REPLACE(head, elm, elm2, field) do { \
+ if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL) \
+ (elm2)->field.tqe_next->field.tqe_prev = \
+ &(elm2)->field.tqe_next; \
+ else \
+ (head)->tqh_last = &(elm2)->field.tqe_next; \
+ (elm2)->field.tqe_prev = (elm)->field.tqe_prev; \
+ *(elm2)->field.tqe_prev = (elm2); \
+} while (0)
+
+/*
+ * Circular queue definitions.
+ */
+#define CIRCLEQ_HEAD(name, type) \
+struct name { \
+ struct type *cqh_first; /* first element */ \
+ struct type *cqh_last; /* last element */ \
+}
+
+#define CIRCLEQ_HEAD_INITIALIZER(head) \
+ { CIRCLEQ_END(&head), CIRCLEQ_END(&head) }
+
+#define CIRCLEQ_ENTRY(type) \
+struct { \
+ struct type *cqe_next; /* next element */ \
+ struct type *cqe_prev; /* previous element */ \
+}
+
+/*
+ * Circular queue access methods
+ */
+#define CIRCLEQ_FIRST(head) ((head)->cqh_first)
+#define CIRCLEQ_LAST(head) ((head)->cqh_last)
+#define CIRCLEQ_END(head) ((void *)(head))
+#define CIRCLEQ_NEXT(elm, field) ((elm)->field.cqe_next)
+#define CIRCLEQ_PREV(elm, field) ((elm)->field.cqe_prev)
+#define CIRCLEQ_EMPTY(head) \
+ (CIRCLEQ_FIRST(head) == CIRCLEQ_END(head))
+
+#define CIRCLEQ_FOREACH(var, head, field) \
+ for((var) = CIRCLEQ_FIRST(head); \
+ (var) != CIRCLEQ_END(head); \
+ (var) = CIRCLEQ_NEXT(var, field))
+
+#define CIRCLEQ_FOREACH_REVERSE(var, head, field) \
+ for((var) = CIRCLEQ_LAST(head); \
+ (var) != CIRCLEQ_END(head); \
+ (var) = CIRCLEQ_PREV(var, field))
+
+/*
+ * Circular queue functions.
+ */
+#define CIRCLEQ_INIT(head) do { \
+ (head)->cqh_first = CIRCLEQ_END(head); \
+ (head)->cqh_last = CIRCLEQ_END(head); \
+} while (0)
+
+#define CIRCLEQ_INSERT_AFTER(head, listelm, elm, field) do { \
+ (elm)->field.cqe_next = (listelm)->field.cqe_next; \
+ (elm)->field.cqe_prev = (listelm); \
+ if ((listelm)->field.cqe_next == CIRCLEQ_END(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (listelm)->field.cqe_next->field.cqe_prev = (elm); \
+ (listelm)->field.cqe_next = (elm); \
+} while (0)
+
+#define CIRCLEQ_INSERT_BEFORE(head, listelm, elm, field) do { \
+ (elm)->field.cqe_next = (listelm); \
+ (elm)->field.cqe_prev = (listelm)->field.cqe_prev; \
+ if ((listelm)->field.cqe_prev == CIRCLEQ_END(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (listelm)->field.cqe_prev->field.cqe_next = (elm); \
+ (listelm)->field.cqe_prev = (elm); \
+} while (0)
+
+#define CIRCLEQ_INSERT_HEAD(head, elm, field) do { \
+ (elm)->field.cqe_next = (head)->cqh_first; \
+ (elm)->field.cqe_prev = CIRCLEQ_END(head); \
+ if ((head)->cqh_last == CIRCLEQ_END(head)) \
+ (head)->cqh_last = (elm); \
+ else \
+ (head)->cqh_first->field.cqe_prev = (elm); \
+ (head)->cqh_first = (elm); \
+} while (0)
+
+#define CIRCLEQ_INSERT_TAIL(head, elm, field) do { \
+ (elm)->field.cqe_next = CIRCLEQ_END(head); \
+ (elm)->field.cqe_prev = (head)->cqh_last; \
+ if ((head)->cqh_first == CIRCLEQ_END(head)) \
+ (head)->cqh_first = (elm); \
+ else \
+ (head)->cqh_last->field.cqe_next = (elm); \
+ (head)->cqh_last = (elm); \
+} while (0)
+
+#define CIRCLEQ_REMOVE(head, elm, field) do { \
+ if ((elm)->field.cqe_next == CIRCLEQ_END(head)) \
+ (head)->cqh_last = (elm)->field.cqe_prev; \
+ else \
+ (elm)->field.cqe_next->field.cqe_prev = \
+ (elm)->field.cqe_prev; \
+ if ((elm)->field.cqe_prev == CIRCLEQ_END(head)) \
+ (head)->cqh_first = (elm)->field.cqe_next; \
+ else \
+ (elm)->field.cqe_prev->field.cqe_next = \
+ (elm)->field.cqe_next; \
+} while (0)
+
+#define CIRCLEQ_REPLACE(head, elm, elm2, field) do { \
+ if (((elm2)->field.cqe_next = (elm)->field.cqe_next) == \
+ CIRCLEQ_END(head)) \
+ (head).cqh_last = (elm2); \
+ else \
+ (elm2)->field.cqe_next->field.cqe_prev = (elm2); \
+ if (((elm2)->field.cqe_prev = (elm)->field.cqe_prev) == \
+ CIRCLEQ_END(head)) \
+ (head).cqh_first = (elm2); \
+ else \
+ (elm2)->field.cqe_prev->field.cqe_next = (elm2); \
+} while (0)
+
+#endif /* !_SYS_QUEUE_H_ */
diff --git a/main/minimime/test.sh b/main/minimime/test.sh
new file mode 100755
index 000000000..1beca0b74
--- /dev/null
+++ b/main/minimime/test.sh
@@ -0,0 +1,54 @@
+#!/bin/sh
+# MiniMIME test cases
+
+[ ! -x ./tests/parse -o ! -x ./tests/create ] && {
+ echo "You need to compile the test suite first to accomplish tests"
+ exit 1
+}
+
+LD_LIBRARY_PATH=${PWD}
+export LD_LIBRARY_PATH
+
+DIRECTORY=${1:-tests/messages}
+FILES=${2:-"*"}
+
+TESTS=0
+F_ERRORS=0
+F_INVALID=""
+M_ERRORS=0
+M_INVALID=""
+for f in ${DIRECTORY}/${FILES}; do
+ if [ -f "${f}" ]; then
+ TESTS=$((TESTS + 2))
+ echo -n "Running PARSER test for $f (file)... "
+ output=`./tests/parse $f 2>&1`
+ [ $? != 0 ] && {
+ echo "FAILED ($output)"
+ F_ERRORS=$((F_ERRORS + 1))
+ F_INVALID="${F_INVALID} ${f} "
+ } || {
+ echo "PASSED"
+ }
+ echo -n "Running PARSER test for $f (memory)... "
+ output=`./tests/parse -m $f 2>&1`
+ [ $? != 0 ] && {
+ echo "FAILED ($output)"
+ M_ERRORS=$((M_ERRORS + 1))
+ M_INVALID="${M_INVALID} ${f} "
+ } || {
+ echo "PASSED"
+ }
+ fi
+done
+
+echo "Ran a total of ${TESTS} tests"
+
+if [ ${F_ERRORS} -gt 0 ]; then
+ echo "!! ${F_ERRORS} messages had errors in file based parsing"
+ echo "-> ${F_INVALID}"
+fi
+if [ ${M_ERRORS} -gt 0 ]; then
+ echo "!! ${F_ERRORS} messages had errors in memory based parsing"
+fi
+
+unset LD_LIBRARY_PATH
diff --git a/main/minimime/test/CVS/Entries b/main/minimime/test/CVS/Entries
new file mode 100644
index 000000000..178481050
--- /dev/null
+++ b/main/minimime/test/CVS/Entries
@@ -0,0 +1 @@
+D
diff --git a/main/minimime/test/CVS/Repository b/main/minimime/test/CVS/Repository
new file mode 100644
index 000000000..c4c9417cc
--- /dev/null
+++ b/main/minimime/test/CVS/Repository
@@ -0,0 +1 @@
+minimime/src/test
diff --git a/main/minimime/test/CVS/Root b/main/minimime/test/CVS/Root
new file mode 100644
index 000000000..4c379009c
--- /dev/null
+++ b/main/minimime/test/CVS/Root
@@ -0,0 +1 @@
+:pserver:anonymous@cvs.minimime.berlios.de:/cvsroot/minimime
diff --git a/main/minimime/tests/CVS/Entries b/main/minimime/tests/CVS/Entries
new file mode 100644
index 000000000..667ffb1c1
--- /dev/null
+++ b/main/minimime/tests/CVS/Entries
@@ -0,0 +1,4 @@
+/Makefile/1.1/Wed Jun 9 09:44:47 2004//
+/create.c/1.1/Wed Jun 9 09:44:47 2004//
+/parse.c/1.2/Thu Jun 24 07:25:34 2004//
+D
diff --git a/main/minimime/tests/CVS/Entries.Log b/main/minimime/tests/CVS/Entries.Log
new file mode 100644
index 000000000..9e493f721
--- /dev/null
+++ b/main/minimime/tests/CVS/Entries.Log
@@ -0,0 +1 @@
+A D/messages////
diff --git a/main/minimime/tests/CVS/Repository b/main/minimime/tests/CVS/Repository
new file mode 100644
index 000000000..7a7de8746
--- /dev/null
+++ b/main/minimime/tests/CVS/Repository
@@ -0,0 +1 @@
+minimime/src/tests
diff --git a/main/minimime/tests/CVS/Root b/main/minimime/tests/CVS/Root
new file mode 100644
index 000000000..4c379009c
--- /dev/null
+++ b/main/minimime/tests/CVS/Root
@@ -0,0 +1 @@
+:pserver:anonymous@cvs.minimime.berlios.de:/cvsroot/minimime
diff --git a/main/minimime/tests/Makefile b/main/minimime/tests/Makefile
new file mode 100644
index 000000000..ae460c6b2
--- /dev/null
+++ b/main/minimime/tests/Makefile
@@ -0,0 +1,18 @@
+BINARIES=parse create
+CFLAGS=-Wall -ggdb -g3 -I..
+LDFLAGS=-L..
+LIBS=-lmmime
+CC=gcc
+
+all: parse create
+
+parse: parse.o
+ $(CC) -o parse parse.o $(LDFLAGS) $(LIBS)
+
+create: create.o
+ $(CC) -o create create.o $(LDFLAGS) $(LIBS)
+
+clean:
+ rm -f $(BINARIES)
+ rm -f *.o
+ rm -f *.core
diff --git a/main/minimime/tests/create.c b/main/minimime/tests/create.c
new file mode 100644
index 000000000..a8ca479f1
--- /dev/null
+++ b/main/minimime/tests/create.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2004 Jann Fischer. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * MiniMIME test program - create.c
+ *
+ * Creates a MIME message of the given MIME parts
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <err.h>
+
+#include "mm.h"
+
+const char *progname;
+
+void
+usage(void)
+{
+ fprintf(stderr,
+ "MiniMIME test suite\n"
+ "USAGE: %s <part> [<part_2>[<part_N>[...]]]\n",
+ progname
+ );
+}
+
+void
+print_error(void)
+{
+ fprintf(stderr, "ERROR: %s\n", mm_error_string());
+}
+
+int
+main(int argc, char **argv)
+{
+ MM_CTX *ctx;
+ struct mm_mimepart *part;
+ char *data;
+ size_t length;
+ int i;
+
+ progname = argv[0];
+
+ if (argc < 2) {
+ usage();
+ exit(1);
+ }
+
+ mm_library_init();
+
+ ctx = mm_context_new();
+
+ part = mm_mimepart_new();
+ mm_context_attachpart(ctx, part);
+ mm_envelope_setheader(ctx, "From", "foo@bar.com");
+
+ for (i=1; i < argc; i++) {
+ part = mm_mimepart_fromfile(argv[i]);
+ if (part == NULL) {
+ print_error();
+ exit(1);
+ }
+ mm_context_attachpart(ctx, part);
+ }
+
+ if (mm_context_flatten(ctx, &data, &length, 0) == -1) {
+ print_error();
+ exit(1);
+ }
+
+ printf("%s", data);
+
+ exit(0);
+}
diff --git a/main/minimime/tests/messages/CVS/Entries b/main/minimime/tests/messages/CVS/Entries
new file mode 100644
index 000000000..481ac7fda
--- /dev/null
+++ b/main/minimime/tests/messages/CVS/Entries
@@ -0,0 +1,8 @@
+/test1.txt/1.1/Wed Jun 9 09:44:47 2004//
+/test2.txt/1.1/Wed Jun 9 09:44:47 2004//
+/test3.txt/1.1/Wed Jun 9 09:44:47 2004//
+/test4.txt/1.1/Wed Jun 9 09:44:47 2004//
+/test5.txt/1.1/Wed Jun 9 09:44:47 2004//
+/test6.txt/1.1/Wed Jun 9 09:44:47 2004//
+/test7.txt/1.1/Wed Jun 9 09:44:47 2004//
+D
diff --git a/main/minimime/tests/messages/CVS/Repository b/main/minimime/tests/messages/CVS/Repository
new file mode 100644
index 000000000..b91caac65
--- /dev/null
+++ b/main/minimime/tests/messages/CVS/Repository
@@ -0,0 +1 @@
+minimime/src/tests/messages
diff --git a/main/minimime/tests/messages/CVS/Root b/main/minimime/tests/messages/CVS/Root
new file mode 100644
index 000000000..4c379009c
--- /dev/null
+++ b/main/minimime/tests/messages/CVS/Root
@@ -0,0 +1 @@
+:pserver:anonymous@cvs.minimime.berlios.de:/cvsroot/minimime
diff --git a/main/minimime/tests/messages/test1.txt b/main/minimime/tests/messages/test1.txt
new file mode 100644
index 000000000..2c24b1972
--- /dev/null
+++ b/main/minimime/tests/messages/test1.txt
@@ -0,0 +1,50 @@
+Return-Path: <rezine@hannover.ccc.de>
+X-Original-To: test@mistrust.net
+Delivered-To: rezine@hannover.ccc.de
+Received: from thinktank.niedersachsen.de (thinktank.niedersachsen.de [195.37.192.218])
+ (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
+ (Client did not present a certificate)
+ by gost.hannover.ccc.de (Postfix) with ESMTP id 90EDEBBF2
+ for <test@mistrust.net>; Sun, 24 Aug 2003 16:05:29 +0200 (CEST)
+Date: Sun, 24 Aug 2003 15:49:15 +0200
+From: Jann Fischer <rezine@hannover.ccc.de>
+To: test@mistrust.net
+Subject: Test
+Message-Id: <20030824154915.12cb3f85.rezine@hannover.ccc.de>
+Organization: Chaos Computer Club Hannover
+X-Mailer: Who-Cares 5.23
+Mime-Version: 1.0
+Content-Type: multipart/encrypted; protocol="application/pgp-encrypted";
+ boundary="=.2S1ZDSX8ir3lbt"
+
+--=.2S1ZDSX8ir3lbt
+Content-Type: application/pgp-encrypted
+
+Version: 1
+
+--=.2S1ZDSX8ir3lbt
+Content-Type: application/octet-stream
+
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v1.2.2 (OpenBSD)
+
+hQEOA3TvLJ6KBZLBEAP/cl4DiRH5+8S7/kP2BIVdDavHJ9cwHh8awGoyddhMKPJ3
+2558r8MKT0Etjpo649O5WUvT5Z2Jcp12+dTPlAC1kvoIjNNk8+Oe3JCREz/pXYnm
+5ANSCThVYSS34jppgT3NsqiV8sQK3e+Nq/NY7SoKVAV37L0fU4HHozcDZfXqOLsE
+AJgfxjRjjEazPHmgTTu8Pnt5gmlxyP35Yy0pl+gJmboG3Cn5WBcD/rrQf8oiwrB6
+Vak2Hk9TNU7hDO2IRolz4wUfkId47SK31PdhDLBnNPWn6LNWHd+G4hI97e+xeqLW
+dpG7Li5CdP0gfuHx2ux9Y5buWVVtqPhdDUlRaIBfM7Fu0sENAeREANAtdPHn0yTf
+V4T5NvImY3gXgLST5wNm3Ft+4nIDZrcnSy04x4faTLFBOcY95W0O1omILHyN5Ste
+Le5NhXhQRKyl6ebXtIvEOsJOK4NT6JaUF20l4yvgf0AnetG9Pbzc37mRqmE6Fb8O
+h/De3iqw7dexaQc+LaD3XTmvPyyDK2aI4cXOdc9WOzrWR7+9iEiY32SFsQWMRMZJ
+GdKkGk22K2p7MPFaU3MHQ3Af+WCN4mRW8SurFxH1379Y5e1IPfTeL6OBkj8hHilX
+Y+Y7523ADiStJsONIZPBXJVhZ/VAJ+jL+T1/Xht10VsJcWAY8A9tP+jNgyg8dh+J
+JgWVchQOZipdftYwR7w5GkhL2Nc5NYBJBg4DFd9g2nnwuzaAKYO5kMTzEmm9KOYq
+0DC5ukok4SGDwWPUIogNHmaSnFr723hYuJC7DwSxHXVG3VxxF78u1gzEnImOWRsf
+1RzGb7b8Lf7Rj98H5cNiZ55BXAmidjm7WghCLsT2GvxviqQoRIJ2h/WHM0Bl2v3F
+Dpa3N01p2NIIgQLRoXXyBCZTwGOH4y9nBj5PU7vzzSrMweHHt1BwHXcqItCyWFXX
+2tj4//Dyw3Lw/L5xGxYRP1Q=
+=fSLd
+-----END PGP MESSAGE-----
+
+--=.2S1ZDSX8ir3lbt--
diff --git a/main/minimime/tests/messages/test2.txt b/main/minimime/tests/messages/test2.txt
new file mode 100644
index 000000000..2c24b1972
--- /dev/null
+++ b/main/minimime/tests/messages/test2.txt
@@ -0,0 +1,50 @@
+Return-Path: <rezine@hannover.ccc.de>
+X-Original-To: test@mistrust.net
+Delivered-To: rezine@hannover.ccc.de
+Received: from thinktank.niedersachsen.de (thinktank.niedersachsen.de [195.37.192.218])
+ (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
+ (Client did not present a certificate)
+ by gost.hannover.ccc.de (Postfix) with ESMTP id 90EDEBBF2
+ for <test@mistrust.net>; Sun, 24 Aug 2003 16:05:29 +0200 (CEST)
+Date: Sun, 24 Aug 2003 15:49:15 +0200
+From: Jann Fischer <rezine@hannover.ccc.de>
+To: test@mistrust.net
+Subject: Test
+Message-Id: <20030824154915.12cb3f85.rezine@hannover.ccc.de>
+Organization: Chaos Computer Club Hannover
+X-Mailer: Who-Cares 5.23
+Mime-Version: 1.0
+Content-Type: multipart/encrypted; protocol="application/pgp-encrypted";
+ boundary="=.2S1ZDSX8ir3lbt"
+
+--=.2S1ZDSX8ir3lbt
+Content-Type: application/pgp-encrypted
+
+Version: 1
+
+--=.2S1ZDSX8ir3lbt
+Content-Type: application/octet-stream
+
+-----BEGIN PGP MESSAGE-----
+Version: GnuPG v1.2.2 (OpenBSD)
+
+hQEOA3TvLJ6KBZLBEAP/cl4DiRH5+8S7/kP2BIVdDavHJ9cwHh8awGoyddhMKPJ3
+2558r8MKT0Etjpo649O5WUvT5Z2Jcp12+dTPlAC1kvoIjNNk8+Oe3JCREz/pXYnm
+5ANSCThVYSS34jppgT3NsqiV8sQK3e+Nq/NY7SoKVAV37L0fU4HHozcDZfXqOLsE
+AJgfxjRjjEazPHmgTTu8Pnt5gmlxyP35Yy0pl+gJmboG3Cn5WBcD/rrQf8oiwrB6
+Vak2Hk9TNU7hDO2IRolz4wUfkId47SK31PdhDLBnNPWn6LNWHd+G4hI97e+xeqLW
+dpG7Li5CdP0gfuHx2ux9Y5buWVVtqPhdDUlRaIBfM7Fu0sENAeREANAtdPHn0yTf
+V4T5NvImY3gXgLST5wNm3Ft+4nIDZrcnSy04x4faTLFBOcY95W0O1omILHyN5Ste
+Le5NhXhQRKyl6ebXtIvEOsJOK4NT6JaUF20l4yvgf0AnetG9Pbzc37mRqmE6Fb8O
+h/De3iqw7dexaQc+LaD3XTmvPyyDK2aI4cXOdc9WOzrWR7+9iEiY32SFsQWMRMZJ
+GdKkGk22K2p7MPFaU3MHQ3Af+WCN4mRW8SurFxH1379Y5e1IPfTeL6OBkj8hHilX
+Y+Y7523ADiStJsONIZPBXJVhZ/VAJ+jL+T1/Xht10VsJcWAY8A9tP+jNgyg8dh+J
+JgWVchQOZipdftYwR7w5GkhL2Nc5NYBJBg4DFd9g2nnwuzaAKYO5kMTzEmm9KOYq
+0DC5ukok4SGDwWPUIogNHmaSnFr723hYuJC7DwSxHXVG3VxxF78u1gzEnImOWRsf
+1RzGb7b8Lf7Rj98H5cNiZ55BXAmidjm7WghCLsT2GvxviqQoRIJ2h/WHM0Bl2v3F
+Dpa3N01p2NIIgQLRoXXyBCZTwGOH4y9nBj5PU7vzzSrMweHHt1BwHXcqItCyWFXX
+2tj4//Dyw3Lw/L5xGxYRP1Q=
+=fSLd
+-----END PGP MESSAGE-----
+
+--=.2S1ZDSX8ir3lbt--
diff --git a/main/minimime/tests/messages/test3.txt b/main/minimime/tests/messages/test3.txt
new file mode 100644
index 000000000..082b6fb61
--- /dev/null
+++ b/main/minimime/tests/messages/test3.txt
@@ -0,0 +1,12 @@
+From: Jann Fischer <rezine@criminology.de>
+To: cipherlist <cipherlist@mistrust.net>
+Subject: Foobar
+Date: blahblah
+MIME-Version: 1.0 (MiniMIME)
+Content-Type: multipart/mixed; boundary="abcd"
+
+--abcd
+Content-Type: plain/text;
+
+This is a test :->
+--abcd--
diff --git a/main/minimime/tests/messages/test4.txt b/main/minimime/tests/messages/test4.txt
new file mode 100644
index 000000000..a08246939
--- /dev/null
+++ b/main/minimime/tests/messages/test4.txt
@@ -0,0 +1,168 @@
+X-Envelope-From: <511-bounces@hannover.ccc.de>
+X-Envelope-To: <rezine@criminology.de>
+X-Delivery-Time: 1070263752
+Received: from gost.hannover.ccc.de (hannover.ccc.de [62.48.71.164])
+ by mailin.webmailer.de (8.12.10/8.12.10) with ESMTP id hB17TAUR020052
+ for <rezine@criminology.de>; Mon, 1 Dec 2003 08:29:10 +0100 (MET)
+Received: from localhost.hannover.ccc.de (unknown [127.0.0.1])
+ by gost.hannover.ccc.de (Postfix) with ESMTP
+ id 092C8BC81; Mon, 1 Dec 2003 08:29:23 +0100 (CET)
+X-Original-To: 511@hannover.ccc.de
+Delivered-To: 511@hannover.ccc.de
+Received: from sbapp3 (unknown [211.157.36.9])
+ by gost.hannover.ccc.de (Postfix) with ESMTP id 3F93ABC7C
+ for <511@hannover.ccc.de>; Mon, 1 Dec 2003 08:29:12 +0100 (CET)
+From: "Vanessa Lintner" <reply@seekercenter.net>
+To: 511@hannover.ccc.de
+Date: Mon, 1 Dec 2003 15:30:57 +0800
+X-Priority: 3
+X-Library: Indy 8.0.25
+Message-Id: <20031201072912.3F93ABC7C@gost.hannover.ccc.de>
+Subject: [CCC511] http://lists.hannover.ccc.de
+X-BeenThere: 511@hannover.ccc.de
+X-Mailman-Version: 2.1.2
+Precedence: list
+Reply-To: Vanessa Lintner <vanessa@seekercenter.net>,
+ Oeffentliche Mailingliste des C3H <511@hannover.ccc.de>
+List-Id: Oeffentliche Mailingliste des C3H <511.hannover.ccc.de>
+List-Unsubscribe: <http://hannover.ccc.de/mailman/listinfo/511>,
+ <mailto:511-request@hannover.ccc.de?subject=unsubscribe>
+List-Post: <mailto:511@hannover.ccc.de>
+List-Help: <mailto:511-request@hannover.ccc.de?subject=help>
+List-Subscribe: <http://hannover.ccc.de/mailman/listinfo/511>,
+ <mailto:511-request@hannover.ccc.de?subject=subscribe>
+Content-Type: multipart/mixed; boundary="===============14807035762661644=="
+Sender: 511-bounces@hannover.ccc.de
+Errors-To: 511-bounces@hannover.ccc.de
+
+--===============14807035762661644==
+Content-Type: text/html;
+
+<html>
+<head>
+<title></title>
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
+<style type="text/css">
+.stbtm {
+ BACKGROUND-COLOR:#cecbde; BORDER-BOTTOM: #665b8e 1px solid; BORDER-LEFT: #ffffff 1px solid; BORDER-RIGHT: #665b8e 1px solid; BORDER-TOP: #ffffff 1px solid; COLOR: #000000; FONT-SIZE: 12pt; HEIGHT: 26px; WIDTH: 120px; clip: rect( )}
+.stedit {
+ background-color:#484C68; white-space: nowrap; border: #000000; BORDER-BOTTOM: #ffffff 1px solid; BORDER-LEFT: #ffffff 1px solid; BORDER-RIGHT: #ffffff 1px solid; BORDER-TOP: #ffffff 1px solid; FONT-SIZE: 10pt; color: #CCCCCC; font-weight: bold}
+
+</style>
+</head>
+<BODY leftMargin=0 onload="" topMargin=0 marginheight="0" marginwidth="0" bgcolor="#FFFFFF">
+ <table border="0" cellspacing="0" cellpadding="0" width="580">
+ <tr>
+ <td width="20" rowspan="2">&nbsp;</td>
+ <td colspan="3">
+ <table border="0" cellspacing="0" cellpadding="0" align="left" width="560">
+ <tr>
+ <td width="330" height="307">
+ <table width="330" border="0" cellspacing="0" cellpadding="0" background="http://www.imagespool.com/skbmp/letter_01.gif" height="307">
+ <tr>
+ <td>
+ <p> <font face=Arial size=2> </font> <font face=Arial size=2><font face="Verdana, Arial, Helvetica, sans-serif" color="#000000">Hello,<br>
+ <br>
+ I have visited <a href='http://lists.hannover.ccc.de'>lists.hannover.ccc.de</a>
+ and noticed that your website is not listed on some search
+ engines. I am sure that through our service the number of
+ people who visit your website will definitely increase.
+ <a target=_blank href="http://www.seekercenter.net/index.php">SeekerCenter</a>
+ is a unique technology that instantly submits your website
+ to over 500,000 search engines and directories -- a really
+ low-cost and effective way to advertise your site. For more
+ details please go to <a target=_blank href="http://www.seekercenter.net/index.php">SeekerCenter.net</a>.<br>
+ <br>
+ Give your website maximum exposure today!<br>
+ Looking forward to hearing from you.<br>
+ <br>
+ </font></font>
+ <table border=0 width=100%>
+ <tr>
+ <td width=50%> <font face="Arial" color="#000000" size="2">Best
+ Regards,<br>
+ Vanessa Lintner<br>
+ Sales &amp; Marketing <br>
+ <a target=_blank href="http://www.seekercenter.net/index.php">www.SeekerCenter.net</a></font>
+ <TD><td width=50%>
+ <div align="center" valign=middle>
+ <form target=_blank action=http://www.seekercenter.net method=POST>
+ <input type="submit" name="Submit" value="Signup Now!!!" class="stbtm">
+ </form>
+ </div>
+ </TD>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ <td width="250" height="64" valign="middle">
+ <table width="230" border="0" cellspacing="0" cellpadding="0">
+ <tr>
+ <td colspan="3" height="2"></td>
+ </tr>
+ <tr>
+ <td colspan="3"><img src="http://report.imagespool.com/report_email.php?s=1&e=511@hannover.ccc.de" border=0 width=0 height=0>
+ <p><img src="http://www.imagespool.com/skbmp/letter_04.gif" height="12"></p>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3"><img src="http://www.imagespool.com/skbmp/letter_05.gif" height="127"><img src="http://ww2.imagespool.com/1/9/b/0r066.jpg" width="177" height="127"><img src="http://www.imagespool.com/skbmp/letter_07.gif" width="33" height="127"></td>
+ </tr>
+ <tr>
+ <td colspan="3" height="92" background="http://www.imagespool.com/skbmp/letter_08.gif" valign="bottom">
+ <table width="230" border="0" cellspacing="0" cellpadding="0" height="92">
+ <tr>
+ <td width="36" height="43">&nbsp;</td>
+ <td width="157" height="43">&nbsp;</td>
+ <td width="134" height="43">&nbsp;</td>
+ </tr>
+ <tr>
+ <td width="36" height="2">&nbsp;</td>
+ <td width="157" height="2">&nbsp;</td>
+ <td width="134" height="2">&nbsp;</td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr> </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ <tr>
+ <td colspan="3">
+ <table width="560" border="0" cellspacing="0" cellpadding="1" bordercolor="0">
+ <tr>
+ <td>&nbsp;</td>
+ </tr>
+ <tr>
+ <td bgcolor="#EFEFEF"><font face="Verdana, Arial, Helvetica, sans-serif" size="1">You
+ are receiving this email because you opted-in to receive special
+ offers through a partner website. If you feel that you received
+ this email in error or do not wish to receive additional special
+ offers, please enter your email address here and click the button
+ of &quot;Remove Me&quot;: <a href="http://www.seekercenter.net/remove.php?email=511@hannover.ccc.de">
+ <img src="http://www.imagespool.com/skbmp/removeme.gif" width="73" height="17" border="0"></a>
+ </font></td>
+ </tr>
+ </table>
+ </td>
+ </tr>
+ </table>
+</body>
+</html>
+
+--===============14807035762661644==
+Content-Type: text/plain; charset="iso-8859-1"
+MIME-Version: 1.0
+Content-Transfer-Encoding: quoted-printable
+Content-Disposition: inline
+
+_______________________________________________
+511 mailing list
+511@hannover.ccc.de
+--===============14807035762661644==--
diff --git a/main/minimime/tests/messages/test5.txt b/main/minimime/tests/messages/test5.txt
new file mode 100644
index 000000000..5e4cdb17d
--- /dev/null
+++ b/main/minimime/tests/messages/test5.txt
@@ -0,0 +1,44 @@
+Return-Path: <rezine@criminology.de>
+X-Original-To: rezine@mistrust.net
+Delivered-To: rezine@hannover.ccc.de
+Received: from thinktank.niedersachsen.de (thinktank.niedersachsen.de [195.37.192.218])
+ (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits))
+ (Client did not present a certificate)
+ by gost.hannover.ccc.de (Postfix) with ESMTP id 79E9BBC7C
+ for <rezine@mistrust.net>; Wed, 24 Dec 2003 13:35:36 +0100 (CET)
+Received: from thinktank.niedersachsen.de (localhost [127.0.0.1])
+ by thinktank.niedersachsen.de (8.12.9/8.12.2) with SMTP id hBOCZBFU029588
+ for <rezine@mistrust.net>; Wed, 24 Dec 2003 13:35:11 +0100 (CET)
+Date: Wed, 24 Dec 2003 13:35:11 +0100
+From: Jann Fischer <rezine@criminology.de>
+To: rezine@mistrust.net
+Subject: Test
+Message-Id: <20031224133511.5f4b6d9b.rezine@criminology.de>
+X-Mailer: Who Cares 5.23
+Mime-Version: 1.0
+Content-Type: multipart/mixed;
+ boundary="Multipart_Wed__24_Dec_2003_13:35:11_+0100_00148800"
+
+This is a multi-part message in MIME format.
+
+--Multipart_Wed__24_Dec_2003_13:35:11_+0100_00148800
+Content-Type: text/plain; charset=US-ASCII
+Content-Transfer-Encoding: 7bit
+
+Test
+
+--
+Be careful who you follow.
+0x6D839821 | FA8C 3663 9906 D8C3 AC16 F7C4 66E0 F351 6D83 9821
+
+--Multipart_Wed__24_Dec_2003_13:35:11_+0100_00148800
+Content-Type: application/octet-stream;
+ name="bar.c"
+Content-Disposition: attachment;
+ filename="bar.c"
+Content-Transfer-Encoding: base64
+
+I2luY2x1ZGUgPHN0ZGlvLmg+Cgp2b2lkCm1haW4oaW50IGFyZ2MsIGNoYXIgKiphcmd2KQp7CgkJ
+cHJpbnRmKCIlc1xuIiwgYXJndlswXSk7Cn0K
+
+--Multipart_Wed__24_Dec_2003_13:35:11_+0100_00148800--
diff --git a/main/minimime/tests/messages/test6.txt b/main/minimime/tests/messages/test6.txt
new file mode 100644
index 000000000..fb4e7a14c
--- /dev/null
+++ b/main/minimime/tests/messages/test6.txt
@@ -0,0 +1,12 @@
+From: Me
+Date: Foobar
+To: There
+MIME-Version: 1.0
+Content-Type: multipart/mixed; boundary="abcde"
+
+--abcde
+Content-Type: text/plain
+
+Blah blah
+Blah
+--abcde--
diff --git a/main/minimime/tests/messages/test7.txt b/main/minimime/tests/messages/test7.txt
new file mode 100644
index 000000000..1cda11e3f
--- /dev/null
+++ b/main/minimime/tests/messages/test7.txt
@@ -0,0 +1,64 @@
+Return-Path: MAILER-DAEMON
+Received: from chaos.verfassungsschutz.de (localhost [IPv6:::1])
+ by chaos.verfassungsschutz.de (8.12.7/8.12.2) with ESMTP id h2EKV1oM031761
+ for <jfi@chaos.verfassungsschutz.de>; Fri, 14 Mar 2003 21:31:18 +0100 (CET)
+Received: from localhost (localhost)
+ by chaos.verfassungsschutz.de (8.12.7/8.12.2/Submit) id h2BNU1vr029177;
+ Wed, 12 Mar 2003 00:35:01 +0100 (CET)
+Date: Wed, 12 Mar 2003 00:35:01 +0100 (CET)
+From: Mail Delivery Subsystem <MAILER-DAEMON@chaos.verfassungsschutz.de>
+Message-Id: <200303112335.h2BNU1vr029177@chaos.verfassungsschutz.de>
+To: jfi@chaos.verfassungsschutz.de
+MIME-Version: 1.0
+Content-Type: multipart/report; report-type=delivery-status;
+ boundary="h2BNU1vr029177.1047425701/chaos.verfassungsschutz.de"
+Subject: Warning: could not send message for past 4 hours
+Auto-Submitted: auto-generated (warning-timeout)
+
+This is a MIME-encapsulated message
+
+--h2BNU1vr029177.1047425701/chaos.verfassungsschutz.de
+
+ **********************************************
+ ** THIS IS A WARNING MESSAGE ONLY **
+ ** YOU DO NOT NEED TO RESEND YOUR MESSAGE **
+ **********************************************
+
+The original message was received at Tue, 11 Mar 2003 20:18:36 +0100 (CET)
+from jfi@localhost
+
+ ----- Transcript of session follows -----
+451 4.4.1 reply: read error from localhost
+rezine@kommunism.us... Deferred: Connection timed out with localhost
+Warning: message still undelivered after 4 hours
+Will keep trying until message is 5 days old
+
+--h2BNU1vr029177.1047425701/chaos.verfassungsschutz.de
+Content-Type: message/delivery-status
+
+Reporting-MTA: dns; chaos.verfassungsschutz.de
+Arrival-Date: Tue, 11 Mar 2003 20:18:36 +0100 (CET)
+
+Final-Recipient: RFC822; rezine@kommunism.us
+Action: delayed
+Status: 4.4.2
+Last-Attempt-Date: Wed, 12 Mar 2003 00:35:01 +0100 (CET)
+Will-Retry-Until: Sun, 16 Mar 2003 20:18:36 +0100 (CET)
+
+--h2BNU1vr029177.1047425701/chaos.verfassungsschutz.de
+Content-Type: message/rfc822
+
+Return-Path: <jfi>
+Received: (from jfi@localhost)
+ by chaos.verfassungsschutz.de (8.12.7/8.12.2/Submit) id h2BJIawm025679
+ for rezine@kommunism.us; Tue, 11 Mar 2003 20:18:36 +0100 (CET)
+Date: Tue, 11 Mar 2003 20:18:36 +0100 (CET)
+From: Jann Fischer <jfi>
+Message-Id: <200303111918.h2BJIawm025679@chaos.verfassungsschutz.de>
+To: rezine@kommunism.us
+Subject: Test
+
+Test
+
+--h2BNU1vr029177.1047425701/chaos.verfassungsschutz.de--
+
diff --git a/main/minimime/tests/parse.c b/main/minimime/tests/parse.c
new file mode 100644
index 000000000..805bd2cb1
--- /dev/null
+++ b/main/minimime/tests/parse.c
@@ -0,0 +1,231 @@
+/*
+ * Copyright (c) 2004 Jann Fischer. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+/*
+ * MiniMIME test program - parse.c
+ *
+ * Parses any given messages
+ */
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <err.h>
+
+#include "mm.h"
+
+const char *progname;
+
+void
+usage(void)
+{
+ fprintf(stderr,
+ "MiniMIME test suite\n"
+ "Usage: %s [-m] <filename>\n\n"
+ " -m : use memory based scanning\n\n",
+ progname
+ );
+ exit(1);
+}
+
+int
+main(int argc, char **argv)
+{
+ MM_CTX *ctx;
+ struct mm_mimeheader *header, *lastheader = NULL;
+ struct mm_mimepart *part;
+ struct mm_content *ct;
+ int parts, i;
+ struct stat st;
+ int fd;
+ char *buf;
+ int scan_mode = 0;
+
+ progname = strdup(argv[0]);
+
+ while ((i = getopt(argc, argv, "m")) != -1) {
+ switch(i) {
+ case 'm':
+ scan_mode = 1;
+ break;
+ default:
+ usage();
+ }
+ }
+
+ argc -= optind;
+ argv += optind;
+
+ if (argc < 1) {
+ usage();
+ }
+
+#ifdef __HAVE_LEAK_DETECTION
+ /* Initialize memory leak detection if compiled in */
+ MM_leakd_init();
+#endif
+
+ /* Initialize MiniMIME library */
+ mm_library_init();
+
+ /* Register all default codecs (base64/qp) */
+ mm_codec_registerdefaultcodecs();
+
+ do {
+ /* Create a new context */
+ ctx = mm_context_new();
+
+ /* Parse a file into our context */
+ if (scan_mode == 0) {
+ i = mm_parse_file(ctx, argv[0], MM_PARSE_LOOSE, 0);
+ } else {
+ if (stat(argv[0], &st) == -1) {
+ err(1, "stat");
+ }
+
+ if ((fd = open(argv[0], O_RDONLY)) == -1) {
+ err(1, "open");
+ }
+
+ buf = (char *)malloc(st.st_size);
+ if (buf == NULL) {
+ err(1, "malloc");
+ }
+
+ if (read(fd, buf, st.st_size) != st.st_size) {
+ err(1, "read");
+ }
+
+ close(fd);
+ buf[st.st_size] = '\0';
+
+ i = mm_parse_mem(ctx, buf, MM_PARSE_LOOSE, 0);
+ }
+
+ if (i == -1 || mm_errno != MM_ERROR_NONE) {
+ printf("ERROR: %s at line %d\n", mm_error_string(), mm_error_lineno());
+ exit(1);
+ }
+
+ /* Get the number of MIME parts */
+ parts = mm_context_countparts(ctx);
+ if (parts == 0) {
+ printf("ERROR: got zero MIME parts, huh\n");
+ exit(1);
+ } else {
+ if (mm_context_iscomposite(ctx)) {
+ printf("Got %d MIME parts\n", parts - 1);
+ } else {
+ printf("Flat message (not multipart)\n");
+ }
+ }
+
+ /* Get the main MIME part */
+ part = mm_context_getpart(ctx, 0);
+ if (part == NULL) {
+ fprintf(stderr, "Could not get envelope part\n");
+ exit(1);
+ }
+
+ printf("Printing envelope headers:\n");
+ /* Print all headers */
+ lastheader = NULL;
+ while ((header = mm_mimepart_headers_next(part, &lastheader)) != NULL)
+ printf("%s: %s\n", header->name, header->value);
+
+ printf("%s\n", mm_content_tostring(part->type));
+ printf("\n");
+
+ ct = part->type;
+ assert(ct != NULL);
+
+ if (mm_context_iscomposite(ctx) == 0) {
+ printf("Printing body part for FLAT message:\n");
+ part = mm_context_getpart(ctx, 0);
+ printf("%s", part->body);
+ }
+
+ /* Loop through all MIME parts beginning with 1 */
+ for (i = 1; i < mm_context_countparts(ctx); i++) {
+ char *decoded;
+
+ printf("Printing headers for MIME part %d\n", i);
+
+ /* Get the current MIME entity */
+ part = mm_context_getpart(ctx, i);
+ if (part == NULL) {
+ fprintf(stderr, "Should have %d parts but "
+ "couldn't retrieve part %d",
+ mm_context_countparts(ctx), i);
+ exit(1);
+ }
+
+ /* Print all headers */
+ lastheader = NULL;
+ while ((header = mm_mimepart_headers_next(part, &lastheader)) != NULL)
+ printf("%s: %s\n", header->name, header->value);
+
+ printf("%s\n", mm_content_tostring(part->type));
+
+ /* Print MIME part body */
+ printf("\nPRINTING MESSAGE BODY (%d):\n%s\n", i, part->opaque_body);
+ decoded = mm_mimepart_decode(part);
+ if (decoded != NULL) {
+ printf("DECODED:\n%s\n", decoded);
+ free(decoded);
+ }
+ }
+
+ printf("RECONSTRUCTED MESSAGE:\n");
+
+ do {
+ char *env;
+ size_t env_len;
+
+ mm_context_flatten(ctx, &env, &env_len, 0);
+ printf("%s", env);
+ free(env);
+
+ } while (0);
+
+ mm_context_free(ctx);
+ ctx = NULL;
+
+#ifdef __HAVE_LEAK_DETECTION
+ MM_leakd_printallocated();
+#endif
+
+ } while (0);
+
+ return 0;
+}
diff --git a/main/strcompat.c b/main/strcompat.c
index f6e3bfa07..dbad22b75 100644
--- a/main/strcompat.c
+++ b/main/strcompat.c
@@ -341,3 +341,131 @@ int getloadavg(double *list, int nelem)
}
#endif /* linux */
#endif /* !HAVE_GETLOADAVG */
+
+
+/*
+ * For strlcat()
+ *
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Appends src to string dst of size siz (unlike strncat, siz is the
+ * full size of dst, not space left). At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz <= strlen(dst)).
+ * Returns strlen(src) + MIN(siz, strlen(initial dst)).
+ * If retval >= siz, truncation occurred.
+ */
+#ifndef HAVE_STRLCAT
+size_t strlcat(char *dst, const char *src, size_t siz)
+{
+ register char *d = dst;
+ register const char *s = src;
+ register size_t n = siz;
+ size_t dlen;
+
+ /* Find the end of dst and adjust bytes left but don't go past end */
+ while (n-- != 0 && *d != '\0')
+ d++;
+ dlen = d - dst;
+ n = siz - dlen;
+
+ if (n == 0)
+ return dlen + strlen(s);
+
+ while (*s != '\0') {
+ if (n != 1) {
+ *d++ = *s;
+ n--;
+ }
+ s++;
+ }
+ *d = '\0';
+
+ return dlen + (s - src); /* count does not include NUL */
+}
+#endif /* HAVE_STRLCAT */
+
+/*
+ * For strlcpy()
+ *
+ * Copyright (c) 1998 Todd C. Miller <Todd.Miller@courtesan.com>
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
+ * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
+ * THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Copy src to string dst of size siz. At most siz-1 characters
+ * will be copied. Always NUL terminates (unless siz == 0).
+ * Returns strlen(src); if retval >= siz, truncation occurred.
+ */
+#ifndef HAVE_STRLCPY
+size_t strlcpy(char *dst, const char *src, size_t siz)
+{
+ register char *d = dst;
+ register const char *s = src;
+ register size_t n = siz;
+
+ /* Copy as many bytes as will fit */
+ if (n != 0 && --n != 0) {
+ do {
+ if ((*d++ = *s++) == 0)
+ break;
+ } while (--n != 0);
+ }
+
+ /* Not enough room in dst, add NUL and traverse rest of src */
+ if (n == 0) {
+ if (siz != 0)
+ *d = '\0'; /* NUL-terminate dst */
+ while (*s++)
+ ;
+ }
+
+ return s - src - 1; /* count does not include NUL */
+}
+#endif /* HAVE_STRLCPY */