]> arthur.barton.de Git - netatalk.git/blobdiff - libatalk/unicode/charcnv.c
remove '\n' char in log messages.
[netatalk.git] / libatalk / unicode / charcnv.c
index c2782c160442b132d2ff480762c64213a3394eb5..539f9a863ee71363af1b8c604e639cee14c61179 100644 (file)
 #include <stdlib.h>
 #include <unistd.h>
 #include <string.h>
-#include <sys/param.h>
 #include <ctype.h>
-#include <sys/stat.h>
-#include <atalk/logger.h>
 #include <errno.h>
-
-#include <netatalk/endian.h>
-#include <atalk/unicode.h>
-
+#include <sys/stat.h>
+#include <sys/param.h>
 #ifdef HAVE_USABLE_ICONV
 #include <iconv.h>
 #endif
-
 #if HAVE_LOCALE_H
 #include <locale.h>
 #endif
-
 #if HAVE_LANGINFO_H
 #include <langinfo.h>
 #endif
 
+#include <netatalk/endian.h>
+#include <atalk/logger.h>
+#include <atalk/unicode.h>
+#include "byteorder.h"
+
 
 /**
  * @file
@@ -84,7 +82,7 @@ static const char *charset_name(charset_t ch)
 {
        const char *ret = NULL;
 
-       if (ch == CH_UCS2) ret = "UCS-2LE";
+       if (ch == CH_UCS2) ret = "UCS-2";
        else if (ch == CH_UNIX) ret = "LOCALE"; /*lp_unix_charset();*/
        else if (ch == CH_MAC) ret = "MAC_ROMAN"; /*lp_display_charset();*/
        else if (ch == CH_UTF8) ret = "UTF8";
@@ -104,7 +102,7 @@ static const char *charset_name(charset_t ch)
                if (ln) {
                        /* Check whether the charset name is supported
                           by iconv */
-                       atalk_iconv_t handle = atalk_iconv_open(ln,"UCS-2LE");
+                       atalk_iconv_t handle = atalk_iconv_open(ln,"UCS-2");
                        if (handle == (atalk_iconv_t) -1) {
                                LOG(log_debug, logtype_default, "Locale charset '%s' unsupported, using ASCII instead", ln);
                                ln = NULL;
@@ -114,6 +112,8 @@ static const char *charset_name(charset_t ch)
                }
                ret = ln;
        }
+#else /* system doesn't have LOCALE support */
+if (ch == CH_UNIX) ret = NULL;
 #endif
 
        if (!ret || !*ret) ret = "ASCII";
