/* util-imap-utf7.c generated by valac 0.56.3, the Vala compiler
 * generated from util-imap-utf7.vala, do not modify */

/* Copyright 2016 Software Freedom Conservancy Inc.
 * Copyright (c) 2008-2012 Dovecot authors
 *
 * This software is licensed under the GNU Lesser General Public License
 * (version 2.1 or later).  See the COPYING file in this distribution.
 */

#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include "geary-engine.h"

#define GEARY_IMAP_UTF7_UTF16_SURROGATE_BASE ((gunichar) 0x10000)
#define GEARY_IMAP_UTF7_UTF16_SURROGATE_SHIFT 10
#define GEARY_IMAP_UTF7_UTF16_SURROGATE_MASK ((gunichar) 0x03ff)
#define GEARY_IMAP_UTF7_UTF16_SURROGATE_HIGH_FIRST ((gunichar) 0xd800)
#define GEARY_IMAP_UTF7_UTF16_SURROGATE_HIGH_LAST ((gunichar) 0xdbff)
#define GEARY_IMAP_UTF7_UTF16_SURROGATE_HIGH_MAX ((gunichar) 0xdfff)
#define GEARY_IMAP_UTF7_UTF16_SURROGATE_LOW_FIRST ((gunichar) 0xdc00)
#define GEARY_IMAP_UTF7_UTF16_SURROGATE_LOW_LAST ((gunichar) 0xdfff)
#define GEARY_IMAP_UTF7_imap_b64enc "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+,"
#define GEARY_IMAP_UTF7_XX ((guint8) 0xff)

#define _g_string_free0(var) ((var == NULL) ? NULL : (var = (g_string_free (var, TRUE), NULL)))
#define _g_free0(var) (var = (g_free (var), NULL))

VALA_EXTERN gunichar geary_imap_utf7_UTF16_SURROGATE_HIGH (gunichar chr);
VALA_EXTERN gunichar geary_imap_utf7_UTF16_SURROGATE_LOW (gunichar chr);
VALA_EXTERN void geary_imap_utf7_mbase64_encode (GString* dest,
                                     guint8* input,
                                     gint input_length1);
VALA_EXTERN gint geary_imap_utf7_first_encode_index (const gchar* str);
static void _vala_array_add8 (guint8* * array,
                       gint* length,
                       gint* size,
                       guint8 value);
static void _vala_array_add9 (guint8* * array,
                       gint* length,
                       gint* size,
                       guint8 value);
static void _vala_array_add10 (guint8* * array,
                        gint* length,
                        gint* size,
                        guint8 value);
static void _vala_array_add11 (guint8* * array,
                        gint* length,
                        gint* size,
                        guint8 value);
static void _vala_array_add12 (guint8* * array,
                        gint* length,
                        gint* size,
                        guint8 value);
static void _vala_array_add13 (guint8* * array,
                        gint* length,
                        gint* size,
                        guint8 value);
VALA_EXTERN void geary_imap_utf7_utf16buf_to_utf8 (GString* dest,
                                       guint8* output,
                                       gint output_length1,
                                       gint* pos,
                                       gint len,
                                       GError** error);
VALA_EXTERN void geary_imap_utf7_mbase64_decode_to_utf8 (GString* dest,
                                             const gchar* str,
                                             gint* p,
                                             GError** error);

const guint8 GEARY_IMAP_UTF7_imap_b64dec[256] = {GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, (guint8) 62, (guint8) 63, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, (guint8) 52, (guint8) 53, (guint8) 54, (guint8) 55, (guint8) 56, (guint8) 57, (guint8) 58, (guint8) 59, (guint8) 60, (guint8) 61, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, (guint8) 0, (guint8) 1, (guint8) 2, (guint8) 3, (guint8) 4, (guint8) 5, (guint8) 6, (guint8) 7, (guint8) 8, (guint8) 9, (guint8) 10, (guint8) 11, (guint8) 12, (guint8) 13, (guint8) 14, (guint8) 15, (guint8) 16, (guint8) 17, (guint8) 18, (guint8) 19, (guint8) 20, (guint8) 21, (guint8) 22, (guint8) 23, (guint8) 24, (guint8) 25, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, (guint8) 26, (guint8) 27, (guint8) 28, (guint8) 29, (guint8) 30, (guint8) 31, (guint8) 32, (guint8) 33, (guint8) 34, (guint8) 35, (guint8) 36, (guint8) 37, (guint8) 38, (guint8) 39, (guint8) 40, (guint8) 41, (guint8) 42, (guint8) 43, (guint8) 44, (guint8) 45, (guint8) 46, (guint8) 47, (guint8) 48, (guint8) 49, (guint8) 50, (guint8) 51, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX, GEARY_IMAP_UTF7_XX};

