예제 #1
0
/**
 * Initialize iconv conversion descriptors.
 *
 * This is called the first time it is needed, and also called again
 * every time the configuration is reloaded, because the charset or
 * codepage might have changed.
 **/
void init_iconv(void)
{
    int c1;

    for (c1=0;c1<NUM_CHARSETS;c1++) {
        const char *name = charset_name((charset_t)c1);

        conv_handles[c1][CH_UCS2] = atalk_iconv_open( charset_name(CH_UCS2), name);
        if (conv_handles[c1][CH_UCS2] == (atalk_iconv_t)-1) {
            LOG(log_error, logtype_default, "Required conversion from %s to %s not supported",
                name,  charset_name(CH_UCS2));
            conv_handles[c1][CH_UCS2] = 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);
    }
}
예제 #2
0
/*
 * FIXME the size is a mess we really need a malloc/free logic
 *`dest size must be dest_len +2
 */
size_t convert_charset ( charset_t from_set, charset_t to_set, charset_t cap_charset, const char *src, size_t src_len, char *dest, size_t dest_len, uint16_t *flags)
{
    size_t i_len, o_len;
    ucs2_t *u;
    ucs2_t buffer[MAXPATHLEN +2];
    ucs2_t buffer2[MAXPATHLEN +2];

    lazy_initialize_conv();

    /* convert from_set to UCS2 */
    if ((size_t)(-1) == ( o_len = pull_charset_flags( from_set, to_set, cap_charset, src, src_len,
                                                      (char *) buffer, sizeof(buffer) -2, 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 */
    i_len = sizeof(buffer2) -2;
    u = buffer2;
    if (CHECK_FLAGS(flags, CONV_DECOMPOSE) || (charsets[to_set] && (charsets[to_set]->flags & CHARSET_DECOMPOSED)) ) {
        if ( (size_t)-1 == (i_len = decompose_w(buffer, o_len, u, &i_len)) )
            return (size_t)(-1);
    }
    else if (CHECK_FLAGS(flags, CONV_PRECOMPOSE) || !charsets[from_set] || (charsets[from_set]->flags & CHARSET_DECOMPOSED)) {
        if ( (size_t)-1 == (i_len = precompose_w(buffer, o_len, u, &i_len)) )
            return (size_t)(-1);
    }
    else {
        u = buffer;
        i_len = o_len;
    }
    /* null terminate */
    u[i_len] = 0;
    u[i_len +1] = 0;

    /* Do case conversions */
    if (CHECK_FLAGS(flags, CONV_TOUPPER)) {
        strupper_w(u);
    }
    else if (CHECK_FLAGS(flags, CONV_TOLOWER)) {
        strlower_w(u);
    }

    /* Convert UCS2 to to_set */
    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;
    }
    /* null terminate */
    dest[o_len] = 0;
    dest[o_len +1] = 0;

    return o_len;
}
예제 #3
0
charset_t add_charset(const char* name)
{
    static charset_t max_charset_t = NUM_CHARSETS-1;
    charset_t cur_charset_t = max_charset_t+1;
    unsigned int c1;

    lazy_initialize_conv();

    for (c1=0; c1<=max_charset_t;c1++) {
        if ( strcasecmp(name, charset_name(c1)) == 0)
            return (c1);
    }

    if ( cur_charset_t >= MAX_CHARSETS )  {
        LOG (log_debug, logtype_default, "Adding charset %s failed, too many charsets (max. %u allowed)",
             name, MAX_CHARSETS);
        return (charset_t) -1;
    }

    /* First try to setup the required conversions */

    conv_handles[cur_charset_t][CH_UCS2] = atalk_iconv_open( charset_name(CH_UCS2), name);
    if (conv_handles[cur_charset_t][CH_UCS2] == (atalk_iconv_t)-1) {
        LOG(log_error, logtype_default, "Required conversion from %s to %s not supported",
            name,  charset_name(CH_UCS2));
        conv_handles[cur_charset_t][CH_UCS2] = NULL;
        return (charset_t) -1;
    }

    conv_handles[CH_UCS2][cur_charset_t] = atalk_iconv_open( name, charset_name(CH_UCS2));
    if (conv_handles[CH_UCS2][cur_charset_t] == (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][cur_charset_t] = NULL;
        return (charset_t) -1;
    }

    /* register the new charset_t name */
    charset_names[cur_charset_t] = strdup(name);

    charsets[cur_charset_t] = get_charset_functions (cur_charset_t);
    max_charset_t++;

#ifdef DEBUG
    LOG(log_debug9, logtype_default, "Added charset %s with handle %u", name, cur_charset_t);
#endif
    return (cur_charset_t);
}
예제 #4
0
static struct charset_functions* get_charset_functions (charset_t ch)
{
    if (charsets[ch] != NULL)
        return charsets[ch];

    charsets[ch] = find_charset_functions(charset_name(ch));

    return charsets[ch];
}
예제 #5
0
size_t convert_string_allocate(charset_t from, charset_t to,
                               void const *src, size_t srclen,
                               char ** dest)
{
    size_t i_len, o_len;
    ucs2_t *u;
    ucs2_t buffer[MAXPATHLEN];
    ucs2_t buffer2[MAXPATHLEN];

    *dest = NULL;

    /* convert from_set to UCS2 */
    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;
    }

    /* Do pre/decomposition */
    i_len = sizeof(buffer2);
    u = buffer2;
    if (charsets[to] && (charsets[to]->flags & CHARSET_DECOMPOSED) ) {
        if ( (size_t)-1 == (i_len = decompose_w(buffer, o_len, u, &i_len)) )
            return (size_t)-1;
    }
    else if ( !charsets[from] || (charsets[from]->flags & CHARSET_DECOMPOSED) ) {
        if ( (size_t)-1 == (i_len = precompose_w(buffer, o_len, u, &i_len)) )
            return (size_t)-1;
    }
    else {
        u = buffer;
        i_len = o_len;
    }

    /* Convert UCS2 to to_set */
    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;

}
예제 #6
0
파일: charcnv.c 프로젝트: AllardJ/Tomato
/**
 * Initialize iconv conversion descriptors.
 *
 * This is called the first time it is needed, and also called again
 * every time the configuration is reloaded, because the charset or
 * codepage might have changed.
 **/
void init_iconv(void)
{
	int c1, c2;
	BOOL did_reload = False;

	/* so that charset_name() works we need to get the UNIX<->UCS2 going
	   first */
	if (!conv_handles[CH_UNIX][CH_UTF16LE])
		conv_handles[CH_UNIX][CH_UTF16LE] = smb_iconv_open(charset_name(CH_UTF16LE), "ASCII");

	if (!conv_handles[CH_UTF16LE][CH_UNIX])
		conv_handles[CH_UTF16LE][CH_UNIX] = smb_iconv_open("ASCII", charset_name(CH_UTF16LE));

	for (c1=0;c1<NUM_CHARSETS;c1++) {
		for (c2=0;c2<NUM_CHARSETS;c2++) {
			const char *n1 = charset_name((charset_t)c1);
			const char *n2 = charset_name((charset_t)c2);
			if (conv_handles[c1][c2] &&
			    strcmp(n1, conv_handles[c1][c2]->from_name) == 0 &&
			    strcmp(n2, conv_handles[c1][c2]->to_name) == 0)
				continue;

			did_reload = True;

			if (conv_handles[c1][c2])
				smb_iconv_close(conv_handles[c1][c2]);

			conv_handles[c1][c2] = smb_iconv_open(n2,n1);
			if (conv_handles[c1][c2] == (smb_iconv_t)-1) {
				DEBUG(0,("init_iconv: Conversion from %s to %s not supported\n",
					 charset_name((charset_t)c1), charset_name((charset_t)c2)));
				if (c1 != CH_UTF16LE && c1 != CH_UTF16BE) {
					n1 = "ASCII";
				}
				if (c2 != CH_UTF16LE && c2 != CH_UTF16BE) {
					n2 = "ASCII";
				}
				DEBUG(0,("init_iconv: Attempting to replace with conversion from %s to %s\n",
					n1, n2 ));
				conv_handles[c1][c2] = smb_iconv_open(n2,n1);
				if (!conv_handles[c1][c2]) {
					DEBUG(0,("init_iconv: Conversion from %s to %s failed", n1, n2));
					smb_panic("init_iconv: conv_handle initialization failed.");
				}
			}
		}
	}

	if (did_reload) {
		/* XXX: Does this really get called every time the dos
		 * codepage changes? */
		/* XXX: Is the did_reload test too strict? */
		conv_silent = True;
		init_doschar_table();
		init_valid_table();
		conv_silent = False;
	}
}
예제 #7
0
파일: charcnv.c 프로젝트: AllardJ/Tomato
static size_t convert_string_internal(charset_t from, charset_t to,
		      void const *src, size_t srclen, 
		      void *dest, size_t destlen, BOOL allow_bad_conv)
{
	size_t i_len, o_len;
	size_t retval;
	const char* inbuf = (const char*)src;
	char* outbuf = (char*)dest;
	smb_iconv_t descriptor;

	lazy_initialize_conv();

	descriptor = conv_handles[from][to];

	if (srclen == (size_t)-1) {
		if (from == CH_UTF16LE || from == CH_UTF16BE) {
			srclen = (strlen_w((const smb_ucs2_t *)src)+1) * 2;
		} else {
			srclen = strlen((const char *)src)+1;
		}
	}


	if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
		if (!conv_silent)
			DEBUG(0,("convert_string_internal: Conversion not supported.\n"));
		return (size_t)-1;
	}

	i_len=srclen;
	o_len=destlen;

 again:

	retval = smb_iconv(descriptor, &inbuf, &i_len, &outbuf, &o_len);
	if(retval==(size_t)-1) {
	    	const char *reason="unknown error";
		switch(errno) {
			case EINVAL:
				reason="Incomplete multibyte sequence";
				if (!conv_silent)
					DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
				if (allow_bad_conv)
					goto use_as_is;
				break;
			case E2BIG:
				reason="No more room"; 
				if (!conv_silent) {
					if (from == CH_UNIX) {
						DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u - '%s'\n",
							charset_name(from), charset_name(to),
							(unsigned int)srclen, (unsigned int)destlen, (const char *)src));
					} else {
						DEBUG(3,("E2BIG: convert_string(%s,%s): srclen=%u destlen=%u\n",
							charset_name(from), charset_name(to),
							(unsigned int)srclen, (unsigned int)destlen));
					}
				}
				break;
			case EILSEQ:
				reason="Illegal multibyte sequence";
				if (!conv_silent)
					DEBUG(3,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
				if (allow_bad_conv)
					goto use_as_is;
				break;
			default:
				if (!conv_silent)
					DEBUG(0,("convert_string_internal: Conversion error: %s(%s)\n",reason,inbuf));
				break;
		}
		/* smb_panic(reason); */
	}
	return destlen-o_len;

 use_as_is:

	/* 
	 * Conversion not supported. This is actually an error, but there are so
	 * many misconfigured iconv systems and smb.conf's out there we can't just
	 * fail. Do a very bad conversion instead.... JRA.
	 */

	{
		if (o_len == 0 || i_len == 0)
			return destlen - o_len;

		if (((from == CH_UTF16LE)||(from == CH_UTF16BE)) &&
				((to != CH_UTF16LE)||(to != CH_UTF16BE))) {
			/* Can't convert from utf16 any endian to multibyte.
			   Replace with the default fail char.
			*/
			if (i_len < 2)
				return destlen - o_len;
			if (i_len >= 2) {
				*outbuf = lp_failed_convert_char();

				outbuf++;
				o_len--;

				inbuf += 2;
				i_len -= 2;
			}

			if (o_len == 0 || i_len == 0)
				return destlen - o_len;

			/* Keep trying with the next char... */
			goto again;

		} else if (from != CH_UTF16LE && from != CH_UTF16BE && to == CH_UTF16LE) {
			/* Can't convert to UTF16LE - just widen by adding the
			   default fail char then zero.
			*/
			if (o_len < 2)
				return destlen - o_len;

			outbuf[0] = lp_failed_convert_char();
			outbuf[1] = '\0';

			inbuf++;
			i_len--;

			outbuf += 2;
			o_len -= 2;

			if (o_len == 0 || i_len == 0)
				return destlen - o_len;

			/* Keep trying with the next char... */
			goto again;

		} else if (from != CH_UTF16LE && from != CH_UTF16BE &&
				to != CH_UTF16LE && to != CH_UTF16BE) {
			/* Failed multibyte to multibyte. Just copy the default fail char and
				try again. */
			outbuf[0] = lp_failed_convert_char();

			inbuf++;
			i_len--;

			outbuf++;
			o_len--;

			if (o_len == 0 || i_len == 0)
				return destlen - o_len;

			/* Keep trying with the next char... */
			goto again;

		} else {
			/* Keep compiler happy.... */
			return destlen - o_len;
		}
	}
}
예제 #8
0
    }
    else {
        dump_octets(fp, data->s, MAX_TEXT/2);
        fputs("    ...\n", fp);
        dump_octets(fp, data->s + data->len - MAX_TEXT/2, MAX_TEXT/2);
    }
#undef MAX_TEXT
}

static int dump_one_section(int partno, charset_t charset, int encoding,
                            const char *subtype, struct buf *data,
                            void *rock __attribute__((unused)))
{
#define MAX_TEXT    512
    printf("SECTION partno=%d length=%llu subtype=%s charset=%s encoding=%s\n",
            partno, (unsigned long long)data->len, subtype, charset_name(charset), encoding_name(encoding));
    dump_buf(stdout, data);
    return 0;
#undef MAX_TEXT
}

static int dump_text_sections(message_t *message)
{
    return message_foreach_text_section(message, dump_one_section, NULL);
}

/*-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-*/

static int dump_message(message_t *message)
{
    return dump_text_sections(message);