Blame ma_conv_charset.c

Packit Service 17f749
/****************************************************************************
Packit Service 17f749
   Copyright (C) 2012, 2020, MariaDB Corporation.
Packit Service 17f749
   
Packit Service 17f749
   This library is free software; you can redistribute it and/or
Packit Service 17f749
   modify it under the terms of the GNU Library General Public
Packit Service 17f749
   License as published by the Free Software Foundation; either
Packit Service 17f749
   version 2 of the License, or (at your option) any later version.
Packit Service 17f749
   
Packit Service 17f749
   This library is distributed in the hope that it will be useful,
Packit Service 17f749
   but WITHOUT ANY WARRANTY; without even the implied warranty of
Packit Service 17f749
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit Service 17f749
   Library General Public License for more details.
Packit Service 17f749
   
Packit Service 17f749
   You should have received a copy of the GNU Library General Public
Packit Service 17f749
   License along with this library; if not see <http://www.gnu.org/licenses>
Packit Service 17f749
   or write to the Free Software Foundation, Inc., 
Packit Service 17f749
   51 Franklin St., Fifth Floor, Boston, MA 02110, USA
Packit Service 17f749
Packit Service 17f749
   Part of this code includes code from the PHP project which
Packit Service 17f749
   is freely available from http://www.php.net
Packit Service 17f749
*****************************************************************************/
Packit Service 17f749
Packit Service 17f749
Packit Service 17f749
#ifndef _WIN32
Packit Service 17f749
#include <strings.h>
Packit Service 17f749
#include <string.h>
Packit Service 17f749
#include <iconv.h>
Packit Service 17f749
#include <errno.h>
Packit Service 17f749
#else
Packit Service 17f749
#include <string.h>
Packit Service 17f749
#endif
Packit Service 17f749
#include <ma_odbc.h>
Packit Service 17f749
Packit Service 17f749
#if defined(SOLARIS) || defined(__sun)
Packit Service 17f749
#define IF_SOLARIS(A,B) A
Packit Service 17f749
#else
Packit Service 17f749
#define IF_SOLARIS(A,B) B
Packit Service 17f749
#endif
Packit Service 17f749
Packit Service 17f749
#define HAVE_ICONV
Packit Service 17f749
Packit Service 17f749
#ifdef HAVE_ICONV
Packit Service 17f749
/* {{{ MADB_MapCharsetName
Packit Service 17f749
   Changing charset name into something iconv understands, if necessary.
Packit Service 17f749
   Another purpose it to avoid BOMs in result string, adding BE if necessary
Packit Service 17f749
   e.g.UTF16 does not work form iconv, while UTF-16 does.
Packit Service 17f749
 */
Packit Service 17f749
static void MADB_MapCharsetName(const char *cs_name, my_bool target_cs, char *buffer, size_t buff_len)
Packit Service 17f749
{
Packit Service 17f749
  char digits[3], endianness[3]= "BE";
Packit Service 17f749
Packit Service 17f749
  if (sscanf(cs_name, "UTF%2[0-9]%2[LBE]", digits, endianness))
Packit Service 17f749
  {
Packit Service 17f749
    /* We should have at least digits. Endianness we write either default(BE), or what we found in the string */
Packit Service 17f749
    snprintf(buffer, buff_len, "UTF-%s%s", digits, endianness);
Packit Service 17f749
  }
Packit Service 17f749
  else
Packit Service 17f749
  {
Packit Service 17f749
    /* Not our client - copy as is*/
Packit Service 17f749
    strncpy(buffer, cs_name, buff_len - 1);
Packit Service 17f749
    buffer[buff_len - 1]= '\0';
Packit Service 17f749
  }
Packit Service 17f749
Packit Service 17f749
  if (target_cs)
Packit Service 17f749
  {
Packit Service 17f749
    strncat(buffer, "//TRANSLIT", buff_len - strlen(buffer));
Packit Service 17f749
  }
Packit Service 17f749
}
Packit Service 17f749
/* }}} */
Packit Service 17f749
#endif
Packit Service 17f749
Packit Service 17f749
/* {{{ MADB_ConvertString
Packit Service 17f749
   Converts string from one charset to another, and writes converted string to given buffer
Packit Service 17f749
   @param[in]     from
Packit Service 17f749
   @param[in/out] from_len
Packit Service 17f749
   @param[in]     from_cs
Packit Service 17f749
   @param[out]    to
Packit Service 17f749
   @param[in/out] to_len
Packit Service 17f749
   @param[in]     to_cs
Packit Service 17f749
   @param[out]    errorcode
Packit Service 17f749
Packit Service 17f749
   @return -1 in case of error, bytes used in the "to" buffer, otherwise
Packit Service 17f749
 */
Packit Service 17f749
size_t STDCALL MADB_ConvertString(const char *from __attribute__((unused)),
Packit Service 17f749
                                   size_t *from_len __attribute__((unused)),
Packit Service 17f749
                                   MARIADB_CHARSET_INFO *from_cs __attribute__((unused)),
Packit Service 17f749
                                   char *to __attribute__((unused)),
Packit Service 17f749
                                   size_t *to_len __attribute__((unused)),
Packit Service 17f749
                                   MARIADB_CHARSET_INFO *to_cs __attribute__((unused)), int *errorcode)
Packit Service 17f749
{
Packit Service 17f749
#ifndef HAVE_ICONV
Packit Service 17f749
  *errorcode= ENOTSUP;
Packit Service 17f749
  return -1;
Packit Service 17f749
#else
Packit Service 17f749
  iconv_t conv= 0;
Packit Service 17f749
  size_t rc= -1;
Packit Service 17f749
  size_t save_len= *to_len;
Packit Service 17f749
  char to_encoding[128], from_encoding[128];
Packit Service 17f749
Packit Service 17f749
  *errorcode= 0;
Packit Service 17f749
Packit Service 17f749
  /* check if conversion is supported */
Packit Service 17f749
  if (!from_cs || !from_cs->encoding || !from_cs->encoding[0] ||
Packit Service 17f749
      !to_cs || !to_cs->encoding || !to_cs->encoding[0])
Packit Service 17f749
  {
Packit Service 17f749
    *errorcode= EINVAL;
Packit Service 17f749
    return rc;
Packit Service 17f749
  }
Packit Service 17f749
Packit Service 17f749
  MADB_MapCharsetName(to_cs->encoding, 1, to_encoding, sizeof(to_encoding));
Packit Service 17f749
  MADB_MapCharsetName(from_cs->encoding, 0, from_encoding, sizeof(from_encoding));
Packit Service 17f749
Packit Service 17f749
  if ((conv= iconv_open(to_encoding, from_encoding)) == (iconv_t)-1)
Packit Service 17f749
  {
Packit Service 17f749
    *errorcode= errno;
Packit Service 17f749
    goto error;
Packit Service 17f749
  }
Packit Service 17f749
  if ((rc= iconv(conv, IF_SOLARIS(,(char **))&from, from_len, &to, to_len)) == (size_t)-1)
Packit Service 17f749
  {
Packit Service 17f749
    *errorcode= errno;
Packit Service 17f749
    goto error;
Packit Service 17f749
  }
Packit Service 17f749
  rc= save_len - *to_len;
Packit Service 17f749
error:
Packit Service 17f749
  if (conv != (iconv_t)-1)
Packit Service 17f749
    iconv_close(conv);
Packit Service 17f749
  return rc;
Packit Service 17f749
#endif
Packit Service 17f749
}
Packit Service 17f749
/* }}} */
Packit Service 17f749