gunichar
geary_imap_utf7_UTF16_SURROGATE_HIGH (gunichar chr)
{
	gunichar result;
	result = GEARY_IMAP_UTF7_UTF16_SURROGATE_HIGH_FIRST + ((chr - GEARY_IMAP_UTF7_UTF16_SURROGATE_BASE) >> GEARY_IMAP_UTF7_UTF16_SURROGATE_SHIFT);
	return result;
}

gunichar
geary_imap_utf7_UTF16_SURROGATE_LOW (gunichar chr)
{
	gunichar result;
	result = GEARY_IMAP_UTF7_UTF16_SURROGATE_LOW_FIRST + ((chr - GEARY_IMAP_UTF7_UTF16_SURROGATE_BASE) & GEARY_IMAP_UTF7_UTF16_SURROGATE_MASK);
	return result;
}

static gchar
string_get (const gchar* self,
            glong index)
{
	gchar _tmp0_;
	gchar result;
	g_return_val_if_fail (self != NULL, '\0');
	_tmp0_ = ((gchar*) self)[index];
	result = _tmp0_;
	return result;
}

void
geary_imap_utf7_mbase64_encode (GString* dest,
                                guint8* input,
                                gint input_length1)
{
	gint pos = 0;
	gint len = 0;
	g_return_if_fail (dest != NULL);
	g_string_append_c (dest, '&');
	pos = 0;
	len = input_length1;
	while (TRUE) {
		guint8 _tmp0_;
		guint8 _tmp1_;
		guint8 _tmp2_;
		guint8 _tmp3_;
		guint8 _tmp4_;
		guint8 _tmp5_;
		if (!(len >= 3)) {
			break;
		}
		_tmp0_ = input[pos + 0];
		g_string_append_c (dest, string_get (GEARY_IMAP_UTF7_imap_b64enc, (glong) (_tmp0_ >> 2)));
		_tmp1_ = input[pos + 0];
		_tmp2_ = input[pos + 1];
		g_string_append_c (dest, string_get (GEARY_IMAP_UTF7_imap_b64enc, (glong) (((_tmp1_ & 3) << 4) | (_tmp2_ >> 4))));
		_tmp3_ = input[pos + 1];
		_tmp4_ = input[pos + 2];
		g_string_append_c (dest, string_get (GEARY_IMAP_UTF7_imap_b64enc, (glong) (((_tmp3_ & 0x0f) << 2) | ((_tmp4_ & 0xc0) >> 6))));
		_tmp5_ = input[pos + 2];
		g_string_append_c (dest, string_get (GEARY_IMAP_UTF7_imap_b64enc, (glong) (_tmp5_ & 0x3f)));
		pos += 3;
		len -= 3;
	}
	if (len > 0) {
		guint8 _tmp6_;
		_tmp6_ = input[pos + 0];
		g_string_append_c (dest, string_get (GEARY_IMAP_UTF7_imap_b64enc, (glong) (_tmp6_ >> 2)));
		if (len == 1) {
			guint8 _tmp7_;
			_tmp7_ = input[pos + 0];
			g_string_append_c (dest, string_get (GEARY_IMAP_UTF7_imap_b64enc, (glong) ((_tmp7_ & 0x03) << 4)));
		} else {
			guint8 _tmp8_;
			guint8 _tmp9_;
			guint8 _tmp10_;
			_tmp8_ = input[pos + 0];
			_tmp9_ = input[pos + 1];
			g_string_append_c (dest, string_get (GEARY_IMAP_UTF7_imap_b64enc, (glong) (((_tmp8_ & 0x03) << 4) | (_tmp9_ >> 4))));
			_tmp10_ = input[pos + 1];
			g_string_append_c (dest, string_get (GEARY_IMAP_UTF7_imap_b64enc, (glong) ((_tmp10_ & 0x0f) << 2)));
		}
	}
	g_string_append_c (dest, '-');
}

