Beispiel #1
0
int check_dos_char(smb_ucs2_t c)
{
	lazy_initialize_conv();
	
	/* Find the right byte, and right bit within the byte; return
	 * 1 or 0 */
	return (doschar_table[(c & 0xffff) / 8] & (1 << (c & 7))) != 0;
}
Beispiel #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;
}
Beispiel #3
0
/**
 * Convert string from one encoding to another, making error checking etc
 *
 * @param src pointer to source string (multibyte or singlebyte)
 * @param srclen length of the source string in bytes
 * @param dest pointer to destination string (multibyte or singlebyte)
 * @param destlen maximal length allowed for string
 * @returns the number of bytes occupied in the destination
 **/
static size_t convert_string_internal(charset_t from, charset_t to,
                                      void const *src, size_t srclen,
                                      void *dest, size_t destlen)
{
    size_t i_len, o_len;
    size_t retval;
    const char* inbuf = (const char*)src;
    char* outbuf = (char*)dest;
    char* o_save = outbuf;
    atalk_iconv_t descriptor;

    /* Fixed based on Samba 3.0.6 */
    if (srclen == (size_t)-1) {
        if (from == CH_UCS2) {
            srclen = (strlen_w((const ucs2_t *)src)) * 2;
        } else {
            srclen = strlen((const char *)src);
        }
    }


    lazy_initialize_conv();

    descriptor = conv_handles[from][to];

    if (descriptor == (atalk_iconv_t)-1 || descriptor == (atalk_iconv_t)0) {
        return (size_t) -1;
    }

    i_len=srclen;
    o_len=destlen;
    retval = atalk_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";
            break;
        case E2BIG:
            reason="No more room";
            break;
        case EILSEQ:
            reason="Illegal multibyte sequence";
            break;
        }
        LOG(log_debug, logtype_default,"Conversion error: %s",reason);
        return (size_t)-1;
    }

    /* Terminate the string */
    return add_null( to, o_save, o_len, destlen -o_len);
}
Beispiel #4
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);
}
Beispiel #5
0
void init_valid_table(void)
{
	static int mapped_file;
	int i;
	const char *allowed = ".!#$%&'()_-@^`~";
	uint8 *valid_file;

	if (mapped_file) {
		/* Can't unmap files, so stick with what we have */
		return;
	}

	valid_file = (uint8 *)map_file(data_path("valid.dat"), 0x10000);
	if (valid_file) {
		valid_table = valid_file;
		mapped_file = 1;
		valid_table_use_unmap = True;
		return;
	}

	/* Otherwise, we're using a dynamically created valid_table.
	 * It might need to be regenerated if the code page changed.
	 * We know that we're not using a mapped file, so we can
	 * free() the old one. */
	SAFE_FREE(valid_table);

	/* use free rather than unmap */
	valid_table_use_unmap = False;

	DEBUG(2,("creating default valid table\n"));
	valid_table = (uint8 *)SMB_MALLOC(0x10000);
	SMB_ASSERT(valid_table != NULL);
	for (i=0;i<128;i++) {
		valid_table[i] = isalnum(i) || strchr(allowed,i);
	}

	lazy_initialize_conv();

	for (;i<0x10000;i++) {
		smb_ucs2_t c;
		SSVAL(&c, 0, i);
		valid_table[i] = check_dos_char_slowly(c);
	}
}
Beispiel #6
0
size_t convert_string_allocate(TALLOC_CTX *ctx, charset_t from, charset_t to,
			       void const *src, size_t srclen, void *dst, BOOL allow_bad_conv)
{
	size_t i_len, o_len, destlen = (srclen * 3) / 2;
	size_t retval;
	const char *inbuf = (const char *)src;
	char *outbuf = NULL, *ob = NULL;
	smb_iconv_t descriptor;
	void **dest = (void **)dst;

	*dest = NULL;

	if (src == NULL || srclen == (size_t)-1)
		return (size_t)-1;
	if (srclen == 0)
		return 0;

	lazy_initialize_conv();

	descriptor = conv_handles[from][to];

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

  convert:

	/* +2 is for ucs2 null termination. */
	if ((destlen*2)+2 < destlen) {
		/* wrapped ! abort. */
		if (!conv_silent)
			DEBUG(0, ("convert_string_allocate: destlen wrapped !\n"));
		if (!ctx)
			SAFE_FREE(outbuf);
		return (size_t)-1;
	} else {
		destlen = destlen * 2;
	}

	/* +2 is for ucs2 null termination. */
	if (ctx) {
		ob = (char *)TALLOC_REALLOC(ctx, ob, destlen + 2);
	} else {
		ob = (char *)SMB_REALLOC(ob, destlen + 2);
	}

	if (!ob) {
		DEBUG(0, ("convert_string_allocate: realloc failed!\n"));
		return (size_t)-1;
	}
	outbuf = ob;
	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_allocate: Conversion error: %s(%s)\n",reason,inbuf));
				if (allow_bad_conv)
					goto use_as_is;
				break;
			case E2BIG:
				goto convert;		
			case EILSEQ:
				reason="Illegal multibyte sequence";
				if (!conv_silent)
					DEBUG(3,("convert_string_allocate: Conversion error: %s(%s)\n",reason,inbuf));
				if (allow_bad_conv)
					goto use_as_is;
				break;
		}
		if (!conv_silent)
			DEBUG(0,("Conversion error: %s(%s)\n",reason,inbuf));
		/* smb_panic(reason); */
		return (size_t)-1;
	}

  out:

	destlen = destlen - o_len;
	if (ctx) {
		/* We're shrinking here so we know the +2 is safe from wrap. */
		ob = (char *)TALLOC_REALLOC(ctx,ob,destlen + 2);
	} else {
		ob = (char *)SMB_REALLOC(ob,destlen + 2);
	}

	if (destlen && !ob) {
		DEBUG(0, ("convert_string_allocate: out of memory!\n"));
		return (size_t)-1;
	}

	*dest = ob;

	/* Must ucs2 null terminate in the extra space we allocated. */
	ob[destlen] = '\0';
	ob[destlen+1] = '\0';

	return destlen;

 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)
			goto out;

		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)
				goto out;

			if (i_len >= 2) {
				*outbuf = lp_failed_convert_char();

				outbuf++;
				o_len--;

				inbuf += 2;
				i_len -= 2;
			}

			if (o_len == 0 || i_len == 0)
				goto out;

			/* 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)
				goto out;

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

			inbuf++;
			i_len--;

			outbuf += 2;
			o_len -= 2;

			if (o_len == 0 || i_len == 0)
				goto out;

			/* 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)
				goto out;

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

		} else {
			/* Keep compiler happy.... */
			goto out;
		}
	}
}
Beispiel #7
0
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;
		}
	}
}
Beispiel #8
0
codepoint_t next_codepoint(const char *str, size_t *size)
{
	/* It cannot occupy more than 4 bytes in UTF16 format */
	uint8_t buf[4];
	smb_iconv_t descriptor;
	size_t ilen_orig;
	size_t ilen;
	size_t olen;
	char *outbuf;

	if ((str[0] & 0x80) == 0) {
		*size = 1;
		return (codepoint_t)str[0];
	}

	/* We assume that no multi-byte character can take
	   more than 5 bytes. This is OK as we only
	   support codepoints up to 1M */

	ilen_orig = strnlen(str, 5);
	ilen = ilen_orig;

        lazy_initialize_conv();

        descriptor = conv_handles[CH_UNIX][CH_UTF16LE];
	if (descriptor == (smb_iconv_t)-1 || descriptor == (smb_iconv_t)0) {
		*size = 1;
		return INVALID_CODEPOINT;
	}

	/* This looks a little strange, but it is needed to cope
	   with codepoints above 64k which are encoded as per RFC2781. */
	olen = 2;
	outbuf = (char *)buf;
	smb_iconv(descriptor, &str, &ilen, &outbuf, &olen);
	if (olen == 2) {
		/* We failed to convert to a 2 byte character.
		   See if we can convert to a 4 UTF16-LE byte char encoding.
		*/
		olen = 4;
		outbuf = (char *)buf;
		smb_iconv(descriptor,  &str, &ilen, &outbuf, &olen);
		if (olen == 4) {
			/* We didn't convert any bytes */
			*size = 1;
			return INVALID_CODEPOINT;
		}
		olen = 4 - olen;
	} else {
		olen = 2 - olen;
	}

	*size = ilen_orig - ilen;

	if (olen == 2) {
		/* 2 byte, UTF16-LE encoded value. */
		return (codepoint_t)SVAL(buf, 0);
	}
	if (olen == 4) {
		/* Decode a 4 byte UTF16-LE character manually.
		   See RFC2871 for the encoding machanism.
		*/
		codepoint_t w1 = SVAL(buf,0) & ~0xD800;
		codepoint_t w2 = SVAL(buf,2) & ~0xDC00;

		return (codepoint_t)0x10000 +
				(w1 << 10) + w2;
	}

	/* no other length is valid */
	return INVALID_CODEPOINT;
}
Beispiel #9
0
static size_t convert_string_allocate_internal(charset_t from, charset_t to,
                                               void const *src, size_t srclen, char **dest)
{
    size_t i_len, o_len, destlen;
    size_t retval;
    const char *inbuf = (const char *)src;
    char *outbuf = NULL, *ob = NULL;
    atalk_iconv_t descriptor;

    *dest = NULL;

    if (src == NULL || srclen == (size_t)-1)
        return (size_t)-1;

    lazy_initialize_conv();

    descriptor = conv_handles[from][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!");
        return -1;
    }

    destlen = MAX(srclen, 512);
convert:
    destlen = destlen * 2;
    outbuf = (char *)realloc(ob, destlen);
    if (!outbuf) {
        LOG(log_debug, logtype_default,"convert_string_allocate: realloc failed!");
        SAFE_FREE(ob);
        return (size_t)-1;
    } else {
        ob = outbuf;
    }
    inbuf = src;   /* this restarts the whole conversion if buffer needed to be increased */
    i_len = srclen;
    o_len = destlen;
    retval = atalk_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";
            break;
        case E2BIG:
            goto convert;
        case EILSEQ:
            reason="Illegal multibyte sequence";
            break;
        }
        LOG(log_debug, logtype_default,"Conversion error: %s(%s)",reason,inbuf);
        SAFE_FREE(ob);
        return (size_t)-1;
    }


    destlen = destlen - o_len;

    /* Terminate the string */
    if (to == CH_UCS2 && o_len >= 2) {
        ob[destlen] = 0;
        ob[destlen+1] = 0;
        *dest = (char *)realloc(ob,destlen+2);
    }
    else if ( to != CH_UCS2 && o_len > 0 ) {
        ob[destlen] = 0;
        *dest = (char *)realloc(ob,destlen+1);
    }
    else {
        goto convert; /* realloc */
    }

    if (destlen && !*dest) {
        LOG(log_debug, logtype_default, "convert_string_allocate: out of memory!");
        SAFE_FREE(ob);
        return (size_t)-1;
    }

    return destlen;
}