@@ -201,14 +201,6 @@ void init_iconv(void)
 {
        int c1;
 
-       /* so that charset_name() works we need to get the UNIX<->UCS2 going
-          first */
-       if (!conv_handles[CH_UNIX][CH_UCS2])
-               conv_handles[CH_UNIX][CH_UCS2] = atalk_iconv_open("UCS-2LE", "ASCII");
-
-       if (!conv_handles[CH_UCS2][CH_UNIX])
-               conv_handles[CH_UCS2][CH_UNIX] = atalk_iconv_open("ASCII", "UCS-2LE");
-
        for (c1=0;c1<NUM_CHARSETS;c1++) {
                const char *name = charset_name((charset_t)c1);
 
@@ -219,11 +211,13 @@ void init_iconv(void)
                        conv_handles[c1][CH_UCS2] = NULL;
                }
 
-               conv_handles[CH_UCS2][c1] = atalk_iconv_open( name, charset_name(CH_UCS2));
-               if (conv_handles[CH_UCS2][1] == (atalk_iconv_t)-1) {
-                       LOG(log_error, logtype_default, "Required conversion from %s to %s not supported",
-                               charset_name(CH_UCS2), name);
-                       conv_handles[c1][c1] = NULL;
+               if (c1 != CH_UCS2) { /* avoid lost memory, make valgrind happy */
+                       conv_handles[CH_UCS2][c1] = atalk_iconv_open( name, charset_name(CH_UCS2));
+                       if (conv_handles[CH_UCS2][c1] == (atalk_iconv_t)-1) {
+                               LOG(log_error, logtype_default, "Required conversion from %s to %s not supported",
+                                       charset_name(CH_UCS2), name);
+                               conv_handles[CH_UCS2][c1] = NULL;
+                       }
                }
                
                charsets[c1] = get_charset_functions (c1);
@@ -247,6 +241,7 @@ static size_t convert_string_internal(charset_t from, charset_t to,
        size_t retval;
        const char* inbuf = (const char*)src;
        char* outbuf = (char*)dest;
+       char* o_save = outbuf;
        atalk_iconv_t descriptor;
 
        if (srclen == (size_t)-1)
@@ -257,10 +252,7 @@ static size_t convert_string_internal(charset_t from, charset_t to,
        descriptor = conv_handles[from][to];
 
        if (descriptor == (atalk_iconv_t)-1 || descriptor == (atalk_iconv_t)0) {
-               /* conversion not supported, use as is */
-               size_t len = MIN(srclen,destlen);
-               memcpy(dest,src,len);
-               return len;
+               return (size_t) -1;
        }
 
        i_len=srclen;
@@ -274,28 +266,25 @@ static size_t convert_string_internal(charset_t from, charset_t to,
                                break;
                        case E2BIG:
                                reason="No more room"; 
-                               LOG(log_debug, logtype_default, "convert_string: Required %d, available %d\n",
-                                       srclen, destlen);
-                               /* we are not sure we need srclen bytes,
-                                 may be more, may be less.
-                                 We only know we need more than destlen
-                                 bytes ---simo */
                               break;
                        case EILSEQ:
                               reason="Illegal multibyte sequence";
                               break;
                }
+               LOG(log_debug, logtype_default,"Conversion error: %s",reason);
                return (size_t)-1;
-               /* smb_panic(reason); */
        }
 
        /* Terminate the string */
        if (to == CH_UCS2 && destlen-o_len >= 2) {
-               *outbuf++ = 0;
-               *outbuf++ = 0;
+               o_save[destlen-o_len]   = 0;
+               o_save[destlen-o_len+1] = 0;
+       }
+       else if ( to != CH_UCS2 && destlen-o_len > 0 )
+               o_save[destlen-o_len] = 0;
+       else {
+               /* FIXME: what should we do here, string *might* be unterminated. E2BIG? */
        }
-       else if ( destlen-o_len > 0)
-               *outbuf++ = 0;
 
        return destlen-o_len;
 }
@@ -306,15 +295,16 @@ size_t convert_string(charset_t from, charset_t to,
                      void *dest, size_t destlen)
 {
        size_t i_len, o_len;
-       char *u;
-       char buffer[MAXPATHLEN];
-       char buffer2[MAXPATHLEN];
+       ucs2_t *u;
+       ucs2_t buffer[MAXPATHLEN];
+       ucs2_t buffer2[MAXPATHLEN];
        int composition = 0;
 
        lazy_initialize_conv();
 
        /* convert from_set to UCS2 */
-       if ((size_t)(-1) == ( o_len = convert_string_internal( from, CH_UCS2, src, srclen, buffer, MAXPATHLEN)) ) {
+       if ((size_t)(-1) == ( o_len = convert_string_internal( from, CH_UCS2, src, srclen, 
+                                                               (char*) buffer, sizeof(buffer))) ) {
                LOG(log_error, logtype_default, "Conversion failed ( %s to CH_UCS2 )", charset_name(from));
                return (size_t) -1;
        }
@@ -326,7 +316,7 @@ size_t convert_string(charset_t from, charset_t to,
        if ((charsets[to] && charsets[to]->flags & CHARSET_DECOMPOSED) )
            composition = 2;
  
-       i_len = MAXPATHLEN;
+       i_len = sizeof(buffer2);
        u = buffer2;
 
        switch (composition) {
@@ -335,17 +325,17 @@ size_t convert_string(charset_t from, charset_t to,
            i_len = o_len;
            break;
        case 1:
-            if ( (size_t)-1 == (i_len = precompose_w((ucs2_t *)buffer, o_len, (ucs2_t *)u, &i_len)) )
+            if ( (size_t)-1 == (i_len = precompose_w(buffer, o_len, u, &i_len)) )
                return (size_t)(-1);
            break;
        case 2:
-            if ( (size_t)-1 == (i_len = decompose_w((ucs2_t *)buffer, o_len, (ucs2_t *)u, &i_len)) )
+            if ( (size_t)-1 == (i_len = decompose_w(buffer, o_len, u, &i_len)) )
                return (size_t)(-1);
            break;
        }
                
        /* Convert UCS2 to to_set */
-       if ((size_t)(-1) == ( o_len = convert_string_internal( CH_UCS2, to, u, i_len, dest, destlen)) ) {
+       if ((size_t)(-1) == ( o_len = convert_string_internal( CH_UCS2, to, (char*) u, i_len, dest, destlen)) ) {
                LOG(log_error, logtype_default, "Conversion failed (CH_UCS2 to %s):%s", charset_name(to), strerror(errno));
                return (size_t) -1;
        }
@@ -371,7 +361,7 @@ static size_t convert_string_allocate_internal(charset_t from, charset_t to,
        size_t i_len, o_len, destlen;
        size_t retval;
        const char *inbuf = (const char *)src;
-       char *outbuf, *ob;
+       char *outbuf = NULL, *ob = NULL;
        atalk_iconv_t descriptor;
 
        *dest = NULL;
@@ -385,22 +375,22 @@ static size_t convert_string_allocate_internal(charset_t from, charset_t to,
 
        if (descriptor == (atalk_iconv_t)-1 || descriptor == (atalk_iconv_t)0) {
                /* conversion not supported, return -1*/
-               LOG(log_debug, logtype_default, "convert_string_allocate: conversion not supported!\n");
+               LOG(log_debug, logtype_default, "convert_string_allocate: conversion not supported!");
                return -1;
        }
 
        destlen = MAX(srclen, 512);
-       outbuf = NULL;
 convert:
        destlen = destlen * 2;
-       ob = (char *)realloc(outbuf, destlen);
+       ob = (char *)realloc(ob, destlen);
        if (!ob) {
-               LOG(log_debug, logtype_default,"convert_string_allocate: realloc failed!\n");
+               LOG(log_debug, logtype_default,"convert_string_allocate: realloc failed!");
                SAFE_FREE(outbuf);
                return (size_t)-1;
        } else {
                outbuf = ob;
        }
+       inbuf = src;   /* this restarts the whole conversion if buffer needed to be increased */
        i_len = srclen;
        o_len = destlen;
        retval = atalk_iconv(descriptor,
@@ -418,8 +408,7 @@ convert:
                                reason="Illegal multibyte sequence";
                                break;
                }
-               LOG(log_debug, logtype_default,"Conversion error: %s(%s)\n",reason,inbuf);
-               /* smb_panic(reason); */
+               LOG(log_debug, logtype_default,"Conversion error: %s(%s)",reason,inbuf);
                return (size_t)-1;
        }
 
@@ -427,19 +416,21 @@ convert:
        destlen = destlen - o_len;
 
        /* Terminate the string */
-       if (to == CH_UCS2 && destlen-o_len >= 2) {
-               *outbuf++ = 0;
-               *outbuf++ = 0;
+       if (to == CH_UCS2 && o_len >= 2) {
+               ob[destlen] = 0;
+               ob[destlen+1] = 0;
                *dest = (char *)realloc(ob,destlen+2);
        }
-       else if ( destlen-o_len > 0) {
-               *outbuf++ = 0;
+       else if ( to != CH_UCS2 && o_len > 0 ) {
+               ob[destlen] = 0;
                *dest = (char *)realloc(ob,destlen+1);
        }
+       else {
+               goto convert; /* realloc */
+       }
 
-       //*dest = (char *)realloc(ob,destlen);
        if (destlen && !*dest) {
-               LOG(log_debug, logtype_default, "convert_string_allocate: out of memory!\n");
+               LOG(log_debug, logtype_default, "convert_string_allocate: out of memory!");
                SAFE_FREE(ob);
                return (size_t)-1;
        }
@@ -453,15 +444,18 @@ size_t convert_string_allocate(charset_t from, charset_t to,
                      char ** dest)
 {
        size_t i_len, o_len;
-       char *u;
-       char buffer[MAXPATHLEN];
-       char buffer2[MAXPATHLEN];
+       ucs2_t *u;
+       ucs2_t buffer[MAXPATHLEN];
+       ucs2_t buffer2[MAXPATHLEN];
        int composition = 0;
 
        lazy_initialize_conv();
 
+       *dest = NULL;
+
        /* convert from_set to UCS2 */
-       if ((size_t)(-1) == ( o_len = convert_string_internal( from, CH_UCS2, src, srclen, buffer, MAXPATHLEN)) ) {
+       if ((size_t)(-1) == ( o_len = convert_string_internal( from, CH_UCS2, src, srclen, 
+                                                               buffer, sizeof(buffer))) ) {
                LOG(log_error, logtype_default, "Conversion failed ( %s to CH_UCS2 )", charset_name(from));
                return (size_t) -1;
        }
@@ -473,7 +467,7 @@ size_t convert_string_allocate(charset_t from, charset_t to,
        if ((charsets[to] && charsets[to]->flags & CHARSET_DECOMPOSED) )
            composition = 2;
  
-       i_len = MAXPATHLEN;
+       i_len = sizeof(buffer2);
        u = buffer2;
 
        switch (composition) {
@@ -482,17 +476,17 @@ size_t convert_string_allocate(charset_t from, charset_t to,
            i_len = o_len;
            break;
        case 1:
-            if ( (size_t)-1 == (i_len = precompose_w((ucs2_t *)buffer, o_len, (ucs2_t *)u, &i_len)) )
+            if ( (size_t)-1 == (i_len = precompose_w(buffer, o_len, u, &i_len)) )
                return (size_t)(-1);
            break;
        case 2:
-            if ( (size_t)-1 == (i_len = decompose_w((ucs2_t *)buffer, o_len, (ucs2_t *)u, &i_len)) )
+            if ( (size_t)-1 == (i_len = decompose_w(buffer, o_len, u, &i_len)) )
                return (size_t)(-1);
            break;
        }
                
        /* Convert UCS2 to to_set */
-       if ((size_t)(-1) == ( o_len = convert_string_allocate_internal( CH_UCS2, to, u, i_len, dest)) ) 
+       if ((size_t)(-1) == ( o_len = convert_string_allocate_internal( CH_UCS2, to, (char*)u, i_len, dest)) ) 
                LOG(log_error, logtype_default, "Conversion failed (CH_UCS2 to %s):%s", charset_name(to), strerror(errno));
                
        return o_len;
@@ -507,7 +501,7 @@ size_t charset_strupper(charset_t ch, const char *src, size_t srclen, char *dest
        size = convert_string_allocate_internal(ch, CH_UCS2, src, srclen,
                                       (char**) &buffer);
        if (size == (size_t)-1) {
-               free(buffer);
+               SAFE_FREE(buffer);
                return size;
        }
        if (!strupper_w((ucs2_t *)buffer) && (dest == src)) {
@@ -528,7 +522,7 @@ size_t charset_strlower(charset_t ch, const char *src, size_t srclen, char *dest
        size = convert_string_allocate_internal(ch, CH_UCS2, src, srclen,
                                       (char **) &buffer);
        if (size == (size_t)-1) {
-               free(buffer);
+               SAFE_FREE(buffer);
                return size;
        }
        if (!strlower_w((ucs2_t *)buffer) && (dest == src)) {
@@ -573,7 +567,7 @@ size_t utf8_strlower(const char *src, size_t srclen, char *dest, size_t destlen)
 
 size_t charset_to_ucs2_allocate(charset_t ch, ucs2_t **dest, const char *src)
 {
-       size_t src_len = strlen(src)+1;
+       size_t src_len = strlen(src);
 
        *dest = NULL;
        return convert_string_allocate(ch, CH_UCS2, src, src_len, (char**) dest);       
@@ -589,7 +583,7 @@ size_t charset_to_ucs2_allocate(charset_t ch, ucs2_t **dest, const char *src)
 
 size_t charset_to_utf8_allocate(charset_t ch, char **dest, const char *src)
 {
-       size_t src_len = strlen(src)+1;
+       size_t src_len = strlen(src);
 
        *dest = NULL;
        return convert_string_allocate(ch, CH_UTF8, src, src_len, dest);        
@@ -603,9 +597,16 @@ size_t charset_to_utf8_allocate(charset_t ch, char **dest, const char *src)
  * @returns The number of bytes occupied by the string in the destination
  **/
 
+size_t ucs2_to_charset(charset_t ch, const ucs2_t *src, char *dest, size_t destlen)
+{
+       size_t src_len = (strlen_w(src)) * sizeof(ucs2_t);
+       return convert_string(CH_UCS2, ch, src, src_len, dest, destlen);        
+}
+
+
 size_t ucs2_to_charset_allocate(charset_t ch, char **dest, const ucs2_t *src)
 {
-       size_t src_len = (strlen_w(src)+1) * sizeof(ucs2_t);
+       size_t src_len = (strlen_w(src)) * sizeof(ucs2_t);
        *dest = NULL;
        return convert_string_allocate(CH_UCS2, ch, src, src_len, dest);        
 }
@@ -628,21 +629,21 @@ size_t utf8_to_charset_allocate(charset_t ch, char **dest, const char *src)
 size_t charset_precompose ( charset_t ch, char * src, size_t inlen, char * dst, size_t outlen)
 {
        char *buffer;
-       char u[MAXPATHLEN];
+       ucs2_t u[MAXPATHLEN];
        size_t len;
        size_t ilen;
 
         if ((size_t)(-1) == (len = convert_string_allocate_internal(ch, CH_UCS2, src, inlen, &buffer)) )
             return len;
 
-       ilen=MAXPATHLEN;
+       ilen=sizeof(u);
 
-       if ( (size_t)-1 == (ilen = precompose_w((ucs2_t *)buffer, len, (ucs2_t *)u, &ilen)) ) {
+       if ( (size_t)-1 == (ilen = precompose_w((ucs2_t *)buffer, len, u, &ilen)) ) {
            free (buffer);
            return (size_t)(-1);
        }
 
-        if ((size_t)(-1) == (len = convert_string_internal( CH_UCS2, ch, u, ilen, dst, outlen)) ) {
+        if ((size_t)(-1) == (len = convert_string_internal( CH_UCS2, ch, (char*)u, ilen, dst, outlen)) ) {
            free (buffer);
            return (size_t)(-1);
        }
@@ -655,21 +656,21 @@ size_t charset_precompose ( charset_t ch, char * src, size_t inlen, char * dst,
 size_t charset_decompose ( charset_t ch, char * src, size_t inlen, char * dst, size_t outlen)
 {
        char *buffer;
-       char u[MAXPATHLEN];
+       ucs2_t u[MAXPATHLEN];
        size_t len;
        size_t ilen;
 
         if ((size_t)(-1) == (len = convert_string_allocate_internal(ch, CH_UCS2, src, inlen, &buffer)) )
             return len;
 
-       ilen=MAXPATHLEN;
+       ilen=sizeof(u);
 
-       if ( (size_t)-1 == (ilen = decompose_w((ucs2_t *)buffer, len, (ucs2_t *)u, &ilen)) ) {
+       if ( (size_t)-1 == (ilen = decompose_w((ucs2_t *)buffer, len, u, &ilen)) ) {
            free (buffer);
            return (size_t)(-1);
        }
 
-        if ((size_t)(-1) == (len = convert_string_internal( CH_UCS2, ch, u, ilen, dst, outlen)) ) {
+        if ((size_t)(-1) == (len = convert_string_internal( CH_UCS2, ch, (char*)u, ilen, dst, outlen)) ) {
            free (buffer);
            return (size_t)(-1);
        }
@@ -713,8 +714,8 @@ char * debug_out ( char * seq, size_t len)
 /* 
  * Convert from MB to UCS2 charset 
  * Flags:
- *             CONV_UNESCAPEHEX:        ':XXXX' will be converted to an UCS2 character
- *             CONV_IGNORE:            unconvertable characters will be replaced with '_'
+ *             CONV_UNESCAPEHEX:        ':XX' will be converted to an UCS2 character
+ *             CONV_IGNORE:             return the first convertable characters.
  * FIXME:
  *             This will *not* work if the destination charset is not multibyte, i.e. UCS2->UCS2 will fail
  *             The (un)escape scheme is not compatible to the old cap style escape. This is bad, we need it 
@@ -760,19 +761,9 @@ conversion_loop:
        
        retval = atalk_iconv(descriptor,  &inbuf, &i_len, &outbuf, &o_len);
        if(retval==(size_t)-1) {
-               if (errno == EILSEQ && flags && (*flags & CONV_IGNORE)) {
-                               if (o_len < 2) {
-                                       errno = E2BIG;
-                                       return (size_t) -1;
-                               }
-                               o_save[destlen-o_len]   = '_';
-                               o_save[destlen-o_len+1] = 0x0;
-                               o_len -= 2;
-                               outbuf = o_save + destlen - o_len;
-                               inbuf += 1;
-                               i_len -= 1;
+           if (errno == EILSEQ && flags && (*flags & CONV_IGNORE)) {
                                *flags |= CONV_REQMANGLE;
-                               goto conversion_loop;
+                               return destlen-o_len;
            }
            else
                return (size_t) -1;
@@ -800,17 +791,8 @@ unhex_char:
                        h_buf = (const char*) h;
                        if ((size_t) -1 == (retval = atalk_iconv(descriptor_cap, &h_buf, &hlen, &outbuf, &o_len)) ) {
                                if (errno == EILSEQ && CHECK_FLAGS(flags, CONV_IGNORE)) {
-                                       if (o_len < hlen) {
-                                               errno = E2BIG;
-                                               return retval;
-                                       }
-                                       while ( hlen > 0) {
-                                               *outbuf++ = '_';
-                                               *outbuf++ = 0;
-                                               o_len -= 2;
-                                               hlen -= 1;
-                                               *flags |= CONV_REQMANGLE;
-                                       }
+                                       *flags |= CONV_REQMANGLE;
+                                       return destlen-o_len;
                                }
                                else {
                                        return retval;
@@ -820,12 +802,8 @@ unhex_char:
                else {
                        /* We have an invalid :xx sequence */
                        if (CHECK_FLAGS(flags, CONV_IGNORE)) {
-                               *outbuf++ = '_';
-                               *outbuf++ = 0;
-                               inbuf++;
-                               o_len -= 2;
-                               j -= 1;
                                *flags |= CONV_REQMANGLE;
+                               return destlen-o_len;
                        }
                        else {
                                errno=EILSEQ;
@@ -838,6 +816,8 @@ unhex_char:
                        goto conversion_loop;
        }
 
+
+
        return destlen-o_len;
 }
 
@@ -845,7 +825,7 @@ unhex_char:
  * Convert from UCS2 to MB charset 
  * Flags:
  *             CONV_ESCAPEDOTS: escape leading dots
- *             CONV_ESCAPEHEX:  unconvertable characters and '/' will be escaped to :XXXX
+ *             CONV_ESCAPEHEX:  unconvertable characters and '/' will be escaped to :XX
  *             CONV_IGNORE:     unconvertable characters will be replaced with '_'
  * FIXME:
  *             CONV_IGNORE and CONV_ESCAPEHEX can't work together. Should we check this ?
@@ -878,7 +858,7 @@ static size_t push_charset_flags (charset_t to_set, charset_t cap_set, char* src
     o_len=destlen;
     o_save=outbuf;
     
-    if (*inbuf == '.' && flags && (*flags & CONV_ESCAPEDOTS)) {
+    if ( SVAL(inbuf,0) == 0x002e && flags && (*flags & CONV_ESCAPEDOTS)) { /* 0x002e = . */
         if (o_len < 3) {
             errno = E2BIG;
             return (size_t) -1;
@@ -896,31 +876,23 @@ static size_t push_charset_flags (charset_t to_set, charset_t cap_set, char* src
 conversion_loop:
     if ( flags && (*flags & CONV_ESCAPEHEX)) {
         for ( i = 0; i < i_len; i+=2) {
-            if ( inbuf[i] == '/' ) {
+            if ( SVAL((inbuf+i),0) == 0x002f) { /* 0x002f = / */
                 j = i_len - i;
                 if ( 0 == ( i_len = i))
                     goto escape_slash;
                 break;
-            }
+            } else if ( SVAL(inbuf+i,0) == 0x003a) { /* 0x003a = : */
+               errno = EILSEQ;
+               return (size_t) -1;
+           }
         }
     }
     
     retval = atalk_iconv(descriptor,  &inbuf, &i_len, &outbuf, &o_len);
     if (retval==(size_t)-1) {
-        if (errno == EILSEQ && flags && (*flags & CONV_IGNORE)) {
-            if (o_len == 0) {
-                errno = E2BIG;
-                return (size_t) -1;
-            }
-            o_save[destlen-o_len] = '_';
-            o_len -=1;
-            outbuf = o_save + destlen - o_len;
-            inbuf += 2;
-            i_len -= 2;
-            if (flags ) 
-                *flags |= CONV_REQMANGLE;
-           if (i_len)
-                goto conversion_loop;
+        if (errno == EILSEQ && CHECK_FLAGS(flags, CONV_IGNORE)) {
+            *flags |= CONV_REQMANGLE;
+           return destlen -o_len;
         }
         else if ( errno == EILSEQ && flags && (*flags & CONV_ESCAPEHEX)) {
             if (o_len < 3) {
@@ -945,6 +917,7 @@ conversion_loop:
            SAFE_FREE(buf_save);
            buflen = 0;
            i_len -= 2;
+           inbuf += 2;
             if (flags) *flags |= CONV_REQESCAPE;
            if ( i_len > 0)
                goto conversion_loop;
@@ -976,19 +949,23 @@ escape_slash:
 size_t convert_charset ( charset_t from_set, charset_t to_set, charset_t cap_charset, char* src, size_t src_len, char* dest, size_t dest_len, u_int16_t *flags)
 {
        size_t i_len, o_len;
-       char *u;
-       char buffer[MAXPATHLEN];
-       char buffer2[MAXPATHLEN];
+       ucs2_t *u;
+       ucs2_t buffer[MAXPATHLEN];
+       ucs2_t buffer2[MAXPATHLEN];
        int composition = 0;
        
        lazy_initialize_conv();
 
        /* convert from_set to UCS2 */
-       if ((size_t)(-1) == ( o_len = pull_charset_flags( from_set, cap_charset, src, src_len, buffer, MAXPATHLEN, flags)) ) {
+       if ((size_t)(-1) == ( o_len = pull_charset_flags( from_set, cap_charset, src, src_len, 
+                                                          (char *) buffer, sizeof(buffer), flags)) ) {
                LOG(log_error, logtype_default, "Conversion failed ( %s to CH_UCS2 )", charset_name(from_set));
                return (size_t) -1;
        }
 
+       if ( o_len == 0)
+               return o_len;
+
        /* Do pre/decomposition */
        if (CHECK_FLAGS(flags, CONV_PRECOMPOSE) || 
                ((!(charsets[to_set])   || !(charsets[to_set]->flags & CHARSET_DECOMPOSED)) && 
@@ -997,7 +974,7 @@ size_t convert_charset ( charset_t from_set, charset_t to_set, charset_t cap_cha
        if (CHECK_FLAGS(flags, CONV_DECOMPOSE) || (charsets[to_set] && charsets[to_set]->flags & CHARSET_DECOMPOSED) )
            composition = 2;
  
-       i_len = MAXPATHLEN;
+       i_len = sizeof(buffer2);
        u = buffer2;
 
        switch (composition) {
@@ -1006,27 +983,25 @@ size_t convert_charset ( charset_t from_set, charset_t to_set, charset_t cap_cha
            i_len = o_len;
            break;
        case 1:
-            if ( (size_t)-1 == (i_len = precompose_w((ucs2_t *)buffer, o_len, (ucs2_t *)u, &i_len)) )
+            if ( (size_t)-1 == (i_len = precompose_w(buffer, o_len, u, &i_len)) )
                return (size_t)(-1);
            break;
        case 2:
-            if ( (size_t)-1 == (i_len = decompose_w((ucs2_t *)buffer, o_len, (ucs2_t *)u, &i_len)) )
+            if ( (size_t)-1 == (i_len = decompose_w(buffer, o_len, u, &i_len)) )
                return (size_t)(-1);
            break;
        }
                
        /* Do case conversions */       
        if (CHECK_FLAGS(flags, CONV_TOUPPER)) {
-           if (!strupper_w((ucs2_t *) u)) 
-               return (size_t)(-1);
+           strupper_w(u);
        }
        if (CHECK_FLAGS(flags, CONV_TOLOWER)) {
-           if (!strlower_w((ucs2_t *) u)) 
-               return (size_t)(-1);
+           strlower_w(u);
        }
 
        /* Convert UCS2 to to_set */
-       if ((size_t)(-1) == ( o_len = push_charset_flags( to_set, cap_charset, u, i_len, dest, dest_len, flags )) ) {
+       if ((size_t)(-1) == ( o_len = push_charset_flags( to_set, cap_charset, (char *)u, i_len, dest, dest_len, flags )) ) {
                LOG(log_error, logtype_default, 
                       "Conversion failed (CH_UCS2 to %s):%s", charset_name(to_set), strerror(errno));
                return (size_t) -1;