gint
geary_imap_utf7_first_encode_index (const gchar* str)
{
	gint result;
	g_return_val_if_fail (str != NULL, 0);
	{
		gint p = 0;
		p = 0;
		{
			gboolean _tmp0_ = FALSE;
			_tmp0_ = TRUE;
			while (TRUE) {
				gboolean _tmp2_ = FALSE;
				if (!_tmp0_) {
					gint _tmp1_;
					_tmp1_ = p;
					p = _tmp1_ + 1;
				}
				_tmp0_ = FALSE;
				if (!(string_get (str, (glong) p) != '\0')) {
					break;
				}
				if (string_get (str, (glong) p) == '&') {
					_tmp2_ = TRUE;
				} else {
					_tmp2_ = ((gint) ((guint8) string_get (str, (glong) p))) >= 0x80;
				}
				if (_tmp2_) {
					result = p;
					return result;
				}
			}
		}
	}
	result = -1;
	return result;
}

static gboolean
string_get_next_char (const gchar* self,
                      gint* index,
                      gunichar* c)
{
	gunichar _vala_c = 0U;
	gboolean result;
	g_return_val_if_fail (self != NULL, FALSE);
	_vala_c = g_utf8_get_char (((gchar*) self) + (*index));
	if (_vala_c != ((gunichar) 0)) {
		gchar* _tmp0_;
		_tmp0_ = g_utf8_next_char (((gchar*) self) + (*index));
		*index = (gint) (_tmp0_ - ((gchar*) self));
		result = TRUE;
		if (c) {
			*c = _vala_c;
		}
		return result;
	} else {
		result = FALSE;
		if (c) {
			*c = _vala_c;
		}
		return result;
	}
}

static void
_vala_array_add8 (guint8* * array,
                  gint* length,
                  gint* size,
                  guint8 value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (guint8, *array, *size);
	}
	(*array)[(*length)++] = value;
}

static void
_vala_array_add9 (guint8* * array,
                  gint* length,
                  gint* size,
                  guint8 value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (guint8, *array, *size);
	}
	(*array)[(*length)++] = value;
}

static void
_vala_array_add10 (guint8* * array,
                   gint* length,
                   gint* size,
                   guint8 value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (guint8, *array, *size);
	}
	(*array)[(*length)++] = value;
}

static void
_vala_array_add11 (guint8* * array,
                   gint* length,
                   gint* size,
                   guint8 value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (guint8, *array, *size);
	}
	(*array)[(*length)++] = value;
}

static void
_vala_array_add12 (guint8* * array,
                   gint* length,
                   gint* size,
                   guint8 value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (guint8, *array, *size);
	}
	(*array)[(*length)++] = value;
}

static void
_vala_array_add13 (guint8* * array,
                   gint* length,
                   gint* size,
                   guint8 value)
{
	if ((*length) == (*size)) {
		*size = (*size) ? (2 * (*size)) : 4;
		*array = g_renew (guint8, *array, *size);
	}
	(*array)[(*length)++] = value;
}

