summaryrefslogtreecommitdiffstats
path: root/maildir/maildirinfo2.c
diff options
context:
space:
mode:
authorSam Varshavchik2018-07-14 15:51:42 -0400
committerSam Varshavchik2018-07-16 21:20:25 -0400
commit9643d3d5adcbc6357833a818e2928eb8e76717ed (patch)
tree367ec86c8ccfb3aa2ab40b2440ebabfea382e0ce /maildir/maildirinfo2.c
parent3359e8155147662382d2fd982bcf75a1644901a0 (diff)
downloadcourier-libs-9643d3d5adcbc6357833a818e2928eb8e76717ed.tar.bz2
Add maidirmake options to convert pre-unicode mailboxes to unicode mailboxes.
Diffstat (limited to 'maildir/maildirinfo2.c')
-rw-r--r--maildir/maildirinfo2.c148
1 files changed, 148 insertions, 0 deletions
diff --git a/maildir/maildirinfo2.c b/maildir/maildirinfo2.c
new file mode 100644
index 0000000..fcae14c
--- /dev/null
+++ b/maildir/maildirinfo2.c
@@ -0,0 +1,148 @@
+/*
+** Copyright 2018 Double Precision, Inc.
+** See COPYING for distribution information.
+*/
+
+#if HAVE_CONFIG_H
+#include "config.h"
+#endif
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <ctype.h>
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "maildirinfo.h"
+#include <courier-unicode.h>
+
+
+/* Count the size of the converted filename or foldername string */
+static void count_utf8(const char *str, size_t n, void *arg)
+{
+ *(size_t *)arg += n;
+}
+
+/* Save the converted filename or foldername string */
+static void save_utf8(const char *str, size_t n, void *arg)
+{
+ char **p=(char **)arg;
+
+ memcpy( (*p), str, n);
+ *p += n;
+}
+
+/*
+** Split a string at periods, convert each split range between charsets.
+*/
+static int foldername_filename_convert(const char *src_chset,
+ const char *dst_chset,
+ const char *foldername,
+ void (*closure)(const char *, size_t,
+ void *),
+ void *arg)
+{
+ unicode_convert_handle_t h;
+ char *cbufptr;
+ size_t cbufsize;
+ size_t l;
+ int conversion_error;
+
+ while (*foldername)
+ {
+ if (*foldername == '.')
+ {
+ (*closure)(foldername, 1, arg);
+ ++foldername;
+ continue;
+ }
+
+ h=unicode_convert_tocbuf_init(src_chset,
+ dst_chset,
+ &cbufptr,
+ &cbufsize,
+ 0);
+ if (!h)
+ {
+ errno=EINVAL;
+ return -1;
+ }
+
+ for (l=0; foldername[l] && foldername[l] != '.'; ++l)
+ ;
+
+ unicode_convert(h, foldername, l);
+
+ if (unicode_convert_deinit(h, &conversion_error) == 0)
+ {
+ closure(cbufptr, cbufsize, arg);
+ free(cbufptr);
+ if (conversion_error)
+ {
+ errno=EILSEQ;
+ return -1;
+ }
+ }
+ else
+ return -1;
+ foldername += l;
+ }
+ return 0;
+}
+
+/* Convert either a foldername or a filename to the other */
+
+static char *foldername_filename_convert_tobuf(const char *src_chset,
+ const char *dst_chset,
+ const char *foldername)
+{
+ char *utf8, *p;
+ size_t l=1;
+
+ if (foldername_filename_convert(src_chset,
+ dst_chset,
+ foldername, count_utf8, &l))
+ return NULL;
+
+ utf8=malloc(l+1);
+
+ if (!utf8)
+ return NULL;
+
+ p=utf8;
+ if (foldername_filename_convert(src_chset,
+ dst_chset,
+ foldername, save_utf8, &p))
+ {
+ free(utf8);
+ return NULL;
+ }
+
+ *p=0;
+
+ return utf8;
+}
+
+char *imap_foldername_to_filename(int utf8_format, const char *foldername)
+{
+ if (utf8_format)
+ return strdup(foldername);
+
+ return foldername_filename_convert_tobuf
+ (unicode_x_imap_modutf7,
+ "utf-8",
+ foldername);
+}
+
+char *imap_filename_to_foldername(int utf8_format, const char *filename)
+{
+ if (utf8_format)
+ return strdup(filename);
+
+ return foldername_filename_convert_tobuf
+ ("utf-8",
+ unicode_x_imap_modutf7,
+ filename);
+}