+ gchar *p;
+ gboolean in_escape = FALSE;
+
+ if (!separator || separator == '/') return;
+
+ for (p = str; *p != '\0'; p++) {
+ if (*p == '/' && !in_escape)
+ *p = separator;
+ else if (*p == '&' && *(p + 1) != '-' && !in_escape)
+ in_escape = TRUE;
+ else if (*p == '-' && in_escape)
+ in_escape = FALSE;
+ }
+}
+
+static gchar *imap_modified_utf7_to_locale(const gchar *mutf7_str)
+{
+#if !HAVE_LIBJCONV
+ return g_strdup(mutf7_str);
+#else
+ static iconv_t cd = (iconv_t)-1;
+ static gboolean iconv_ok = TRUE;
+ GString *norm_utf7;
+ gchar *norm_utf7_p;
+ size_t norm_utf7_len;
+ const gchar *p;
+ gchar *to_str, *to_p;
+ size_t to_len;
+ gboolean in_escape = FALSE;
+
+ if (!iconv_ok) return g_strdup(mutf7_str);
+
+ if (cd == (iconv_t)-1) {
+ cd = iconv_open(conv_get_current_charset_str(), "UTF-7");
+ if (cd == (iconv_t)-1) {
+ g_warning(_("iconv cannot convert UTF-7 to %s\n"),
+ conv_get_current_charset_str());
+ iconv_ok = FALSE;
+ return g_strdup(mutf7_str);
+ }
+ }
+
+ norm_utf7 = g_string_new(NULL);
+
+ for (p = mutf7_str; *p != '\0'; p++) {
+ /* replace: '&' -> '+',
+ "&-" -> '&',
+ escaped ',' -> '/' */
+ if (!in_escape && *p == '&') {
+ if (*(p + 1) != '-') {
+ g_string_append_c(norm_utf7, '+');
+ in_escape = TRUE;
+ } else {
+ g_string_append_c(norm_utf7, '&');
+ p++;
+ }
+ } else if (in_escape && *p == ',') {
+ g_string_append_c(norm_utf7, '/');
+ } else if (in_escape && *p == '-') {
+ g_string_append_c(norm_utf7, '-');
+ in_escape = FALSE;
+ } else {
+ g_string_append_c(norm_utf7, *p);
+ }
+ }
+
+ norm_utf7_p = norm_utf7->str;
+ norm_utf7_len = norm_utf7->len;
+ to_len = strlen(mutf7_str) * 5;
+ to_p = to_str = g_malloc(to_len + 1);
+
+ if (iconv(cd, &norm_utf7_p, &norm_utf7_len, &to_p, &to_len) == -1) {
+ g_warning(_("iconv cannot convert UTF-7 to %s\n"),
+ conv_get_current_charset_str());
+ g_string_free(norm_utf7, TRUE);
+ g_free(to_str);
+ return g_strdup(mutf7_str);
+ }
+
+ /* second iconv() call for flushing */
+ iconv(cd, NULL, NULL, &to_p, &to_len);
+ g_string_free(norm_utf7, TRUE);
+ *to_p = '\0';
+
+ return to_str;
+#endif /* !HAVE_LIBJCONV */
+}
+
+static gchar *imap_locale_to_modified_utf7(const gchar *from)
+{
+#if !HAVE_LIBJCONV
+ return g_strdup(from);
+#else
+ static iconv_t cd = (iconv_t)-1;
+ static gboolean iconv_ok = TRUE;
+ gchar *norm_utf7, *norm_utf7_p;
+ size_t from_len, norm_utf7_len;
+ GString *to_str;
+ gchar *from_tmp, *to, *p;
+ gboolean in_escape = FALSE;
+
+ if (!iconv_ok) return g_strdup(from);
+
+ if (cd == (iconv_t)-1) {
+ cd = iconv_open("UTF-7", conv_get_current_charset_str());
+ if (cd == (iconv_t)-1) {
+ g_warning(_("iconv cannot convert %s to UTF-7\n"),
+ conv_get_current_charset_str());
+ iconv_ok = FALSE;
+ return g_strdup(from);
+ }
+ }
+
+ Xstrdup_a(from_tmp, from, return g_strdup(from));
+ from_len = strlen(from);
+ norm_utf7_len = from_len * 5;
+ Xalloca(norm_utf7, norm_utf7_len + 1, return g_strdup(from));
+ norm_utf7_p = norm_utf7;
+
+#define IS_PRINT(ch) (isprint(ch) && isascii(ch))
+
+ while (from_len > 0) {
+ if (IS_PRINT(*from_tmp)) {
+ /* printable ascii char */
+ *norm_utf7_p = *from_tmp;
+ norm_utf7_p++;
+ from_tmp++;
+ from_len--;
+ } else {
+ size_t mblen;
+
+ /* unprintable char: convert to UTF-7 */
+ for (mblen = 0;
+ !IS_PRINT(from_tmp[mblen]) && mblen < from_len;
+ mblen++)
+ ;
+ from_len -= mblen;
+ if (iconv(cd, &from_tmp, &mblen,
+ &norm_utf7_p, &norm_utf7_len) == -1) {
+ g_warning(_("iconv cannot convert %s to UTF-7\n"),
+ conv_get_current_charset_str());
+ return g_strdup(from);
+ }
+
+ /* second iconv() call for flushing */
+ iconv(cd, NULL, NULL, &norm_utf7_p, &norm_utf7_len);
+ }
+ }
+
+#undef IS_PRINT
+
+ *norm_utf7_p = '\0';
+ to_str = g_string_new(NULL);
+ for (p = norm_utf7; p < norm_utf7_p; p++) {
+ /* replace: '&' -> "&-",
+ '+' -> '&',
+ escaped '/' -> ',' */
+ if (!in_escape && *p == '&') {
+ g_string_append(to_str, "&-");
+ } else if (!in_escape && *p == '+') {
+ g_string_append_c(to_str, '&');
+ in_escape = TRUE;
+ } else if (in_escape && *p == '/') {
+ g_string_append_c(to_str, ',');
+ } else if (in_escape && *p == '-') {
+ in_escape = FALSE;
+ g_string_append_c(to_str, '-');
+ } else {
+ g_string_append_c(to_str, *p);
+ }
+ }
+
+ if (in_escape) {
+ in_escape = FALSE;
+ g_string_append_c(to_str, '-');
+ }
+
+ to = to_str->str;
+ g_string_free(to_str, FALSE);
+
+ return to;
+#endif