gchar*
geary_imap_utf7_utf8_to_imap_utf7 (const gchar* str)
{
	gint p = 0;
	GString* dest = NULL;
	GString* _tmp1_;
	GString* _tmp2_;
	GString* _tmp13_;
	const gchar* _tmp14_;
	gchar* _tmp15_;
	gchar* result;
	g_return_val_if_fail (str != NULL, NULL);
	p = geary_imap_utf7_first_encode_index (str);
	if (p < 0) {
		gchar* _tmp0_;
		_tmp0_ = g_strdup (str);
		result = _tmp0_;
		return result;
	}
	_tmp1_ = g_string_new ("");
	dest = _tmp1_;
	_tmp2_ = dest;
	g_string_append_len (_tmp2_, str, (gssize) p);
	while (TRUE) {
		gint _tmp3_;
		gint _tmp4_;
		guint8* utf16 = NULL;
		guint8* _tmp9_;
		gint utf16_length1;
		gint _utf16_size_;
		GString* _tmp11_;
		guint8* _tmp12_;
		gint _tmp12__length1;
		_tmp3_ = strlen (str);
		_tmp4_ = _tmp3_;
		if (!(p < _tmp4_)) {
			break;
		}
		if (string_get (str, (glong) p) == '&') {
			GString* _tmp5_;
			gint _tmp6_;
			_tmp5_ = dest;
			g_string_append (_tmp5_, "&-");
			_tmp6_ = p;
			p = _tmp6_ + 1;
			continue;
		}
		if (((gint) ((guint8) string_get (str, (glong) p))) < 0x80) {
			GString* _tmp7_;
			gint _tmp8_;
			_tmp7_ = dest;
			g_string_append_c (_tmp7_, string_get (str, (glong) p));
			_tmp8_ = p;
			p = _tmp8_ + 1;
			continue;
		}
		_tmp9_ = g_new0 (guint8, 0);
		utf16 = _tmp9_;
		utf16_length1 = 0;
		_utf16_size_ = utf16_length1;
		while (TRUE) {
			gint next_p = 0;
			gunichar chr = 0U;
			gunichar _tmp10_ = 0U;
			if (!(((gint) ((guint8) string_get (str, (glong) p))) >= 0x80)) {
				break;
			}
			next_p = p;
			string_get_next_char (str, &next_p, &_tmp10_);
			chr = _tmp10_;
			if (chr < GEARY_IMAP_UTF7_UTF16_SURROGATE_BASE) {
				_vala_array_add8 (&utf16, &utf16_length1, &_utf16_size_, (guint8) (chr >> 8));
				_vala_array_add9 (&utf16, &utf16_length1, &_utf16_size_, (guint8) (chr & 0xff));
			} else {
				gunichar u16 = 0U;
				u16 = geary_imap_utf7_UTF16_SURROGATE_HIGH (chr);
				_vala_array_add10 (&utf16, &utf16_length1, &_utf16_size_, (guint8) (u16 >> 8));
				_vala_array_add11 (&utf16, &utf16_length1, &_utf16_size_, (guint8) (u16 & 0xff));
				u16 = geary_imap_utf7_UTF16_SURROGATE_LOW (chr);
				_vala_array_add12 (&utf16, &utf16_length1, &_utf16_size_, (guint8) (u16 >> 8));
				_vala_array_add13 (&utf16, &utf16_length1, &_utf16_size_, (guint8) (u16 & 0xff));
			}
			p = next_p;
		}
		_tmp11_ = dest;
		_tmp12_ = utf16;
		_tmp12__length1 = utf16_length1;
		geary_imap_utf7_mbase64_encode (_tmp11_, _tmp12_, (gint) _tmp12__length1);
		utf16 = (g_free (utf16), NULL);
	}
	_tmp13_ = dest;
	_tmp14_ = _tmp13_->str;
	_tmp15_ = g_strdup (_tmp14_);
	result = _tmp15_;
	_g_string_free0 (dest);
	return result;
}

static gchar*
g_unichar_to_string (gunichar self)
{
	gchar* str = NULL;
	gchar* _tmp0_;
	gchar* result;
	_tmp0_ = g_new0 (gchar, 7);
	str = (gchar*) _tmp0_;
	g_unichar_to_utf8 (self, str);
	result = str;
	return result;
}

