---
src/drv_imap.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 118 insertions(+)
diff --git a/src/drv_imap.c b/src/drv_imap.c
index 7bc88f6..918dead 100644
--- a/src/drv_imap.c
+++ b/src/drv_imap.c
@@ -35,6 +35,8 @@
#include <ctype.h>
#include <time.h>
#include <sys/wait.h>
+#include <iconv.h>
+#include <langinfo.h>
#ifdef HAVE_LIBSASL
# include <sasl/sasl.h>
@@ -237,6 +239,7 @@ static const char *cap_list[] = {
#define RESP_OK 0
#define RESP_NO 1
#define RESP_CANCEL 2
+#define UTF7_INBOX_NAME_MAX_LENGTH 2048
static INLINE void imap_ref( imap_store_t *ctx ) { ++ctx->ref_count; }
static int imap_deref( imap_store_t *ctx );
@@ -273,6 +276,121 @@ new_imap_cmd( int size )
cmdp->gen.callback = cb; \
cmdp->gen.callback_aux = aux;
+static void
+change_shift_char(char const *src, char *dest,
+ size_t max_length,
+ char const old_shift, char const new_shift)
+{
+ for ( ; *src != '\0' && max_length != 0; src++, dest++ ) {
+ // decode litteral old_shift
+ if (*src == old_shift && *(src + 1) == '-') {
+ *dest = *src;
+ src++;
+ if (*src == '\0')
+ break ;
+ }
+ // replace shift
+ else if (*src == old_shift) {
+ *dest = new_shift;
+ }
+ // encode litteral new_shift
+ else if (*src == new_shift) {
+ *dest = new_shift;
+ dest++;
+ max_length--;
+ *dest = '-';
+ }
+ else
+ *dest = *src;
+ max_length--;
+ }
+ *dest = '\0';
+}
+
+static void
+imap_to_utf7(char const *src, char *dest,
+ size_t max_length)
+{
+ change_shift_char(src, dest, max_length, '&', '+');
+}
+
+static void
+utf7_to_imap(char const *src, char *dest,
+ size_t max_length)
+{
+ change_shift_char(src, dest, max_length, '+', '&');
+}
+
+static char *
+decode_utf7_imap(const char * utf7_imap_string)
+{
+ char utf7_plain[UTF7_INBOX_NAME_MAX_LENGTH + 1];
+
+ assert(utf7_imap_string != NULL);
+ imap_to_utf7(utf7_imap_string, utf7_plain, UTF7_INBOX_NAME_MAX_LENGTH);
+
+ size_t length = strlen(utf7_plain);
+ iconv_t conv_state = iconv_open(nl_langinfo(CODESET) , "UTF-7");
+ char * locale_encoding = NULL;
+ if (conv_state != (iconv_t)-1) {
+ size_t output_size = sizeof(*locale_encoding) * (length + 1) *
4;
+ // Use a safety margin should locale encoding produce a longer
string
+ locale_encoding = nfmalloc(output_size);
+ char * utf7 = utf7_plain;
+ char * local = locale_encoding;
+
+ if ((size_t)-1 == iconv(
+ conv_state,
+ &utf7, &length,
+ &local, &output_size)) {
+ error( "Unicode error: the folling string could not be
converted to system locale :\n");
+ error( utf7_imap_string);
+ error (nl_langinfo(CODESET));
+ free(locale_encoding);
+ locale_encoding = NULL;
+ } else {
+ *local = '\0';
+ }
+ }
+ iconv_close(conv_state);
+ return locale_encoding;
+}
+
+static char *
+encode_utf7_imap(const char * locale_string)
+{
+ char utf7[UTF7_INBOX_NAME_MAX_LENGTH + 1];
+ size_t length = strlen(locale_string);
+ char * imap = NULL;
+
+ assert(locale_string != NULL);
+ // + locale_string is a valid locale string.
+
+ iconv_t conv_state = iconv_open("UTF-7" , nl_langinfo(CODESET));
+ if (conv_state != (iconv_t)-1) {
+ size_t output_size = UTF7_INBOX_NAME_MAX_LENGTH;
+ // Use a safety margin should utf7 encoding produce a longer
string
+ char *utf7_plain = utf7;
+
+ if ((size_t)-1 == iconv(
+ conv_state,
+ &locale_string, &length,
+ &utf7_plain, &output_size)) {
+ error( "Unicode error: the folling string could not be
converted to UTF-7\n");
+ error( locale_string);
+ error (nl_langinfo(CODESET));
+ } else {
+ *utf7_plain = '\0';
+ imap = nfmalloc(sizeof(*imap) * (strlen(utf7) + 1) * 2);
+ // Transcoding can produce a string twice as long in
the worse case.
+ utf7_to_imap(utf7, imap, UTF7_INBOX_NAME_MAX_LENGTH);
+ }
+ }
+ iconv_close(conv_state);
+
+ return imap;
+}
+
static void
done_imap_cmd( imap_store_t *ctx, imap_cmd_t *cmd, int response )
{
--
2.26.2
_______________________________________________
isync-devel mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/isync-devel