void
geary_imap_utf7_utf16buf_to_utf8 (GString* dest,
                                  guint8* output,
                                  gint output_length1,
                                  gint* pos,
                                  gint len,
                                  GError** error)
{
	guint16 high = 0U;
	guint8 _tmp1_;
	guint8 _tmp2_;
	gboolean _tmp3_ = FALSE;
	guint16 low = 0U;
	guint8 _tmp10_;
	guint8 _tmp11_;
	gboolean _tmp12_ = FALSE;
	gunichar chr = 0U;
	gchar* s = NULL;
	gchar* _tmp14_;
	const gchar* _tmp15_;
	const gchar* _tmp17_;
	GError* _inner_error0_ = NULL;
	g_return_if_fail (dest != NULL);
	if ((len % 2) != 0) {
		GError* _tmp0_;
		_tmp0_ = g_error_new_literal (G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE, "Odd number of bytes in UTF-16 data");
		_inner_error0_ = _tmp0_;
		if (_inner_error0_->domain == G_CONVERT_ERROR) {
			g_propagate_error (error, _inner_error0_);
			return;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return;
		}
	}
	_tmp1_ = output[(*pos) % 4];
	_tmp2_ = output[((*pos) + 1) % 4];
	high = (guint16) ((_tmp1_ << 8) | _tmp2_);
	if (((gunichar) high) < GEARY_IMAP_UTF7_UTF16_SURROGATE_HIGH_FIRST) {
		_tmp3_ = TRUE;
	} else {
		_tmp3_ = ((gunichar) high) > GEARY_IMAP_UTF7_UTF16_SURROGATE_HIGH_MAX;
	}
	if (_tmp3_) {
		gchar* s = NULL;
		gchar* _tmp4_;
		const gchar* _tmp5_;
		const gchar* _tmp7_;
		_tmp4_ = g_unichar_to_string ((gunichar) high);
		s = _tmp4_;
		_tmp5_ = s;
		if (_tmp5_ == NULL) {
			GError* _tmp6_;
			_tmp6_ = g_error_new (G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE, "Couldn't convert U+%04hx to UTF-8", (gushort) high);
			_inner_error0_ = _tmp6_;
			if (_inner_error0_->domain == G_CONVERT_ERROR) {
				g_propagate_error (error, _inner_error0_);
				_g_free0 (s);
				return;
			} else {
				_g_free0 (s);
				g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
				g_clear_error (&_inner_error0_);
				return;
			}
		}
		_tmp7_ = s;
		g_string_append (dest, _tmp7_);
		*pos = ((*pos) + 2) % 4;
		_g_free0 (s);
		return;
	}
	if (((gunichar) high) > GEARY_IMAP_UTF7_UTF16_SURROGATE_HIGH_LAST) {
		GError* _tmp8_;
		_tmp8_ = g_error_new_literal (G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE, "UTF-16 data out of range");
		_inner_error0_ = _tmp8_;
		if (_inner_error0_->domain == G_CONVERT_ERROR) {
			g_propagate_error (error, _inner_error0_);
			return;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return;
		}
	}
	if (len != 4) {
		GError* _tmp9_;
		_tmp9_ = g_error_new_literal (G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE, "Truncated UTF-16 data");
		_inner_error0_ = _tmp9_;
		if (_inner_error0_->domain == G_CONVERT_ERROR) {
			g_propagate_error (error, _inner_error0_);
			return;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return;
		}
	}
	_tmp10_ = output[((*pos) + 2) % 4];
	_tmp11_ = output[((*pos) + 3) % 4];
	low = (guint16) ((_tmp10_ << 8) | _tmp11_);
	if (((gunichar) low) < GEARY_IMAP_UTF7_UTF16_SURROGATE_LOW_FIRST) {
		_tmp12_ = TRUE;
	} else {
		_tmp12_ = ((gunichar) low) > GEARY_IMAP_UTF7_UTF16_SURROGATE_LOW_LAST;
	}
	if (_tmp12_) {
		GError* _tmp13_;
		_tmp13_ = g_error_new_literal (G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE, "Illegal UTF-16 surrogate");
		_inner_error0_ = _tmp13_;
		if (_inner_error0_->domain == G_CONVERT_ERROR) {
			g_propagate_error (error, _inner_error0_);
			return;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return;
		}
	}
	chr = GEARY_IMAP_UTF7_UTF16_SURROGATE_BASE + (((high & GEARY_IMAP_UTF7_UTF16_SURROGATE_MASK) << GEARY_IMAP_UTF7_UTF16_SURROGATE_SHIFT) | (low & GEARY_IMAP_UTF7_UTF16_SURROGATE_MASK));
	_tmp14_ = g_unichar_to_string (chr);
	s = _tmp14_;
	_tmp15_ = s;
	if (_tmp15_ == NULL) {
		GError* _tmp16_;
		_tmp16_ = g_error_new (G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE, "Couldn't convert U+%04x to UTF-8", (guint) chr);
		_inner_error0_ = _tmp16_;
		if (_inner_error0_->domain == G_CONVERT_ERROR) {
			g_propagate_error (error, _inner_error0_);
			_g_free0 (s);
			return;
		} else {
			_g_free0 (s);
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return;
		}
	}
	_tmp17_ = s;
	g_string_append (dest, _tmp17_);
	_g_free0 (s);
}

void
geary_imap_utf7_mbase64_decode_to_utf8 (GString* dest,
                                        const gchar* str,
                                        gint* p,
                                        GError** error)
{
	guint8 input[4] = {0};
	guint8 output[4] = {0};
	gint outstart = 0;
	gint outpos = 0;
	gint _tmp24_;
	GError* _inner_error0_ = NULL;
	g_return_if_fail (dest != NULL);
	g_return_if_fail (str != NULL);
	outstart = 0;
	outpos = 0;
	while (TRUE) {
		guint8 _tmp0_;
		guint8 _tmp1_;
		gboolean _tmp2_ = FALSE;
		guint8 _tmp3_;
		guint8 _tmp6_;
		guint8 _tmp7_;
		gint _tmp8_;
		gint _tmp9_;
		guint8 _tmp10_;
		guint8 _tmp11_;
		guint8 _tmp13_;
		guint8 _tmp14_;
		gint _tmp15_;
		gint _tmp16_;
		guint8 _tmp17_;
		guint8 _tmp18_;
		guint8 _tmp20_;
		guint8 _tmp21_;
		gint _tmp22_;
		gint _tmp23_;
		if (!(string_get (str, (glong) (*p)) != '-')) {
			break;
		}
		_tmp0_ = GEARY_IMAP_UTF7_imap_b64dec[(guint8) string_get (str, (glong) ((*p) + 0))];
		input[0] = _tmp0_;
		_tmp1_ = GEARY_IMAP_UTF7_imap_b64dec[(guint8) string_get (str, (glong) ((*p) + 1))];
		input[1] = _tmp1_;
		_tmp3_ = input[0];
		if (((gint) _tmp3_) == 0xff) {
			_tmp2_ = TRUE;
		} else {
			guint8 _tmp4_;
			_tmp4_ = input[1];
			_tmp2_ = ((gint) _tmp4_) == 0xff;
		}
		if (_tmp2_) {
			GError* _tmp5_;
			_tmp5_ = g_error_new_literal (G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE, "Illegal character in IMAP base-64 encoded sequence");
			_inner_error0_ = _tmp5_;
			if (_inner_error0_->domain == G_CONVERT_ERROR) {
				g_propagate_error (error, _inner_error0_);
				return;
			} else {
				g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
				g_clear_error (&_inner_error0_);
				return;
			}
		}
		_tmp6_ = input[0];
		_tmp7_ = input[1];
		output[outpos % 4] = (guint8) ((_tmp6_ << 2) | (_tmp7_ >> 4));
		outpos = outpos + 1;
		_tmp8_ = outpos;
		_tmp9_ = outstart;
		if ((_tmp8_ % 4) == _tmp9_) {
			geary_imap_utf7_utf16buf_to_utf8 (dest, output, (gint) 4, &outstart, 4, &_inner_error0_);
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				if (_inner_error0_->domain == G_CONVERT_ERROR) {
					g_propagate_error (error, _inner_error0_);
					return;
				} else {
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
					g_clear_error (&_inner_error0_);
					return;
				}
			}
		}
		_tmp10_ = GEARY_IMAP_UTF7_imap_b64dec[(guint8) string_get (str, (glong) ((*p) + 2))];
		input[2] = _tmp10_;
		_tmp11_ = input[2];
		if (((gint) _tmp11_) == 0xff) {
			if (string_get (str, (glong) ((*p) + 2)) != '-') {
				GError* _tmp12_;
				_tmp12_ = g_error_new_literal (G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE, "Illegal character in IMAP base-64 encoded sequence");
				_inner_error0_ = _tmp12_;
				if (_inner_error0_->domain == G_CONVERT_ERROR) {
					g_propagate_error (error, _inner_error0_);
					return;
				} else {
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
					g_clear_error (&_inner_error0_);
					return;
				}
			}
			*p = (*p) + 2;
			break;
		}
		_tmp13_ = input[1];
		_tmp14_ = input[2];
		output[outpos % 4] = (guint8) ((_tmp13_ << 4) | (_tmp14_ >> 2));
		outpos = outpos + 1;
		_tmp15_ = outpos;
		_tmp16_ = outstart;
		if ((_tmp15_ % 4) == _tmp16_) {
			geary_imap_utf7_utf16buf_to_utf8 (dest, output, (gint) 4, &outstart, 4, &_inner_error0_);
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				if (_inner_error0_->domain == G_CONVERT_ERROR) {
					g_propagate_error (error, _inner_error0_);
					return;
				} else {
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
					g_clear_error (&_inner_error0_);
					return;
				}
			}
		}
		_tmp17_ = GEARY_IMAP_UTF7_imap_b64dec[(guint8) string_get (str, (glong) ((*p) + 3))];
		input[3] = _tmp17_;
		_tmp18_ = input[3];
		if (((gint) _tmp18_) == 0xff) {
			if (string_get (str, (glong) ((*p) + 3)) != '-') {
				GError* _tmp19_;
				_tmp19_ = g_error_new_literal (G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE, "Illegal character in IMAP base-64 encoded sequence");
				_inner_error0_ = _tmp19_;
				if (_inner_error0_->domain == G_CONVERT_ERROR) {
					g_propagate_error (error, _inner_error0_);
					return;
				} else {
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
					g_clear_error (&_inner_error0_);
					return;
				}
			}
			*p = (*p) + 3;
			break;
		}
		_tmp20_ = input[2];
		_tmp21_ = input[3];
		output[outpos % 4] = (guint8) (((_tmp20_ << 6) & 0xc0) | _tmp21_);
		outpos = outpos + 1;
		_tmp22_ = outpos;
		_tmp23_ = outstart;
		if ((_tmp22_ % 4) == _tmp23_) {
			geary_imap_utf7_utf16buf_to_utf8 (dest, output, (gint) 4, &outstart, 4, &_inner_error0_);
			if (G_UNLIKELY (_inner_error0_ != NULL)) {
				if (_inner_error0_->domain == G_CONVERT_ERROR) {
					g_propagate_error (error, _inner_error0_);
					return;
				} else {
					g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
					g_clear_error (&_inner_error0_);
					return;
				}
			}
		}
		*p = (*p) + 4;
	}
	if (outstart != (outpos % 4)) {
		geary_imap_utf7_utf16buf_to_utf8 (dest, output, (gint) 4, &outstart, ((4 + outpos) - outstart) % 4, &_inner_error0_);
		if (G_UNLIKELY (_inner_error0_ != NULL)) {
			if (_inner_error0_->domain == G_CONVERT_ERROR) {
				g_propagate_error (error, _inner_error0_);
				return;
			} else {
				g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
				g_clear_error (&_inner_error0_);
				return;
			}
		}
	}
	_tmp24_ = *p;
	*p = _tmp24_ + 1;
}

gchar*
geary_imap_utf7_imap_utf7_to_utf8 (const gchar* str,
                                   GError** error)
{
	gint p = 0;
	GString* dest = NULL;
	GString* _tmp5_;
	GString* _tmp6_;
	GString* _tmp17_;
	const gchar* _tmp18_;
	gchar* _tmp19_;
	GError* _inner_error0_ = NULL;
	gchar* result;
	g_return_val_if_fail (str != NULL, NULL);
	{
		gboolean _tmp0_ = FALSE;
		p = 0;
		_tmp0_ = TRUE;
		while (TRUE) {
			gboolean _tmp2_ = FALSE;
			if (!_tmp0_) {
				gint _tmp1_;
				_tmp1_ = p;
				p = _tmp1_ + 1;
			}
			_tmp0_ = FALSE;
			if (!(string_get (str, (glong) p) != '\0')) {
				break;
			}
			if (string_get (str, (glong) p) == '&') {
				_tmp2_ = TRUE;
			} else {
				_tmp2_ = ((gint) ((guint8) string_get (str, (glong) p))) >= 0x80;
			}
			if (_tmp2_) {
				break;
			}
		}
	}
	if (string_get (str, (glong) p) == '\0') {
		gchar* _tmp3_;
		_tmp3_ = g_strdup (str);
		result = _tmp3_;
		return result;
	}
	if (((gint) ((guint8) string_get (str, (glong) p))) >= 0x80) {
		GError* _tmp4_;
		_tmp4_ = g_error_new_literal (G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE, "IMAP UTF-7 input string contains 8-bit data");
		_inner_error0_ = _tmp4_;
		if (_inner_error0_->domain == G_CONVERT_ERROR) {
			g_propagate_error (error, _inner_error0_);
			return NULL;
		} else {
			g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
			g_clear_error (&_inner_error0_);
			return NULL;
		}
	}
	_tmp5_ = g_string_new ("");
	dest = _tmp5_;
	_tmp6_ = dest;
	g_string_append_len (_tmp6_, str, (gssize) p);
	while (TRUE) {
		if (!(string_get (str, (glong) p) != '\0')) {
			break;
		}
		if (string_get (str, (glong) p) == '&') {
			const gchar* _tmp7_;
			gint _tmp8_;
			_tmp7_ = str;
			p = p + 1;
			_tmp8_ = p;
			if (string_get (_tmp7_, (glong) _tmp8_) == '-') {
				GString* _tmp9_;
				gint _tmp10_;
				_tmp9_ = dest;
				g_string_append_c (_tmp9_, '&');
				_tmp10_ = p;
				p = _tmp10_ + 1;
			} else {
				GString* _tmp11_;
				gboolean _tmp12_ = FALSE;
				_tmp11_ = dest;
				geary_imap_utf7_mbase64_decode_to_utf8 (_tmp11_, str, &p, &_inner_error0_);
				if (G_UNLIKELY (_inner_error0_ != NULL)) {
					if (_inner_error0_->domain == G_CONVERT_ERROR) {
						g_propagate_error (error, _inner_error0_);
						_g_string_free0 (dest);
						return NULL;
					} else {
						_g_string_free0 (dest);
						g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
						g_clear_error (&_inner_error0_);
						return NULL;
					}
				}
				if (string_get (str, (glong) (p + 0)) == '&') {
					_tmp12_ = string_get (str, (glong) (p + 1)) != '-';
				} else {
					_tmp12_ = FALSE;
				}
				if (_tmp12_) {
					GError* _tmp13_;
					_tmp13_ = g_error_new_literal (G_CONVERT_ERROR, G_CONVERT_ERROR_ILLEGAL_SEQUENCE, "Illegal break in encoded text");
					_inner_error0_ = _tmp13_;
					if (_inner_error0_->domain == G_CONVERT_ERROR) {
						g_propagate_error (error, _inner_error0_);
						_g_string_free0 (dest);
						return NULL;
					} else {
						_g_string_free0 (dest);
						g_critical ("file %s: line %d: uncaught error: %s (%s, %d)", __FILE__, __LINE__, _inner_error0_->message, g_quark_to_string (_inner_error0_->domain), _inner_error0_->code);
						g_clear_error (&_inner_error0_);
						return NULL;
					}
				}
			}
		} else {
			GString* _tmp14_;
			const gchar* _tmp15_;
			gint _tmp16_;
			_tmp14_ = dest;
			_tmp15_ = str;
			_tmp16_ = p;
			p = _tmp16_ + 1;
			g_string_append_c (_tmp14_, string_get (_tmp15_, (glong) _tmp16_));
		}
	}
	_tmp17_ = dest;
	_tmp18_ = _tmp17_->str;
	_tmp19_ = g_strdup (_tmp18_);
	result = _tmp19_;
	_g_string_free0 (dest);
	return result;
}

