Commit c61a2f58 authored by Tom Lane's avatar Tom Lane

Change the backend to reject strings containing invalidly-encoded multibyte

characters in all cases.  Formerly we mostly just threw warnings for invalid
input, and failed to detect it at all if no encoding conversion was required.
The tighter check is needed to defend against SQL-injection attacks as per
CVE-2006-2313 (further details will be published after release).  Embedded
zero (null) bytes will be rejected as well.  The checks are applied during
input to the backend (receipt from client or COPY IN), so it no longer seems
necessary to check in textin() and related routines; any string arriving at
those functions will already have been validated.  Conversion failure
reporting (for characters with no equivalent in the destination encoding)
has been cleaned up and made consistent while at it.

Also, fix a few longstanding errors in little-used encoding conversion
routines: win1251_to_iso, win866_to_iso, euc_tw_to_big5, euc_tw_to_mic,
mic_to_euc_tw were all broken to varying extents.

Patches by Tatsuo Ishii and Tom Lane.  Thanks to Akio Ishida and Yasuo Ohgaki
for identifying the security issues.
parent 1f219cf4
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.263 2006/04/05 22:11:54 tgl Exp $ * $PostgreSQL: pgsql/src/backend/commands/copy.c,v 1.264 2006/05/21 20:05:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -1023,9 +1023,15 @@ DoCopy(const CopyStmt *stmt) ...@@ -1023,9 +1023,15 @@ DoCopy(const CopyStmt *stmt)
cstate->raw_buf_index = cstate->raw_buf_len = 0; cstate->raw_buf_index = cstate->raw_buf_len = 0;
cstate->processed = 0; cstate->processed = 0;
/* Set up encoding conversion info */ /*
* Set up encoding conversion info. Even if the client and server
* encodings are the same, we must apply pg_client_to_server() to
* validate data in multibyte encodings.
*/
cstate->client_encoding = pg_get_client_encoding(); cstate->client_encoding = pg_get_client_encoding();
cstate->need_transcoding = (cstate->client_encoding != GetDatabaseEncoding()); cstate->need_transcoding =
(cstate->client_encoding != GetDatabaseEncoding() ||
pg_database_encoding_max_length() > 1);
/* See Multibyte encoding comment above */ /* See Multibyte encoding comment above */
cstate->encoding_embeds_ascii = PG_ENCODING_IS_CLIENT_ONLY(cstate->client_encoding); cstate->encoding_embeds_ascii = PG_ENCODING_IS_CLIENT_ONLY(cstate->client_encoding);
......
...@@ -14,7 +14,7 @@ ...@@ -14,7 +14,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/name.c,v 1.57 2006/03/05 15:58:43 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/name.c,v 1.58 2006/05/21 20:05:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -49,10 +49,7 @@ namein(PG_FUNCTION_ARGS) ...@@ -49,10 +49,7 @@ namein(PG_FUNCTION_ARGS)
NameData *result; NameData *result;
int len; int len;
/* verify encoding */
len = strlen(s); len = strlen(s);
pg_verifymbstr(s, len, false);
len = pg_mbcliplen(s, len, NAMEDATALEN - 1); len = pg_mbcliplen(s, len, NAMEDATALEN - 1);
result = (NameData *) palloc0(NAMEDATALEN); result = (NameData *) palloc0(NAMEDATALEN);
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.115 2006/03/05 15:58:44 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/varchar.c,v 1.116 2006/05/21 20:05:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -73,9 +73,6 @@ bpchar_input(const char *s, size_t len, int32 atttypmod) ...@@ -73,9 +73,6 @@ bpchar_input(const char *s, size_t len, int32 atttypmod)
char *r; char *r;
size_t maxlen; size_t maxlen;
/* verify encoding */
pg_verifymbstr(s, len, false);
/* If typmod is -1 (or invalid), use the actual string length */ /* If typmod is -1 (or invalid), use the actual string length */
if (atttypmod < (int32) VARHDRSZ) if (atttypmod < (int32) VARHDRSZ)
maxlen = len; maxlen = len;
...@@ -393,9 +390,6 @@ varchar_input(const char *s, size_t len, int32 atttypmod) ...@@ -393,9 +390,6 @@ varchar_input(const char *s, size_t len, int32 atttypmod)
VarChar *result; VarChar *result;
size_t maxlen; size_t maxlen;
/* verify encoding */
pg_verifymbstr(s, len, false);
maxlen = atttypmod - VARHDRSZ; maxlen = atttypmod - VARHDRSZ;
if (atttypmod >= (int32) VARHDRSZ && len > maxlen) if (atttypmod >= (int32) VARHDRSZ && len > maxlen)
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
* *
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.146 2006/04/04 19:35:36 tgl Exp $ * $PostgreSQL: pgsql/src/backend/utils/adt/varlena.c,v 1.147 2006/05/21 20:05:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -256,10 +256,7 @@ textin(PG_FUNCTION_ARGS) ...@@ -256,10 +256,7 @@ textin(PG_FUNCTION_ARGS)
text *result; text *result;
int len; int len;
/* verify encoding */
len = strlen(inputText); len = strlen(inputText);
pg_verifymbstr(inputText, len, false);
result = (text *) palloc(len + VARHDRSZ); result = (text *) palloc(len + VARHDRSZ);
VARATT_SIZEP(result) = len + VARHDRSZ; VARATT_SIZEP(result) = len + VARHDRSZ;
...@@ -299,9 +296,6 @@ textrecv(PG_FUNCTION_ARGS) ...@@ -299,9 +296,6 @@ textrecv(PG_FUNCTION_ARGS)
str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes); str = pq_getmsgtext(buf, buf->len - buf->cursor, &nbytes);
/* verify encoding */
pg_verifymbstr(str, nbytes, false);
result = (text *) palloc(nbytes + VARHDRSZ); result = (text *) palloc(nbytes + VARHDRSZ);
VARATT_SIZEP(result) = nbytes + VARHDRSZ; VARATT_SIZEP(result) = nbytes + VARHDRSZ;
memcpy(VARDATA(result), str, nbytes); memcpy(VARDATA(result), str, nbytes);
......
...@@ -6,186 +6,108 @@ ...@@ -6,186 +6,108 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conv.c,v 1.59 2006/03/05 15:58:46 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conv.c,v 1.60 2006/05/21 20:05:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
#include "postgres.h" #include "postgres.h"
#include "mb/pg_wchar.h" #include "mb/pg_wchar.h"
/*
* convert bogus chars that cannot be represented in the current
* encoding system.
*/
void
pg_print_bogus_char(unsigned char **mic, unsigned char **p)
{
char strbuf[16];
int l = pg_mic_mblen(*mic);
*(*p)++ = '(';
while (l--)
{
sprintf(strbuf, "%02x", *(*mic)++);
*(*p)++ = strbuf[0];
*(*p)++ = strbuf[1];
}
*(*p)++ = ')';
}
#ifdef NOT_USED
/* /*
* GB18030 ---> MIC * LATINn ---> MIC when the charset's local codes map directly to MIC
* Added by Bill Huang <bhuang@redhat.com>,<bill_huanghb@ybb.ne.jp> *
* l points to the source string of length len
* p is the output area (must be large enough!)
* lc is the mule character set id for the local encoding
* encoding is the PG identifier for the local encoding
*/ */
static void void
gb180302mic(unsigned char *gb18030, unsigned char *p, int len) latin2mic(const unsigned char *l, unsigned char *p, int len,
int lc, int encoding)
{ {
int c1; int c1;
int c2;
while (len > 0 && (c1 = *gb18030++))
{
if (c1 < 0x80)
{ /* should be ASCII */
len--;
*p++ = c1;
}
else if (c1 >= 0x81 && c1 <= 0xfe)
{
c2 = *gb18030++;
if (c2 >= 0x30 && c2 <= 0x69) while (len > 0)
{
len -= 4;
*p++ = c1;
*p++ = c2;
*p++ = *gb18030++;
*p++ = *gb18030++;
*p++ = *gb18030++;
}
else if ((c2 >= 0x40 && c2 <= 0x7e) || (c2 >= 0x80 && c2 <= 0xfe))
{ {
len -= 2; c1 = *l;
if (c1 == 0)
report_invalid_encoding(encoding, (const char *) l, len);
if (IS_HIGHBIT_SET(c1))
*p++ = lc;
*p++ = c1; *p++ = c1;
*p++ = c2; l++;
*p++ = *gb18030++;
}
else
{ /* throw the strange code */
len--; len--;
} }
}
}
*p = '\0'; *p = '\0';
} }
/* /*
* MIC ---> GB18030 * MIC ---> LATINn when the charset's local codes map directly to MIC
* Added by Bill Huang <bhuang@redhat.com>,<bill_huanghb@ybb.ne.jp> *
* mic points to the source string of length len
* p is the output area (must be large enough!)
* lc is the mule character set id for the local encoding
* encoding is the PG identifier for the local encoding
*/ */
static void void
mic2gb18030(unsigned char *mic, unsigned char *p, int len) mic2latin(const unsigned char *mic, unsigned char *p, int len,
int lc, int encoding)
{ {
int c1; int c1;
int c2;
while (len > 0 && (c1 = *mic)) while (len > 0)
{ {
len -= pg_mic_mblen(mic++); c1 = *mic;
if (c1 == 0)
if (!IS_HIGHBIT_SET(c1)) /* ASCII */ report_invalid_encoding(PG_MULE_INTERNAL, (const char *) mic, len);
*p++ = c1; if (!IS_HIGHBIT_SET(c1))
else if (c1 >= 0x81 && c1 <= 0xfe)
{
c2 = *mic++;
if ((c2 >= 0x40 && c2 <= 0x7e) || (c2 >= 0x80 && c2 <= 0xfe))
{
*p++ = c1;
*p++ = c2;
}
else if (c2 >= 0x30 && c2 <= 0x39)
{ {
/* easy for ASCII */
*p++ = c1; *p++ = c1;
*p++ = c2; mic++;
*p++ = *mic++; len--;
*p++ = *mic++;
}
else
{
mic--;
pg_print_bogus_char(&mic, &p);
mic--;
pg_print_bogus_char(&mic, &p);
}
} }
else else
{ {
mic--; int l = pg_mic_mblen(mic);
pg_print_bogus_char(&mic, &p);
if (len < l)
report_invalid_encoding(PG_MULE_INTERNAL, (const char *) mic,
len);
if (l != 2 || c1 != lc || !IS_HIGHBIT_SET(mic[1]))
report_untranslatable_char(PG_MULE_INTERNAL, encoding,
(const char *) mic, len);
*p++ = mic[1];
mic += 2;
len -= 2;
} }
} }
*p = '\0'; *p = '\0';
} }
#endif
/*
* LATINn ---> MIC
*/
void
latin2mic(unsigned char *l, unsigned char *p, int len, int lc)
{
int c1;
while (len-- > 0 && (c1 = *l++))
{
if (IS_HIGHBIT_SET(c1))
*p++ = lc; /* Latin? */
*p++ = c1;
}
*p = '\0';
}
/* /*
* MIC ---> LATINn * ASCII ---> MIC
*
* While ordinarily SQL_ASCII encoding is forgiving of high-bit-set
* characters, here we must take a hard line because we don't know
* the appropriate MIC equivalent.
*/ */
void void
mic2latin(unsigned char *mic, unsigned char *p, int len, int lc) pg_ascii2mic(const unsigned char *l, unsigned char *p, int len)
{ {
int c1; int c1;
while (len > 0 && (c1 = *mic)) while (len > 0)
{ {
len -= pg_mic_mblen(mic++); c1 = *l;
if (c1 == 0 || IS_HIGHBIT_SET(c1))
if (c1 == lc) report_invalid_encoding(PG_SQL_ASCII, (const char *) l, len);
*p++ = *mic++;
else if (IS_HIGHBIT_SET(c1))
{
mic--;
pg_print_bogus_char(&mic, &p);
}
else
{ /* should be ASCII */
*p++ = c1; *p++ = c1;
l++;
len--;
} }
}
*p = '\0';
}
/*
* ASCII ---> MIC
*/
void
pg_ascii2mic(unsigned char *l, unsigned char *p, int len)
{
int c1;
while (len-- > 0 && (c1 = *l++))
*p++ = (c1 & 0x7f);
*p = '\0'; *p = '\0';
} }
...@@ -193,19 +115,19 @@ pg_ascii2mic(unsigned char *l, unsigned char *p, int len) ...@@ -193,19 +115,19 @@ pg_ascii2mic(unsigned char *l, unsigned char *p, int len)
* MIC ---> ASCII * MIC ---> ASCII
*/ */
void void
pg_mic2ascii(unsigned char *mic, unsigned char *p, int len) pg_mic2ascii(const unsigned char *mic, unsigned char *p, int len)
{ {
int c1; int c1;
while (len-- > 0 && (c1 = *mic)) while (len > 0)
{ {
if (IS_HIGHBIT_SET(c1)) c1 = *mic;
pg_print_bogus_char(&mic, &p); if (c1 == 0 || IS_HIGHBIT_SET(c1))
else report_untranslatable_char(PG_MULE_INTERNAL, PG_SQL_ASCII,
{ /* should be ASCII */ (const char *) mic, len);
*p++ = c1; *p++ = c1;
mic++; mic++;
} len--;
} }
*p = '\0'; *p = '\0';
} }
...@@ -213,86 +135,103 @@ pg_mic2ascii(unsigned char *mic, unsigned char *p, int len) ...@@ -213,86 +135,103 @@ pg_mic2ascii(unsigned char *mic, unsigned char *p, int len)
/* /*
* latin2mic_with_table: a generic single byte charset encoding * latin2mic_with_table: a generic single byte charset encoding
* conversion from a local charset to the mule internal code. * conversion from a local charset to the mule internal code.
* with a encoding conversion table. *
* the table is ordered according to the local charset, * l points to the source string of length len
* p is the output area (must be large enough!)
* lc is the mule character set id for the local encoding
* encoding is the PG identifier for the local encoding
* tab holds conversion entries for the local charset
* starting from 128 (0x80). each entry in the table * starting from 128 (0x80). each entry in the table
* holds the corresponding code point for the mule internal code. * holds the corresponding code point for the mule internal code.
*/ */
void void
latin2mic_with_table( latin2mic_with_table(const unsigned char *l,
unsigned char *l, /* local charset string (source) */ unsigned char *p,
unsigned char *p, /* pointer to store mule internal code int len,
* (destination) */ int lc,
int len, /* length of l */ int encoding,
int lc, /* leading character of p */ const unsigned char *tab)
unsigned char *tab /* code conversion table */
)
{ {
unsigned char c1, unsigned char c1,
c2; c2;
while (len-- > 0 && (c1 = *l++)) while (len > 0)
{ {
if (c1 < 128) c1 = *l;
if (c1 == 0)
report_invalid_encoding(encoding, (const char *) l, len);
if (!IS_HIGHBIT_SET(c1))
*p++ = c1; *p++ = c1;
else else
{ {
c2 = tab[c1 - 128]; c2 = tab[c1 - HIGHBIT];
if (c2) if (c2)
{ {
*p++ = lc; *p++ = lc;
*p++ = c2; *p++ = c2;
} }
else else
{ report_untranslatable_char(encoding, PG_MULE_INTERNAL,
*p++ = ' '; /* cannot convert */ (const char *) l, len);
}
} }
l++;
len--;
} }
*p = '\0'; *p = '\0';
} }
/* /*
* mic2latin_with_table: a generic single byte charset encoding * mic2latin_with_table: a generic single byte charset encoding
* conversion from the mule internal code to a local charset * conversion from the mule internal code to a local charset.
* with a encoding conversion table. *
* the table is ordered according to the second byte of the mule * mic points to the source string of length len
* internal code starting from 128 (0x80). * p is the output area (must be large enough!)
* each entry in the table * lc is the mule character set id for the local encoding
* holds the corresponding code point for the local code. * encoding is the PG identifier for the local encoding
* tab holds conversion entries for the mule internal code's
* second byte, starting from 128 (0x80). each entry in the table
* holds the corresponding code point for the local charset.
*/ */
void void
mic2latin_with_table( mic2latin_with_table(const unsigned char *mic,
unsigned char *mic, /* mule internal code (source) */ unsigned char *p,
unsigned char *p, /* local code (destination) */ int len,
int len, /* length of p */ int lc,
int lc, /* leading character */ int encoding,
unsigned char *tab /* code conversion table */ const unsigned char *tab)
)
{ {
unsigned char c1, unsigned char c1,
c2; c2;
while (len-- > 0 && (c1 = *mic++)) while (len > 0)
{ {
if (c1 < 128) c1 = *mic;
*p++ = c1; if (c1 == 0)
else if (c1 == lc) report_invalid_encoding(PG_MULE_INTERNAL, (const char *) mic, len);
if (!IS_HIGHBIT_SET(c1))
{ {
c1 = *mic++; /* easy for ASCII */
*p++ = c1;
mic++;
len--; len--;
c2 = tab[c1 - 128];
if (c2)
*p++ = c2;
else
{
*p++ = ' '; /* cannot convert */
}
} }
else else
{ {
*p++ = ' '; /* bogus character */ int l = pg_mic_mblen(mic);
if (len < l)
report_invalid_encoding(PG_MULE_INTERNAL, (const char *) mic,
len);
if (l != 2 || c1 != lc || !IS_HIGHBIT_SET(mic[1]) ||
(c2 = tab[mic[1] - HIGHBIT]) == 0)
{
report_untranslatable_char(PG_MULE_INTERNAL, encoding,
(const char *) mic, len);
break; /* keep compiler quiet */
}
*p++ = c2;
mic += 2;
len -= 2;
} }
} }
*p = '\0'; *p = '\0';
...@@ -331,25 +270,38 @@ compare2(const void *p1, const void *p2) ...@@ -331,25 +270,38 @@ compare2(const void *p1, const void *p2)
/* /*
* UTF8 ---> local code * UTF8 ---> local code
* *
* utf: input UTF8 string. Its length is limited by "len" parameter * utf: input UTF8 string (need not be null-terminated).
* or a null terminator. * iso: pointer to the output area (must be large enough!)
* iso: pointer to the output.
* map: the conversion map. * map: the conversion map.
* size: the size of the conversion map. * size: the size of the conversion map.
* encoding: the PG identifier for the local encoding.
* len: length of input string.
*/ */
void void
UtfToLocal(unsigned char *utf, unsigned char *iso, UtfToLocal(const unsigned char *utf, unsigned char *iso,
pg_utf_to_local *map, int size, int len) const pg_utf_to_local *map, int size, int encoding, int len)
{ {
unsigned int iutf; unsigned int iutf;
int l; int l;
pg_utf_to_local *p; pg_utf_to_local *p;
for (; len > 0 && *utf; len -= l) for (; len > 0; len -= l)
{ {
/* "break" cases all represent errors */
if (*utf == '\0')
break;
l = pg_utf_mblen(utf); l = pg_utf_mblen(utf);
if (len < l)
break;
if (!pg_utf8_islegal(utf, l))
break;
if (l == 1) if (l == 1)
{ {
/* ASCII case is easy */
*iso++ = *utf++; *iso++ = *utf++;
continue; continue;
} }
...@@ -371,16 +323,14 @@ UtfToLocal(unsigned char *utf, unsigned char *iso, ...@@ -371,16 +323,14 @@ UtfToLocal(unsigned char *utf, unsigned char *iso,
iutf |= *utf++ << 8; iutf |= *utf++ << 8;
iutf |= *utf++; iutf |= *utf++;
} }
p = bsearch(&iutf, map, size, p = bsearch(&iutf, map, size,
sizeof(pg_utf_to_local), compare1); sizeof(pg_utf_to_local), compare1);
if (p == NULL) if (p == NULL)
{ report_untranslatable_char(PG_UTF8, encoding,
ereport(WARNING, (const char *) (utf - l), len);
(errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
errmsg("ignoring unconvertible UTF-8 character 0x%04x",
iutf)));
continue;
}
if (p->code & 0xff000000) if (p->code & 0xff000000)
*iso++ = p->code >> 24; *iso++ = p->code >> 24;
if (p->code & 0x00ff0000) if (p->code & 0x00ff0000)
...@@ -390,15 +340,26 @@ UtfToLocal(unsigned char *utf, unsigned char *iso, ...@@ -390,15 +340,26 @@ UtfToLocal(unsigned char *utf, unsigned char *iso,
if (p->code & 0x000000ff) if (p->code & 0x000000ff)
*iso++ = p->code & 0x000000ff; *iso++ = p->code & 0x000000ff;
} }
if (len > 0)
report_invalid_encoding(PG_UTF8, (const char *) utf, len);
*iso = '\0'; *iso = '\0';
} }
/* /*
* local code ---> UTF8 * local code ---> UTF8
*
* iso: input local string (need not be null-terminated).
* utf: pointer to the output area (must be large enough!)
* map: the conversion map.
* size: the size of the conversion map.
* encoding: the PG identifier for the local encoding.
* len: length of input string.
*/ */
void void
LocalToUtf(unsigned char *iso, unsigned char *utf, LocalToUtf(const unsigned char *iso, unsigned char *utf,
pg_local_to_utf *map, int size, int encoding, int len) const pg_local_to_utf *map, int size, int encoding, int len)
{ {
unsigned int iiso; unsigned int iiso;
int l; int l;
...@@ -409,16 +370,23 @@ LocalToUtf(unsigned char *iso, unsigned char *utf, ...@@ -409,16 +370,23 @@ LocalToUtf(unsigned char *iso, unsigned char *utf,
(errcode(ERRCODE_INVALID_PARAMETER_VALUE), (errcode(ERRCODE_INVALID_PARAMETER_VALUE),
errmsg("invalid encoding number: %d", encoding))); errmsg("invalid encoding number: %d", encoding)));
for (; len > 0 && *iso; len -= l) for (; len > 0; len -= l)
{ {
/* "break" cases all represent errors */
if (*iso == '\0')
break;
if (!IS_HIGHBIT_SET(*iso)) if (!IS_HIGHBIT_SET(*iso))
{ {
/* ASCII case is easy */
*utf++ = *iso++; *utf++ = *iso++;
l = 1; l = 1;
continue; continue;
} }
l = pg_encoding_mblen(encoding, (char *) iso); l = pg_encoding_verifymb(encoding, (const char *) iso, len);
if (l < 0)
break;
if (l == 1) if (l == 1)
iiso = *iso++; iiso = *iso++;
...@@ -440,16 +408,13 @@ LocalToUtf(unsigned char *iso, unsigned char *utf, ...@@ -440,16 +408,13 @@ LocalToUtf(unsigned char *iso, unsigned char *utf,
iiso |= *iso++ << 8; iiso |= *iso++ << 8;
iiso |= *iso++; iiso |= *iso++;
} }
p = bsearch(&iiso, map, size, p = bsearch(&iiso, map, size,
sizeof(pg_local_to_utf), compare2); sizeof(pg_local_to_utf), compare2);
if (p == NULL) if (p == NULL)
{ report_untranslatable_char(encoding, PG_UTF8,
ereport(WARNING, (const char *) (iso - l), len);
(errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
errmsg("ignoring unconvertible %s character 0x%04x",
(&pg_enc2name_tbl[encoding])->name, iiso)));
continue;
}
if (p->utf & 0xff000000) if (p->utf & 0xff000000)
*utf++ = p->utf >> 24; *utf++ = p->utf >> 24;
if (p->utf & 0x00ff0000) if (p->utf & 0x00ff0000)
...@@ -459,5 +424,9 @@ LocalToUtf(unsigned char *iso, unsigned char *utf, ...@@ -459,5 +424,9 @@ LocalToUtf(unsigned char *iso, unsigned char *utf,
if (p->utf & 0x000000ff) if (p->utf & 0x000000ff)
*utf++ = p->utf & 0x000000ff; *utf++ = p->utf & 0x000000ff;
} }
if (len > 0)
report_invalid_encoding(encoding, (const char *) iso, len);
*utf = '\0'; *utf = '\0';
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/cyrillic_and_mic/cyrillic_and_mic.c,v 1.12 2006/03/05 15:58:47 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/cyrillic_and_mic/cyrillic_and_mic.c,v 1.13 2006/05/21 20:05:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -70,14 +70,14 @@ extern Datum win866_to_iso(PG_FUNCTION_ARGS); ...@@ -70,14 +70,14 @@ extern Datum win866_to_iso(PG_FUNCTION_ARGS);
* ---------- * ----------
*/ */
static void koi8r2mic(unsigned char *l, unsigned char *p, int len); static void koi8r2mic(const unsigned char *l, unsigned char *p, int len);
static void mic2koi8r(unsigned char *mic, unsigned char *p, int len); static void mic2koi8r(const unsigned char *mic, unsigned char *p, int len);
static void iso2mic(unsigned char *l, unsigned char *p, int len); static void iso2mic(const unsigned char *l, unsigned char *p, int len);
static void mic2iso(unsigned char *mic, unsigned char *p, int len); static void mic2iso(const unsigned char *mic, unsigned char *p, int len);
static void win12512mic(unsigned char *l, unsigned char *p, int len); static void win12512mic(const unsigned char *l, unsigned char *p, int len);
static void mic2win1251(unsigned char *mic, unsigned char *p, int len); static void mic2win1251(const unsigned char *mic, unsigned char *p, int len);
static void win8662mic(unsigned char *l, unsigned char *p, int len); static void win8662mic(const unsigned char *l, unsigned char *p, int len);
static void mic2win866(unsigned char *mic, unsigned char *p, int len); static void mic2win866(const unsigned char *mic, unsigned char *p, int len);
Datum Datum
koi8r_to_mic(PG_FUNCTION_ARGS) koi8r_to_mic(PG_FUNCTION_ARGS)
...@@ -401,7 +401,7 @@ win1251_to_iso(PG_FUNCTION_ARGS) ...@@ -401,7 +401,7 @@ win1251_to_iso(PG_FUNCTION_ARGS)
buf = palloc(len * ENCODING_GROWTH_RATE); buf = palloc(len * ENCODING_GROWTH_RATE);
win12512mic(src, buf, len); win12512mic(src, buf, len);
mic2win1251(buf, dest, strlen((char *) buf)); mic2iso(buf, dest, strlen((char *) buf));
pfree(buf); pfree(buf);
PG_RETURN_VOID(); PG_RETURN_VOID();
...@@ -441,7 +441,7 @@ win866_to_iso(PG_FUNCTION_ARGS) ...@@ -441,7 +441,7 @@ win866_to_iso(PG_FUNCTION_ARGS)
buf = palloc(len * ENCODING_GROWTH_RATE); buf = palloc(len * ENCODING_GROWTH_RATE);
win8662mic(src, buf, len); win8662mic(src, buf, len);
mic2win866(buf, dest, strlen((char *) buf)); mic2iso(buf, dest, strlen((char *) buf));
pfree(buf); pfree(buf);
PG_RETURN_VOID(); PG_RETURN_VOID();
...@@ -460,23 +460,23 @@ win866_to_iso(PG_FUNCTION_ARGS) ...@@ -460,23 +460,23 @@ win866_to_iso(PG_FUNCTION_ARGS)
/* koi8r2mic: KOI8-R to Mule internal code */ /* koi8r2mic: KOI8-R to Mule internal code */
static void static void
koi8r2mic(unsigned char *l, unsigned char *p, int len) koi8r2mic(const unsigned char *l, unsigned char *p, int len)
{ {
latin2mic(l, p, len, LC_KOI8_R); latin2mic(l, p, len, LC_KOI8_R, PG_KOI8R);
} }
/* mic2koi8r: Mule internal code to KOI8-R */ /* mic2koi8r: Mule internal code to KOI8-R */
static void static void
mic2koi8r(unsigned char *mic, unsigned char *p, int len) mic2koi8r(const unsigned char *mic, unsigned char *p, int len)
{ {
mic2latin(mic, p, len, LC_KOI8_R); mic2latin(mic, p, len, LC_KOI8_R, PG_KOI8R);
} }
/* iso2mic: ISO-8859-5 to Mule internal code */ /* iso2mic: ISO-8859-5 to Mule internal code */
static void static void
iso2mic(unsigned char *l, unsigned char *p, int len) iso2mic(const unsigned char *l, unsigned char *p, int len)
{ {
static unsigned char iso2koi[] = { static const unsigned char iso2koi[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
...@@ -495,14 +495,14 @@ iso2mic(unsigned char *l, unsigned char *p, int len) ...@@ -495,14 +495,14 @@ iso2mic(unsigned char *l, unsigned char *p, int len)
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}; };
latin2mic_with_table(l, p, len, LC_KOI8_R, iso2koi); latin2mic_with_table(l, p, len, LC_KOI8_R, PG_ISO_8859_5, iso2koi);
} }
/* mic2iso: Mule internal code to ISO8859-5 */ /* mic2iso: Mule internal code to ISO8859-5 */
static void static void
mic2iso(unsigned char *mic, unsigned char *p, int len) mic2iso(const unsigned char *mic, unsigned char *p, int len)
{ {
static unsigned char koi2iso[] = { static const unsigned char koi2iso[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
...@@ -521,14 +521,14 @@ mic2iso(unsigned char *mic, unsigned char *p, int len) ...@@ -521,14 +521,14 @@ mic2iso(unsigned char *mic, unsigned char *p, int len)
0xcc, 0xcb, 0xb7, 0xc8, 0xcd, 0xc9, 0xc7, 0xca 0xcc, 0xcb, 0xb7, 0xc8, 0xcd, 0xc9, 0xc7, 0xca
}; };
mic2latin_with_table(mic, p, len, LC_KOI8_R, koi2iso); mic2latin_with_table(mic, p, len, LC_KOI8_R, PG_ISO_8859_5, koi2iso);
} }
/* win2mic: CP1251 to Mule internal code */ /* win2mic: CP1251 to Mule internal code */
static void static void
win12512mic(unsigned char *l, unsigned char *p, int len) win12512mic(const unsigned char *l, unsigned char *p, int len)
{ {
static unsigned char win2koi[] = { static const unsigned char win2koi[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
...@@ -547,14 +547,14 @@ win12512mic(unsigned char *l, unsigned char *p, int len) ...@@ -547,14 +547,14 @@ win12512mic(unsigned char *l, unsigned char *p, int len)
0xdb, 0xdd, 0xdf, 0xd9, 0xd8, 0xdc, 0xc0, 0xd1 0xdb, 0xdd, 0xdf, 0xd9, 0xd8, 0xdc, 0xc0, 0xd1
}; };
latin2mic_with_table(l, p, len, LC_KOI8_R, win2koi); latin2mic_with_table(l, p, len, LC_KOI8_R, PG_WIN1251, win2koi);
} }
/* mic2win: Mule internal code to CP1251 */ /* mic2win: Mule internal code to CP1251 */
static void static void
mic2win1251(unsigned char *mic, unsigned char *p, int len) mic2win1251(const unsigned char *mic, unsigned char *p, int len)
{ {
static unsigned char koi2win[] = { static const unsigned char koi2win[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
...@@ -573,14 +573,14 @@ mic2win1251(unsigned char *mic, unsigned char *p, int len) ...@@ -573,14 +573,14 @@ mic2win1251(unsigned char *mic, unsigned char *p, int len)
0xdc, 0xdb, 0xc7, 0xd8, 0xdd, 0xd9, 0xd7, 0xda 0xdc, 0xdb, 0xc7, 0xd8, 0xdd, 0xd9, 0xd7, 0xda
}; };
mic2latin_with_table(mic, p, len, LC_KOI8_R, koi2win); mic2latin_with_table(mic, p, len, LC_KOI8_R, PG_WIN1251, koi2win);
} }
/* win8662mic: CP866 to Mule internal code */ /* win8662mic: CP866 to Mule internal code */
static void static void
win8662mic(unsigned char *l, unsigned char *p, int len) win8662mic(const unsigned char *l, unsigned char *p, int len)
{ {
static unsigned char win8662koi[] = { static const unsigned char win8662koi[] = {
0xe1, 0xe2, 0xf7, 0xe7, 0xe4, 0xe5, 0xf6, 0xfa, 0xe1, 0xe2, 0xf7, 0xe7, 0xe4, 0xe5, 0xf6, 0xfa,
0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0, 0xe9, 0xea, 0xeb, 0xec, 0xed, 0xee, 0xef, 0xf0,
0xf2, 0xf3, 0xf4, 0xf5, 0xe6, 0xe8, 0xe3, 0xfe, 0xf2, 0xf3, 0xf4, 0xf5, 0xe6, 0xe8, 0xe3, 0xfe,
...@@ -599,14 +599,14 @@ win8662mic(unsigned char *l, unsigned char *p, int len) ...@@ -599,14 +599,14 @@ win8662mic(unsigned char *l, unsigned char *p, int len)
0xb6, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 0xb6, 0xa6, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
}; };
latin2mic_with_table(l, p, len, LC_KOI8_R, win8662koi); latin2mic_with_table(l, p, len, LC_KOI8_R, PG_WIN866, win8662koi);
} }
/* mic2win866: Mule internal code to CP866 */ /* mic2win866: Mule internal code to CP866 */
static void static void
mic2win866(unsigned char *mic, unsigned char *p, int len) mic2win866(const unsigned char *mic, unsigned char *p, int len)
{ {
static unsigned char koi2win866[] = { static const unsigned char koi2win866[] = {
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
...@@ -625,5 +625,5 @@ mic2win866(unsigned char *mic, unsigned char *p, int len) ...@@ -625,5 +625,5 @@ mic2win866(unsigned char *mic, unsigned char *p, int len)
0x9c, 0x9b, 0x87, 0x98, 0x9d, 0x99, 0x97, 0x9a 0x9c, 0x9b, 0x87, 0x98, 0x9d, 0x99, 0x97, 0x9a
}; };
mic2latin_with_table(mic, p, len, LC_KOI8_R, koi2win866); mic2latin_with_table(mic, p, len, LC_KOI8_R, PG_WIN866, koi2win866);
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/euc_cn_and_mic/euc_cn_and_mic.c,v 1.13 2006/03/05 15:58:47 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/euc_cn_and_mic/euc_cn_and_mic.c,v 1.14 2006/05/21 20:05:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -32,8 +32,8 @@ extern Datum mic_to_euc_cn(PG_FUNCTION_ARGS); ...@@ -32,8 +32,8 @@ extern Datum mic_to_euc_cn(PG_FUNCTION_ARGS);
* ---------- * ----------
*/ */
static void euc_cn2mic(unsigned char *euc, unsigned char *p, int len); static void euc_cn2mic(const unsigned char *euc, unsigned char *p, int len);
static void mic2euc_cn(unsigned char *mic, unsigned char *p, int len); static void mic2euc_cn(const unsigned char *mic, unsigned char *p, int len);
Datum Datum
euc_cn_to_mic(PG_FUNCTION_ARGS) euc_cn_to_mic(PG_FUNCTION_ARGS)
...@@ -71,23 +71,30 @@ mic_to_euc_cn(PG_FUNCTION_ARGS) ...@@ -71,23 +71,30 @@ mic_to_euc_cn(PG_FUNCTION_ARGS)
* EUC_CN ---> MIC * EUC_CN ---> MIC
*/ */
static void static void
euc_cn2mic(unsigned char *euc, unsigned char *p, int len) euc_cn2mic(const unsigned char *euc, unsigned char *p, int len)
{ {
int c1; int c1;
while (len >= 0 && (c1 = *euc++)) while (len > 0)
{ {
c1 = *euc;
if (IS_HIGHBIT_SET(c1)) if (IS_HIGHBIT_SET(c1))
{ {
len -= 2; if (len < 2 || !IS_HIGHBIT_SET(euc[1]))
report_invalid_encoding(PG_EUC_CN, (const char *) euc, len);
*p++ = LC_GB2312_80; *p++ = LC_GB2312_80;
*p++ = c1; *p++ = c1;
*p++ = *euc++; *p++ = euc[1];
euc += 2;
len -= 2;
} }
else else
{ /* should be ASCII */ { /* should be ASCII */
len--; if (c1 == 0)
report_invalid_encoding(PG_EUC_CN, (const char *) euc, len);
*p++ = c1; *p++ = c1;
euc++;
len--;
} }
} }
*p = '\0'; *p = '\0';
...@@ -97,26 +104,35 @@ euc_cn2mic(unsigned char *euc, unsigned char *p, int len) ...@@ -97,26 +104,35 @@ euc_cn2mic(unsigned char *euc, unsigned char *p, int len)
* MIC ---> EUC_CN * MIC ---> EUC_CN
*/ */
static void static void
mic2euc_cn(unsigned char *mic, unsigned char *p, int len) mic2euc_cn(const unsigned char *mic, unsigned char *p, int len)
{ {
int c1; int c1;
while (len >= 0 && (c1 = *mic)) while (len > 0)
{ {
len -= pg_mic_mblen(mic++); c1 = *mic;
if (IS_HIGHBIT_SET(c1))
if (c1 == LC_GB2312_80)
{ {
if (c1 != LC_GB2312_80)
report_untranslatable_char(PG_MULE_INTERNAL, PG_EUC_CN,
(const char *) mic, len);
if (len < 3 || !IS_HIGHBIT_SET(mic[1]) || !IS_HIGHBIT_SET(mic[2]))
report_invalid_encoding(PG_MULE_INTERNAL,
(const char *) mic, len);
mic++;
*p++ = *mic++; *p++ = *mic++;
*p++ = *mic++; *p++ = *mic++;
} len -= 3;
else if (IS_HIGHBIT_SET(c1))
{ /* cannot convert to EUC_CN! */
mic--;
pg_print_bogus_char(&mic, &p);
} }
else else
*p++ = c1; /* should be ASCII */ { /* should be ASCII */
if (c1 == 0)
report_invalid_encoding(PG_MULE_INTERNAL,
(const char *) mic, len);
*p++ = c1;
mic++;
len--;
}
} }
*p = '\0'; *p = '\0';
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/euc_jp_and_sjis.c,v 1.15 2006/03/04 10:57:35 ishii Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/euc_jp_and_sjis/euc_jp_and_sjis.c,v 1.16 2006/05/21 20:05:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -22,9 +22,6 @@ ...@@ -22,9 +22,6 @@
#define PGSJISALTCODE 0x81ac #define PGSJISALTCODE 0x81ac
#define PGEUCALTCODE 0xa2ae #define PGEUCALTCODE 0xa2ae
#define ISSJISHEAD(c) ((c >= 0x81 && c <= 0x9f) || (c >= 0xe0 && c <= 0xfc))
#define ISSJISTAIL(c) ((c >= 0x40 && c <= 0x7e) || (c >= 0x80 && c <= 0xfc))
/* /*
* conversion table between SJIS UDC (IBM kanji) and EUC_JP * conversion table between SJIS UDC (IBM kanji) and EUC_JP
*/ */
...@@ -57,12 +54,12 @@ extern Datum mic_to_sjis(PG_FUNCTION_ARGS); ...@@ -57,12 +54,12 @@ extern Datum mic_to_sjis(PG_FUNCTION_ARGS);
* ---------- * ----------
*/ */
static void sjis2mic(unsigned char *sjis, unsigned char *p, int len); static void sjis2mic(const unsigned char *sjis, unsigned char *p, int len);
static void mic2sjis(unsigned char *mic, unsigned char *p, int len); static void mic2sjis(const unsigned char *mic, unsigned char *p, int len);
static void euc_jp2mic(unsigned char *euc, unsigned char *p, int len); static void euc_jp2mic(const unsigned char *euc, unsigned char *p, int len);
static void mic2euc_jp(unsigned char *mic, unsigned char *p, int len); static void mic2euc_jp(const unsigned char *mic, unsigned char *p, int len);
static void euc_jp2sjis(unsigned char *mic, unsigned char *p, int len); static void euc_jp2sjis(const unsigned char *mic, unsigned char *p, int len);
static void sjis2euc_jp(unsigned char *mic, unsigned char *p, int len); static void sjis2euc_jp(const unsigned char *mic, unsigned char *p, int len);
Datum Datum
euc_jp_to_sjis(PG_FUNCTION_ARGS) euc_jp_to_sjis(PG_FUNCTION_ARGS)
...@@ -164,38 +161,34 @@ mic_to_sjis(PG_FUNCTION_ARGS) ...@@ -164,38 +161,34 @@ mic_to_sjis(PG_FUNCTION_ARGS)
* SJIS ---> MIC * SJIS ---> MIC
*/ */
static void static void
sjis2mic(unsigned char *sjis, unsigned char *p, int len) sjis2mic(const unsigned char *sjis, unsigned char *p, int len)
{ {
int c1, int c1,
c2, c2,
/* Eiji Tokuya patched begin */
i, i,
k, k,
k2; k2;
/* Eiji Tokuya patched end */ while (len > 0)
while (len >= 0 && (c1 = *sjis++))
{ {
c1 = *sjis;
if (c1 >= 0xa1 && c1 <= 0xdf) if (c1 >= 0xa1 && c1 <= 0xdf)
{ {
/* JIS X0201 (1 byte kana) */ /* JIS X0201 (1 byte kana) */
len--;
*p++ = LC_JISX0201K; *p++ = LC_JISX0201K;
*p++ = c1; *p++ = c1;
sjis++;
len--;
} }
else if (IS_HIGHBIT_SET(c1)) else if (IS_HIGHBIT_SET(c1))
{ {
/* /*
* JIS X0208, X0212, user defined extended characters * JIS X0208, X0212, user defined extended characters
*/ */
c2 = *sjis++; if (len < 2 || !ISSJISHEAD(c1) || !ISSJISTAIL(sjis[1]))
if (!ISSJISHEAD(c1) || !ISSJISTAIL(c2)) report_invalid_encoding(PG_SJIS, (const char *) sjis, len);
ereport(ERROR, c2 = sjis[1];
(errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
errmsg("invalid byte sequence for encoding \"SJIS\": 0x%02x%02x",
c1, c2)));
k = (c1 << 8) + c2; k = (c1 << 8) + c2;
/* Eiji Tokuya patched begin */
if (k >= 0xed40 && k < 0xf040) if (k >= 0xed40 && k < 0xf040)
{ {
/* NEC selection IBM kanji */ /* NEC selection IBM kanji */
...@@ -214,19 +207,15 @@ sjis2mic(unsigned char *sjis, unsigned char *p, int len) ...@@ -214,19 +207,15 @@ sjis2mic(unsigned char *sjis, unsigned char *p, int len)
} }
if (k < 0xeb3f) if (k < 0xeb3f)
/* Eiji Tokuya patched end */
{ {
/* JIS X0208 */ /* JIS X0208 */
len -= 2;
*p++ = LC_JISX0208; *p++ = LC_JISX0208;
*p++ = ((c1 & 0x3f) << 1) + 0x9f + (c2 > 0x9e); *p++ = ((c1 & 0x3f) << 1) + 0x9f + (c2 > 0x9e);
*p++ = c2 + ((c2 > 0x9e) ? 2 : 0x60) + (c2 < 0x80); *p++ = c2 + ((c2 > 0x9e) ? 2 : 0x60) + (c2 < 0x80);
} }
/* Eiji Tokuya patched begin */
else if ((k >= 0xeb40 && k < 0xf040) || (k >= 0xfc4c && k <= 0xfcfc)) else if ((k >= 0xeb40 && k < 0xf040) || (k >= 0xfc4c && k <= 0xfcfc))
{ {
/* NEC selection IBM kanji - Other undecided justice */ /* NEC selection IBM kanji - Other undecided justice */
/* Eiji Tokuya patched end */
*p++ = LC_JISX0208; *p++ = LC_JISX0208;
*p++ = PGEUCALTCODE >> 8; *p++ = PGEUCALTCODE >> 8;
*p++ = PGEUCALTCODE & 0xff; *p++ = PGEUCALTCODE & 0xff;
...@@ -237,7 +226,6 @@ sjis2mic(unsigned char *sjis, unsigned char *p, int len) ...@@ -237,7 +226,6 @@ sjis2mic(unsigned char *sjis, unsigned char *p, int len)
* UDC1 mapping to X0208 85 ku - 94 ku JIS code 0x7521 - * UDC1 mapping to X0208 85 ku - 94 ku JIS code 0x7521 -
* 0x7e7e EUC 0xf5a1 - 0xfefe * 0x7e7e EUC 0xf5a1 - 0xfefe
*/ */
len -= 2;
*p++ = LC_JISX0208; *p++ = LC_JISX0208;
c1 -= 0x6f; c1 -= 0x6f;
*p++ = ((c1 & 0x3f) << 1) + 0xf3 + (c2 > 0x9e); *p++ = ((c1 & 0x3f) << 1) + 0xf3 + (c2 > 0x9e);
...@@ -249,7 +237,6 @@ sjis2mic(unsigned char *sjis, unsigned char *p, int len) ...@@ -249,7 +237,6 @@ sjis2mic(unsigned char *sjis, unsigned char *p, int len)
* UDC2 mapping to X0212 85 ku - 94 ku JIS code 0x7521 - * UDC2 mapping to X0212 85 ku - 94 ku JIS code 0x7521 -
* 0x7e7e EUC 0x8ff5a1 - 0x8ffefe * 0x7e7e EUC 0x8ff5a1 - 0x8ffefe
*/ */
len -= 2;
*p++ = LC_JISX0212; *p++ = LC_JISX0212;
c1 -= 0x74; c1 -= 0x74;
*p++ = ((c1 & 0x3f) << 1) + 0xf3 + (c2 > 0x9e); *p++ = ((c1 & 0x3f) << 1) + 0xf3 + (c2 > 0x9e);
...@@ -259,9 +246,7 @@ sjis2mic(unsigned char *sjis, unsigned char *p, int len) ...@@ -259,9 +246,7 @@ sjis2mic(unsigned char *sjis, unsigned char *p, int len)
{ {
/* /*
* mapping IBM kanji to X0208 and X0212 * mapping IBM kanji to X0208 and X0212
*
*/ */
len -= 2;
for (i = 0;; i++) for (i = 0;; i++)
{ {
k2 = ibmkanji[i].sjis; k2 = ibmkanji[i].sjis;
...@@ -285,11 +270,16 @@ sjis2mic(unsigned char *sjis, unsigned char *p, int len) ...@@ -285,11 +270,16 @@ sjis2mic(unsigned char *sjis, unsigned char *p, int len)
} }
} }
} }
sjis += 2;
len -= 2;
} }
else else
{ /* should be ASCII */ { /* should be ASCII */
len--; if (c1 == 0)
report_invalid_encoding(PG_SJIS, (const char *) sjis, len);
*p++ = c1; *p++ = c1;
sjis++;
len--;
} }
} }
*p = '\0'; *p = '\0';
...@@ -299,22 +289,37 @@ sjis2mic(unsigned char *sjis, unsigned char *p, int len) ...@@ -299,22 +289,37 @@ sjis2mic(unsigned char *sjis, unsigned char *p, int len)
* MIC ---> SJIS * MIC ---> SJIS
*/ */
static void static void
mic2sjis(unsigned char *mic, unsigned char *p, int len) mic2sjis(const unsigned char *mic, unsigned char *p, int len)
{ {
int c1, int c1,
c2, c2,
k; k,
l;
while (len >= 0 && (c1 = *mic)) while (len > 0)
{ {
len -= pg_mic_mblen(mic++); c1 = *mic;
if (!IS_HIGHBIT_SET(c1))
{
/* ASCII */
if (c1 == 0)
report_invalid_encoding(PG_MULE_INTERNAL,
(const char *) mic, len);
*p++ = c1;
mic++;
len--;
continue;
}
l = pg_encoding_verifymb(PG_MULE_INTERNAL, (const char *) mic, len);
if (l < 0)
report_invalid_encoding(PG_MULE_INTERNAL,
(const char *) mic, len);
if (c1 == LC_JISX0201K) if (c1 == LC_JISX0201K)
*p++ = *mic++; *p++ = mic[1];
else if (c1 == LC_JISX0208) else if (c1 == LC_JISX0208)
{ {
c1 = *mic++; c1 = mic[1];
c2 = *mic++; c2 = mic[2];
k = (c1 << 8) | (c2 & 0xff); k = (c1 << 8) | (c2 & 0xff);
if (k >= 0xf5a1) if (k >= 0xf5a1)
{ {
...@@ -331,8 +336,8 @@ mic2sjis(unsigned char *mic, unsigned char *p, int len) ...@@ -331,8 +336,8 @@ mic2sjis(unsigned char *mic, unsigned char *p, int len)
int i, int i,
k2; k2;
c1 = *mic++; c1 = mic[1];
c2 = *mic++; c2 = mic[2];
k = c1 << 8 | c2; k = c1 << 8 | c2;
if (k >= 0xf5a1) if (k >= 0xf5a1)
{ {
...@@ -363,14 +368,11 @@ mic2sjis(unsigned char *mic, unsigned char *p, int len) ...@@ -363,14 +368,11 @@ mic2sjis(unsigned char *mic, unsigned char *p, int len)
} }
} }
} }
else if (IS_HIGHBIT_SET(c1))
{
/* cannot convert to SJIS! */
*p++ = PGSJISALTCODE >> 8;
*p++ = PGSJISALTCODE & 0xff;
}
else else
*p++ = c1; /* should be ASCII */ report_untranslatable_char(PG_MULE_INTERNAL, PG_SJIS,
(const char *) mic, len);
mic += l;
len -= l;
} }
*p = '\0'; *p = '\0';
} }
...@@ -379,37 +381,48 @@ mic2sjis(unsigned char *mic, unsigned char *p, int len) ...@@ -379,37 +381,48 @@ mic2sjis(unsigned char *mic, unsigned char *p, int len)
* EUC_JP ---> MIC * EUC_JP ---> MIC
*/ */
static void static void
euc_jp2mic(unsigned char *euc, unsigned char *p, int len) euc_jp2mic(const unsigned char *euc, unsigned char *p, int len)
{ {
int c1; int c1;
int l;
while (len >= 0 && (c1 = *euc++)) while (len > 0)
{ {
c1 = *euc;
if (!IS_HIGHBIT_SET(c1))
{
/* ASCII */
if (c1 == 0)
report_invalid_encoding(PG_EUC_JP,
(const char *) euc, len);
*p++ = c1;
euc++;
len--;
continue;
}
l = pg_encoding_verifymb(PG_EUC_JP, (const char *) euc, len);
if (l < 0)
report_invalid_encoding(PG_EUC_JP,
(const char *) euc, len);
if (c1 == SS2) if (c1 == SS2)
{ /* 1 byte kana? */ { /* 1 byte kana? */
len -= 2;
*p++ = LC_JISX0201K; *p++ = LC_JISX0201K;
*p++ = *euc++; *p++ = euc[1];
} }
else if (c1 == SS3) else if (c1 == SS3)
{ /* JIS X0212 kanji? */ { /* JIS X0212 kanji? */
len -= 3;
*p++ = LC_JISX0212; *p++ = LC_JISX0212;
*p++ = *euc++; *p++ = euc[1];
*p++ = *euc++; *p++ = euc[2];
} }
else if (c1 & 0x80) else
{ /* kanji? */ { /* kanji? */
len -= 2;
*p++ = LC_JISX0208; *p++ = LC_JISX0208;
*p++ = c1; *p++ = c1;
*p++ = *euc++; *p++ = euc[1];
}
else
{ /* should be ASCII */
len--;
*p++ = c1;
} }
euc += l;
len -= l;
} }
*p = '\0'; *p = '\0';
} }
...@@ -418,37 +431,50 @@ euc_jp2mic(unsigned char *euc, unsigned char *p, int len) ...@@ -418,37 +431,50 @@ euc_jp2mic(unsigned char *euc, unsigned char *p, int len)
* MIC ---> EUC_JP * MIC ---> EUC_JP
*/ */
static void static void
mic2euc_jp(unsigned char *mic, unsigned char *p, int len) mic2euc_jp(const unsigned char *mic, unsigned char *p, int len)
{ {
int c1; int c1;
int l;
while (len >= 0 && (c1 = *mic)) while (len > 0)
{ {
len -= pg_mic_mblen(mic++); c1 = *mic;
if (!IS_HIGHBIT_SET(c1))
{
/* ASCII */
if (c1 == 0)
report_invalid_encoding(PG_MULE_INTERNAL,
(const char *) mic, len);
*p++ = c1;
mic++;
len--;
continue;
}
l = pg_encoding_verifymb(PG_MULE_INTERNAL, (const char *) mic, len);
if (l < 0)
report_invalid_encoding(PG_MULE_INTERNAL,
(const char *) mic, len);
if (c1 == LC_JISX0201K) if (c1 == LC_JISX0201K)
{ {
*p++ = SS2; *p++ = SS2;
*p++ = *mic++; *p++ = mic[1];
} }
else if (c1 == LC_JISX0212) else if (c1 == LC_JISX0212)
{ {
*p++ = SS3; *p++ = SS3;
*p++ = *mic++; *p++ = mic[1];
*p++ = *mic++; *p++ = mic[2];
} }
else if (c1 == LC_JISX0208) else if (c1 == LC_JISX0208)
{ {
*p++ = *mic++; *p++ = mic[1];
*p++ = *mic++; *p++ = mic[2];
}
else if (IS_HIGHBIT_SET(c1))
{ /* cannot convert to EUC_JP! */
mic--;
pg_print_bogus_char(&mic, &p);
} }
else else
*p++ = c1; /* should be ASCII */ report_untranslatable_char(PG_MULE_INTERNAL, PG_EUC_JP,
(const char *) mic, len);
mic += l;
len -= l;
} }
*p = '\0'; *p = '\0';
} }
...@@ -457,30 +483,41 @@ mic2euc_jp(unsigned char *mic, unsigned char *p, int len) ...@@ -457,30 +483,41 @@ mic2euc_jp(unsigned char *mic, unsigned char *p, int len)
* EUC_JP -> SJIS * EUC_JP -> SJIS
*/ */
static void static void
euc_jp2sjis(unsigned char *euc, unsigned char *p, int len) euc_jp2sjis(const unsigned char *euc, unsigned char *p, int len)
{ {
int c1, int c1,
c2, c2,
k; k;
unsigned char *euc_end = euc + len; int l;
while (euc_end >= euc && (c1 = *euc++)) while (len > 0)
{ {
if (c1 < 0x80) c1 = *euc;
if (!IS_HIGHBIT_SET(c1))
{ {
/* should be ASCII */ /* ASCII */
if (c1 == 0)
report_invalid_encoding(PG_EUC_JP,
(const char *) euc, len);
*p++ = c1; *p++ = c1;
euc++;
len--;
continue;
} }
else if (c1 == SS2) l = pg_encoding_verifymb(PG_EUC_JP, (const char *) euc, len);
if (l < 0)
report_invalid_encoding(PG_EUC_JP,
(const char *) euc, len);
if (c1 == SS2)
{ {
/* hankaku kana? */ /* hankaku kana? */
*p++ = *euc++; *p++ = euc[1];
} }
else if (c1 == SS3) else if (c1 == SS3)
{ {
/* JIS X0212 kanji? */ /* JIS X0212 kanji? */
c1 = *euc++; c1 = euc[1];
c2 = *euc++; c2 = euc[2];
k = c1 << 8 | c2; k = c1 << 8 | c2;
if (k >= 0xf5a1) if (k >= 0xf5a1)
{ {
...@@ -517,7 +554,7 @@ euc_jp2sjis(unsigned char *euc, unsigned char *p, int len) ...@@ -517,7 +554,7 @@ euc_jp2sjis(unsigned char *euc, unsigned char *p, int len)
else else
{ {
/* JIS X0208 kanji? */ /* JIS X0208 kanji? */
c2 = *euc++; c2 = euc[1];
k = (c1 << 8) | (c2 & 0xff); k = (c1 << 8) | (c2 & 0xff);
if (k >= 0xf5a1) if (k >= 0xf5a1)
{ {
...@@ -529,6 +566,8 @@ euc_jp2sjis(unsigned char *euc, unsigned char *p, int len) ...@@ -529,6 +566,8 @@ euc_jp2sjis(unsigned char *euc, unsigned char *p, int len)
*p++ = ((c1 - 0xa1) >> 1) + ((c1 < 0xdf) ? 0x81 : 0xc1); *p++ = ((c1 - 0xa1) >> 1) + ((c1 < 0xdf) ? 0x81 : 0xc1);
*p++ = c2 - ((c1 & 1) ? ((c2 < 0xe0) ? 0x61 : 0x60) : 2); *p++ = c2 - ((c1 & 1) ? ((c2 < 0xe0) ? 0x61 : 0x60) : 2);
} }
euc += l;
len -= l;
} }
*p = '\0'; *p = '\0';
} }
...@@ -537,23 +576,34 @@ euc_jp2sjis(unsigned char *euc, unsigned char *p, int len) ...@@ -537,23 +576,34 @@ euc_jp2sjis(unsigned char *euc, unsigned char *p, int len)
* SJIS ---> EUC_JP * SJIS ---> EUC_JP
*/ */
static void static void
sjis2euc_jp(unsigned char *sjis, unsigned char *p, int len) sjis2euc_jp(const unsigned char *sjis, unsigned char *p, int len)
{ {
int c1, int c1,
c2, c2,
i, i,
k, k,
k2; k2;
unsigned char *sjis_end = sjis + len; int l;
while (sjis_end >= sjis && (c1 = *sjis++)) while (len > 0)
{ {
if (c1 < 0x80) c1 = *sjis;
if (!IS_HIGHBIT_SET(c1))
{ {
/* should be ASCII */ /* ASCII */
if (c1 == 0)
report_invalid_encoding(PG_SJIS,
(const char *) sjis, len);
*p++ = c1; *p++ = c1;
sjis++;
len--;
continue;
} }
else if (c1 >= 0xa1 && c1 <= 0xdf) l = pg_encoding_verifymb(PG_SJIS, (const char *) sjis, len);
if (l < 0)
report_invalid_encoding(PG_SJIS,
(const char *) sjis, len);
if (c1 >= 0xa1 && c1 <= 0xdf)
{ {
/* JIS X0201 (1 byte kana) */ /* JIS X0201 (1 byte kana) */
*p++ = SS2; *p++ = SS2;
...@@ -564,12 +614,7 @@ sjis2euc_jp(unsigned char *sjis, unsigned char *p, int len) ...@@ -564,12 +614,7 @@ sjis2euc_jp(unsigned char *sjis, unsigned char *p, int len)
/* /*
* JIS X0208, X0212, user defined extended characters * JIS X0208, X0212, user defined extended characters
*/ */
c2 = *sjis++; c2 = sjis[1];
if (!ISSJISHEAD(c1) || !ISSJISTAIL(c2))
ereport(ERROR,
(errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
errmsg("invalid byte sequence for encoding \"SJIS\": 0x%02x%02x",
c1, c2)));
k = (c1 << 8) + c2; k = (c1 << 8) + c2;
if (k >= 0xed40 && k < 0xf040) if (k >= 0xed40 && k < 0xf040)
{ {
...@@ -650,6 +695,8 @@ sjis2euc_jp(unsigned char *sjis, unsigned char *p, int len) ...@@ -650,6 +695,8 @@ sjis2euc_jp(unsigned char *sjis, unsigned char *p, int len)
} }
} }
} }
sjis += l;
len -= l;
} }
*p = '\0'; *p = '\0';
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/euc_kr_and_mic/euc_kr_and_mic.c,v 1.13 2006/03/05 15:58:47 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/euc_kr_and_mic/euc_kr_and_mic.c,v 1.14 2006/05/21 20:05:19 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -32,8 +32,8 @@ extern Datum mic_to_euc_kr(PG_FUNCTION_ARGS); ...@@ -32,8 +32,8 @@ extern Datum mic_to_euc_kr(PG_FUNCTION_ARGS);
* ---------- * ----------
*/ */
static void euc_kr2mic(unsigned char *euc, unsigned char *p, int len); static void euc_kr2mic(const unsigned char *euc, unsigned char *p, int len);
static void mic2euc_kr(unsigned char *mic, unsigned char *p, int len); static void mic2euc_kr(const unsigned char *mic, unsigned char *p, int len);
Datum Datum
euc_kr_to_mic(PG_FUNCTION_ARGS) euc_kr_to_mic(PG_FUNCTION_ARGS)
...@@ -71,23 +71,34 @@ mic_to_euc_kr(PG_FUNCTION_ARGS) ...@@ -71,23 +71,34 @@ mic_to_euc_kr(PG_FUNCTION_ARGS)
* EUC_KR ---> MIC * EUC_KR ---> MIC
*/ */
static void static void
euc_kr2mic(unsigned char *euc, unsigned char *p, int len) euc_kr2mic(const unsigned char *euc, unsigned char *p, int len)
{ {
int c1; int c1;
int l;
while (len >= 0 && (c1 = *euc++)) while (len > 0)
{ {
c1 = *euc;
if (IS_HIGHBIT_SET(c1)) if (IS_HIGHBIT_SET(c1))
{ {
len -= 2; l = pg_encoding_verifymb(PG_EUC_KR, (const char *) euc, len);
if (l != 2)
report_invalid_encoding(PG_EUC_KR,
(const char *) euc, len);
*p++ = LC_KS5601; *p++ = LC_KS5601;
*p++ = c1; *p++ = c1;
*p++ = *euc++; *p++ = euc[1];
euc += 2;
len -= 2;
} }
else else
{ /* should be ASCII */ { /* should be ASCII */
len--; if (c1 == 0)
report_invalid_encoding(PG_EUC_KR,
(const char *) euc, len);
*p++ = c1; *p++ = c1;
euc++;
len--;
} }
} }
*p = '\0'; *p = '\0';
...@@ -97,26 +108,39 @@ euc_kr2mic(unsigned char *euc, unsigned char *p, int len) ...@@ -97,26 +108,39 @@ euc_kr2mic(unsigned char *euc, unsigned char *p, int len)
* MIC ---> EUC_KR * MIC ---> EUC_KR
*/ */
static void static void
mic2euc_kr(unsigned char *mic, unsigned char *p, int len) mic2euc_kr(const unsigned char *mic, unsigned char *p, int len)
{ {
int c1; int c1;
int l;
while (len >= 0 && (c1 = *mic)) while (len > 0)
{ {
len -= pg_mic_mblen(mic++); c1 = *mic;
if (!IS_HIGHBIT_SET(c1))
if (c1 == LC_KS5601)
{ {
*p++ = *mic++; /* ASCII */
*p++ = *mic++; if (c1 == 0)
report_invalid_encoding(PG_MULE_INTERNAL,
(const char *) mic, len);
*p++ = c1;
mic++;
len--;
continue;
} }
else if (IS_HIGHBIT_SET(c1)) l = pg_encoding_verifymb(PG_MULE_INTERNAL, (const char *) mic, len);
{ /* cannot convert to EUC_KR! */ if (l < 0)
mic--; report_invalid_encoding(PG_MULE_INTERNAL,
pg_print_bogus_char(&mic, &p); (const char *) mic, len);
if (c1 == LC_KS5601)
{
*p++ = mic[1];
*p++ = mic[2];
} }
else else
*p++ = c1; /* should be ASCII */ report_untranslatable_char(PG_MULE_INTERNAL, PG_EUC_KR,
(const char *) mic, len);
mic += l;
len -= l;
} }
*p = '\0'; *p = '\0';
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/euc_tw_and_big5/euc_tw_and_big5.c,v 1.13 2006/03/05 15:58:47 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/euc_tw_and_big5/euc_tw_and_big5.c,v 1.14 2006/05/21 20:05:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -42,10 +42,10 @@ extern Datum mic_to_big5(PG_FUNCTION_ARGS); ...@@ -42,10 +42,10 @@ extern Datum mic_to_big5(PG_FUNCTION_ARGS);
* ---------- * ----------
*/ */
static void big52mic(unsigned char *big5, unsigned char *p, int len); static void big52mic(const unsigned char *big5, unsigned char *p, int len);
static void mic2big5(unsigned char *mic, unsigned char *p, int len); static void mic2big5(const unsigned char *mic, unsigned char *p, int len);
static void euc_tw2mic(unsigned char *euc, unsigned char *p, int len); static void euc_tw2mic(const unsigned char *euc, unsigned char *p, int len);
static void mic2euc_tw(unsigned char *mic, unsigned char *p, int len); static void mic2euc_tw(const unsigned char *mic, unsigned char *p, int len);
Datum Datum
euc_tw_to_big5(PG_FUNCTION_ARGS) euc_tw_to_big5(PG_FUNCTION_ARGS)
...@@ -114,7 +114,7 @@ mic_to_euc_tw(PG_FUNCTION_ARGS) ...@@ -114,7 +114,7 @@ mic_to_euc_tw(PG_FUNCTION_ARGS)
Assert(PG_GETARG_INT32(1) == PG_EUC_TW); Assert(PG_GETARG_INT32(1) == PG_EUC_TW);
Assert(len >= 0); Assert(len >= 0);
mic2big5(src, dest, len); mic2euc_tw(src, dest, len);
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
...@@ -155,16 +155,23 @@ mic_to_big5(PG_FUNCTION_ARGS) ...@@ -155,16 +155,23 @@ mic_to_big5(PG_FUNCTION_ARGS)
* EUC_TW ---> MIC * EUC_TW ---> MIC
*/ */
static void static void
euc_tw2mic(unsigned char *euc, unsigned char *p, int len) euc_tw2mic(const unsigned char *euc, unsigned char *p, int len)
{ {
int c1; int c1;
int l;
while (len >= 0 && (c1 = *euc++)) while (len > 0)
{
c1 = *euc;
if (IS_HIGHBIT_SET(c1))
{ {
l = pg_encoding_verifymb(PG_EUC_TW, (const char *) euc, len);
if (l < 0)
report_invalid_encoding(PG_EUC_TW,
(const char *) euc, len);
if (c1 == SS2) if (c1 == SS2)
{ {
len -= 4; c1 = euc[1]; /* plane No. */
c1 = *euc++; /* plane No. */
if (c1 == 0xa1) if (c1 == 0xa1)
*p++ = LC_CNS11643_1; *p++ = LC_CNS11643_1;
else if (c1 == 0xa2) else if (c1 == 0xa2)
...@@ -172,22 +179,28 @@ euc_tw2mic(unsigned char *euc, unsigned char *p, int len) ...@@ -172,22 +179,28 @@ euc_tw2mic(unsigned char *euc, unsigned char *p, int len)
else else
{ {
*p++ = 0x9d; /* LCPRV2 */ *p++ = 0x9d; /* LCPRV2 */
*p++ = 0xa3 - c1 + LC_CNS11643_3; *p++ = c1 - 0xa3 + LC_CNS11643_3;
} }
*p++ = *euc++; *p++ = euc[2];
*p++ = *euc++; *p++ = euc[3];
} }
else if (IS_HIGHBIT_SET(c1)) else
{ /* CNS11643-1 */ { /* CNS11643-1 */
len -= 2;
*p++ = LC_CNS11643_1; *p++ = LC_CNS11643_1;
*p++ = c1; *p++ = c1;
*p++ = *euc++; *p++ = euc[1];
}
euc += l;
len -= l;
} }
else else
{ /* should be ASCII */ { /* should be ASCII */
len--; if (c1 == 0)
report_invalid_encoding(PG_EUC_TW,
(const char *) euc, len);
*p++ = c1; *p++ = c1;
euc++;
len--;
} }
} }
*p = '\0'; *p = '\0';
...@@ -197,40 +210,54 @@ euc_tw2mic(unsigned char *euc, unsigned char *p, int len) ...@@ -197,40 +210,54 @@ euc_tw2mic(unsigned char *euc, unsigned char *p, int len)
* MIC ---> EUC_TW * MIC ---> EUC_TW
*/ */
static void static void
mic2euc_tw(unsigned char *mic, unsigned char *p, int len) mic2euc_tw(const unsigned char *mic, unsigned char *p, int len)
{ {
int c1; int c1;
int l;
while (len >= 0 && (c1 = *mic)) while (len > 0)
{ {
len -= pg_mic_mblen(mic++); c1 = *mic;
if (!IS_HIGHBIT_SET(c1))
{
/* ASCII */
if (c1 == 0)
report_invalid_encoding(PG_MULE_INTERNAL,
(const char *) mic, len);
*p++ = c1;
mic++;
len--;
continue;
}
l = pg_encoding_verifymb(PG_MULE_INTERNAL, (const char *) mic, len);
if (l < 0)
report_invalid_encoding(PG_MULE_INTERNAL,
(const char *) mic, len);
if (c1 == LC_CNS11643_1) if (c1 == LC_CNS11643_1)
{ {
*p++ = *mic++; *p++ = mic[1];
*p++ = *mic++; *p++ = mic[2];
} }
else if (c1 == LC_CNS11643_2) else if (c1 == LC_CNS11643_2)
{ {
*p++ = SS2; *p++ = SS2;
*p++ = 0xa2; *p++ = 0xa2;
*p++ = *mic++; *p++ = mic[1];
*p++ = *mic++; *p++ = mic[2];
} }
else if (c1 == 0x9d) else if (c1 == 0x9d &&
mic[1] >= LC_CNS11643_3 && mic[1] <= LC_CNS11643_7)
{ /* LCPRV2? */ { /* LCPRV2? */
*p++ = SS2; *p++ = SS2;
*p++ = *mic++ - LC_CNS11643_3 + 0xa3; *p++ = mic[1] - LC_CNS11643_3 + 0xa3;
*p++ = *mic++; *p++ = mic[2];
*p++ = *mic++; *p++ = mic[3];
}
else if (IS_HIGHBIT_SET(c1))
{ /* cannot convert to EUC_TW! */
mic--;
pg_print_bogus_char(&mic, &p);
} }
else else
*p++ = c1; /* should be ASCII */ report_untranslatable_char(PG_MULE_INTERNAL, PG_EUC_TW,
(const char *) mic, len);
mic += l;
len -= l;
} }
*p = '\0'; *p = '\0';
} }
...@@ -239,28 +266,33 @@ mic2euc_tw(unsigned char *mic, unsigned char *p, int len) ...@@ -239,28 +266,33 @@ mic2euc_tw(unsigned char *mic, unsigned char *p, int len)
* Big5 ---> MIC * Big5 ---> MIC
*/ */
static void static void
big52mic(unsigned char *big5, unsigned char *p, int len) big52mic(const unsigned char *big5, unsigned char *p, int len)
{ {
unsigned short c1; unsigned short c1;
unsigned short big5buf, unsigned short big5buf,
cnsBuf; cnsBuf;
unsigned char lc; unsigned char lc;
char bogusBuf[3]; int l;
int i;
while (len >= 0 && (c1 = *big5++)) while (len > 0)
{ {
c1 = *big5;
if (!IS_HIGHBIT_SET(c1)) if (!IS_HIGHBIT_SET(c1))
{ /* ASCII */ {
len--; /* ASCII */
if (c1 == 0)
report_invalid_encoding(PG_BIG5,
(const char *) big5, len);
*p++ = c1; *p++ = c1;
big5++;
len--;
continue;
} }
else l = pg_encoding_verifymb(PG_BIG5, (const char *) big5, len);
{ if (l < 0)
len -= 2; report_invalid_encoding(PG_BIG5,
big5buf = c1 << 8; (const char *) big5, len);
c1 = *big5++; big5buf = (c1 << 8) | big5[1];
big5buf |= c1;
cnsBuf = BIG5toCNS(big5buf, &lc); cnsBuf = BIG5toCNS(big5buf, &lc);
if (lc != 0) if (lc != 0)
{ {
...@@ -273,18 +305,10 @@ big52mic(unsigned char *big5, unsigned char *p, int len) ...@@ -273,18 +305,10 @@ big52mic(unsigned char *big5, unsigned char *p, int len)
*p++ = cnsBuf & 0x00ff; *p++ = cnsBuf & 0x00ff;
} }
else else
{ /* cannot convert */ report_untranslatable_char(PG_BIG5, PG_MULE_INTERNAL,
big5 -= 2; (const char *) big5, len);
*p++ = '('; big5 += l;
for (i = 0; i < 2; i++) len -= l;
{
sprintf(bogusBuf, "%02x", *big5++);
*p++ = bogusBuf[0];
*p++ = bogusBuf[1];
}
*p++ = ')';
}
}
} }
*p = '\0'; *p = '\0';
} }
...@@ -293,46 +317,55 @@ big52mic(unsigned char *big5, unsigned char *p, int len) ...@@ -293,46 +317,55 @@ big52mic(unsigned char *big5, unsigned char *p, int len)
* MIC ---> Big5 * MIC ---> Big5
*/ */
static void static void
mic2big5(unsigned char *mic, unsigned char *p, int len) mic2big5(const unsigned char *mic, unsigned char *p, int len)
{ {
int l;
unsigned short c1; unsigned short c1;
unsigned short big5buf, unsigned short big5buf,
cnsBuf; cnsBuf;
int l;
while (len >= 0 && (c1 = *mic)) while (len > 0)
{ {
l = pg_mic_mblen(mic++); c1 = *mic;
len -= l; if (!IS_HIGHBIT_SET(c1))
{
/* ASCII */
if (c1 == 0)
report_invalid_encoding(PG_MULE_INTERNAL,
(const char *) mic, len);
*p++ = c1;
mic++;
len--;
continue;
}
l = pg_encoding_verifymb(PG_MULE_INTERNAL, (const char *) mic, len);
if (l < 0)
report_invalid_encoding(PG_MULE_INTERNAL,
(const char *) mic, len);
/* 0x9d means LCPRV2 */ /* 0x9d means LCPRV2 */
if (c1 == LC_CNS11643_1 || c1 == LC_CNS11643_2 || c1 == 0x9d) if (c1 == LC_CNS11643_1 || c1 == LC_CNS11643_2 || c1 == 0x9d)
{ {
if (c1 == 0x9d) if (c1 == 0x9d)
{ {
c1 = *mic++; /* get plane no. */ c1 = mic[1]; /* get plane no. */
} cnsBuf = (mic[2] << 8) | mic[3];
cnsBuf = (*mic++) << 8;
cnsBuf |= (*mic++) & 0x00ff;
big5buf = CNStoBIG5(cnsBuf, c1);
if (big5buf == 0)
{ /* cannot convert to Big5! */
mic -= l;
pg_print_bogus_char(&mic, &p);
} }
else else
{ {
cnsBuf = (mic[1] << 8) | mic[2];
}
big5buf = CNStoBIG5(cnsBuf, c1);
if (big5buf == 0)
report_untranslatable_char(PG_MULE_INTERNAL, PG_BIG5,
(const char *) mic, len);
*p++ = (big5buf >> 8) & 0x00ff; *p++ = (big5buf >> 8) & 0x00ff;
*p++ = big5buf & 0x00ff; *p++ = big5buf & 0x00ff;
} }
}
else if (!IS_HIGHBIT_SET(c1)) /* ASCII */
*p++ = c1;
else else
{ /* cannot convert to Big5! */ report_untranslatable_char(PG_MULE_INTERNAL, PG_BIG5,
mic--; (const char *) mic, len);
pg_print_bogus_char(&mic, &p); mic += l;
} len -= l;
} }
*p = '\0'; *p = '\0';
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/latin2_and_win1250/latin2_and_win1250.c,v 1.11 2006/03/05 15:58:47 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/latin2_and_win1250/latin2_and_win1250.c,v 1.12 2006/05/21 20:05:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -42,10 +42,10 @@ extern Datum win1250_to_latin2(PG_FUNCTION_ARGS); ...@@ -42,10 +42,10 @@ extern Datum win1250_to_latin2(PG_FUNCTION_ARGS);
* ---------- * ----------
*/ */
static void latin22mic(unsigned char *l, unsigned char *p, int len); static void latin22mic(const unsigned char *l, unsigned char *p, int len);
static void mic2latin2(unsigned char *mic, unsigned char *p, int len); static void mic2latin2(const unsigned char *mic, unsigned char *p, int len);
static void win12502mic(unsigned char *l, unsigned char *p, int len); static void win12502mic(const unsigned char *l, unsigned char *p, int len);
static void mic2win1250(unsigned char *mic, unsigned char *p, int len); static void mic2win1250(const unsigned char *mic, unsigned char *p, int len);
Datum Datum
latin2_to_mic(PG_FUNCTION_ARGS) latin2_to_mic(PG_FUNCTION_ARGS)
...@@ -152,14 +152,15 @@ win1250_to_latin2(PG_FUNCTION_ARGS) ...@@ -152,14 +152,15 @@ win1250_to_latin2(PG_FUNCTION_ARGS)
} }
static void static void
latin22mic(unsigned char *l, unsigned char *p, int len) latin22mic(const unsigned char *l, unsigned char *p, int len)
{ {
latin2mic(l, p, len, LC_ISO8859_2); latin2mic(l, p, len, LC_ISO8859_2, PG_LATIN2);
} }
static void static void
mic2latin2(unsigned char *mic, unsigned char *p, int len) mic2latin2(const unsigned char *mic, unsigned char *p, int len)
{ {
mic2latin(mic, p, len, LC_ISO8859_2); mic2latin(mic, p, len, LC_ISO8859_2, PG_LATIN2);
} }
/*----------------------------------------------------------------- /*-----------------------------------------------------------------
...@@ -167,9 +168,9 @@ mic2latin2(unsigned char *mic, unsigned char *p, int len) ...@@ -167,9 +168,9 @@ mic2latin2(unsigned char *mic, unsigned char *p, int len)
* Microsoft's CP1250(windows-1250) * Microsoft's CP1250(windows-1250)
*-----------------------------------------------------------------*/ *-----------------------------------------------------------------*/
static void static void
win12502mic(unsigned char *l, unsigned char *p, int len) win12502mic(const unsigned char *l, unsigned char *p, int len)
{ {
static unsigned char win1250_2_iso88592[] = { static const unsigned char win1250_2_iso88592[] = {
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0xA9, 0x8B, 0xA6, 0xAB, 0xAE, 0xAC, 0x88, 0x89, 0xA9, 0x8B, 0xA6, 0xAB, 0xAE, 0xAC,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
...@@ -188,12 +189,14 @@ win12502mic(unsigned char *l, unsigned char *p, int len) ...@@ -188,12 +189,14 @@ win12502mic(unsigned char *l, unsigned char *p, int len)
0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
}; };
latin2mic_with_table(l, p, len, LC_ISO8859_2, win1250_2_iso88592); latin2mic_with_table(l, p, len, LC_ISO8859_2, PG_WIN1250,
win1250_2_iso88592);
} }
static void static void
mic2win1250(unsigned char *mic, unsigned char *p, int len) mic2win1250(const unsigned char *mic, unsigned char *p, int len)
{ {
static unsigned char iso88592_2_win1250[] = { static const unsigned char iso88592_2_win1250[] = {
0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87, 0x80, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
0x88, 0x89, 0x00, 0x8B, 0x00, 0x00, 0x00, 0x00, 0x88, 0x89, 0x00, 0x8B, 0x00, 0x00, 0x00, 0x00,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97,
...@@ -212,5 +215,6 @@ mic2win1250(unsigned char *mic, unsigned char *p, int len) ...@@ -212,5 +215,6 @@ mic2win1250(unsigned char *mic, unsigned char *p, int len)
0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
}; };
mic2latin_with_table(mic, p, len, LC_ISO8859_2, iso88592_2_win1250); mic2latin_with_table(mic, p, len, LC_ISO8859_2, PG_WIN1250,
iso88592_2_win1250);
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/latin_and_mic/latin_and_mic.c,v 1.11 2006/03/05 15:58:47 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/latin_and_mic/latin_and_mic.c,v 1.12 2006/05/21 20:05:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -40,12 +40,12 @@ extern Datum mic_to_latin4(PG_FUNCTION_ARGS); ...@@ -40,12 +40,12 @@ extern Datum mic_to_latin4(PG_FUNCTION_ARGS);
* ---------- * ----------
*/ */
static void latin12mic(unsigned char *l, unsigned char *p, int len); static void latin12mic(const unsigned char *l, unsigned char *p, int len);
static void mic2latin1(unsigned char *mic, unsigned char *p, int len); static void mic2latin1(const unsigned char *mic, unsigned char *p, int len);
static void latin32mic(unsigned char *l, unsigned char *p, int len); static void latin32mic(const unsigned char *l, unsigned char *p, int len);
static void mic2latin3(unsigned char *mic, unsigned char *p, int len); static void mic2latin3(const unsigned char *mic, unsigned char *p, int len);
static void latin42mic(unsigned char *l, unsigned char *p, int len); static void latin42mic(const unsigned char *l, unsigned char *p, int len);
static void mic2latin4(unsigned char *mic, unsigned char *p, int len); static void mic2latin4(const unsigned char *mic, unsigned char *p, int len);
Datum Datum
latin1_to_mic(PG_FUNCTION_ARGS) latin1_to_mic(PG_FUNCTION_ARGS)
...@@ -144,32 +144,37 @@ mic_to_latin4(PG_FUNCTION_ARGS) ...@@ -144,32 +144,37 @@ mic_to_latin4(PG_FUNCTION_ARGS)
} }
static void static void
latin12mic(unsigned char *l, unsigned char *p, int len) latin12mic(const unsigned char *l, unsigned char *p, int len)
{ {
latin2mic(l, p, len, LC_ISO8859_1); latin2mic(l, p, len, LC_ISO8859_1, PG_LATIN1);
} }
static void static void
mic2latin1(unsigned char *mic, unsigned char *p, int len) mic2latin1(const unsigned char *mic, unsigned char *p, int len)
{ {
mic2latin(mic, p, len, LC_ISO8859_1); mic2latin(mic, p, len, LC_ISO8859_1, PG_LATIN1);
} }
static void static void
latin32mic(unsigned char *l, unsigned char *p, int len) latin32mic(const unsigned char *l, unsigned char *p, int len)
{ {
latin2mic(l, p, len, LC_ISO8859_3); latin2mic(l, p, len, LC_ISO8859_3, PG_LATIN3);
} }
static void static void
mic2latin3(unsigned char *mic, unsigned char *p, int len) mic2latin3(const unsigned char *mic, unsigned char *p, int len)
{ {
mic2latin(mic, p, len, LC_ISO8859_3); mic2latin(mic, p, len, LC_ISO8859_3, PG_LATIN3);
} }
static void static void
latin42mic(unsigned char *l, unsigned char *p, int len) latin42mic(const unsigned char *l, unsigned char *p, int len)
{ {
latin2mic(l, p, len, LC_ISO8859_4); latin2mic(l, p, len, LC_ISO8859_4, PG_LATIN4);
} }
static void static void
mic2latin4(unsigned char *mic, unsigned char *p, int len) mic2latin4(const unsigned char *mic, unsigned char *p, int len)
{ {
mic2latin(mic, p, len, LC_ISO8859_4); mic2latin(mic, p, len, LC_ISO8859_4, PG_LATIN4);
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_ascii/utf8_and_ascii.c,v 1.12 2006/03/05 15:58:47 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_ascii/utf8_and_ascii.c,v 1.13 2006/05/21 20:05:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -43,6 +43,7 @@ ascii_to_utf8(PG_FUNCTION_ARGS) ...@@ -43,6 +43,7 @@ ascii_to_utf8(PG_FUNCTION_ARGS)
Assert(PG_GETARG_INT32(1) == PG_UTF8); Assert(PG_GETARG_INT32(1) == PG_UTF8);
Assert(len >= 0); Assert(len >= 0);
/* this looks wrong, but basically we're just rejecting high-bit-set */
pg_ascii2mic(src, dest, len); pg_ascii2mic(src, dest, len);
PG_RETURN_VOID(); PG_RETURN_VOID();
...@@ -59,6 +60,7 @@ utf8_to_ascii(PG_FUNCTION_ARGS) ...@@ -59,6 +60,7 @@ utf8_to_ascii(PG_FUNCTION_ARGS)
Assert(PG_GETARG_INT32(1) == PG_SQL_ASCII); Assert(PG_GETARG_INT32(1) == PG_SQL_ASCII);
Assert(len >= 0); Assert(len >= 0);
/* this looks wrong, but basically we're just rejecting high-bit-set */
pg_mic2ascii(src, dest, len); pg_mic2ascii(src, dest, len);
PG_RETURN_VOID(); PG_RETURN_VOID();
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_big5/utf8_and_big5.c,v 1.12 2006/03/05 15:58:47 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_big5/utf8_and_big5.c,v 1.13 2006/05/21 20:05:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -62,7 +62,7 @@ utf8_to_big5(PG_FUNCTION_ARGS) ...@@ -62,7 +62,7 @@ utf8_to_big5(PG_FUNCTION_ARGS)
Assert(len >= 0); Assert(len >= 0);
UtfToLocal(src, dest, ULmapBIG5, UtfToLocal(src, dest, ULmapBIG5,
sizeof(ULmapBIG5) / sizeof(pg_utf_to_local), len); sizeof(ULmapBIG5) / sizeof(pg_utf_to_local), PG_BIG5, len);
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_cyrillic/utf8_and_cyrillic.c,v 1.14 2006/03/05 15:58:47 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_cyrillic/utf8_and_cyrillic.c,v 1.15 2006/05/21 20:05:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -46,7 +46,7 @@ utf8_to_koi8r(PG_FUNCTION_ARGS) ...@@ -46,7 +46,7 @@ utf8_to_koi8r(PG_FUNCTION_ARGS)
Assert(len >= 0); Assert(len >= 0);
UtfToLocal(src, dest, ULmapKOI8R, UtfToLocal(src, dest, ULmapKOI8R,
sizeof(ULmapKOI8R) / sizeof(pg_utf_to_local), len); sizeof(ULmapKOI8R) / sizeof(pg_utf_to_local), PG_KOI8R, len);
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_euc_cn/utf8_and_euc_cn.c,v 1.13 2006/03/05 15:58:47 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_euc_cn/utf8_and_euc_cn.c,v 1.14 2006/05/21 20:05:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -62,7 +62,7 @@ utf8_to_euc_cn(PG_FUNCTION_ARGS) ...@@ -62,7 +62,7 @@ utf8_to_euc_cn(PG_FUNCTION_ARGS)
Assert(len >= 0); Assert(len >= 0);
UtfToLocal(src, dest, ULmapEUC_CN, UtfToLocal(src, dest, ULmapEUC_CN,
sizeof(ULmapEUC_CN) / sizeof(pg_utf_to_local), len); sizeof(ULmapEUC_CN) / sizeof(pg_utf_to_local), PG_EUC_CN, len);
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_euc_jp/utf8_and_euc_jp.c,v 1.13 2006/03/05 15:58:48 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_euc_jp/utf8_and_euc_jp.c,v 1.14 2006/05/21 20:05:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -62,7 +62,7 @@ utf8_to_euc_jp(PG_FUNCTION_ARGS) ...@@ -62,7 +62,7 @@ utf8_to_euc_jp(PG_FUNCTION_ARGS)
Assert(len >= 0); Assert(len >= 0);
UtfToLocal(src, dest, ULmapEUC_JP, UtfToLocal(src, dest, ULmapEUC_JP,
sizeof(ULmapEUC_JP) / sizeof(pg_utf_to_local), len); sizeof(ULmapEUC_JP) / sizeof(pg_utf_to_local), PG_EUC_JP, len);
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_euc_kr/utf8_and_euc_kr.c,v 1.13 2006/03/05 15:58:48 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_euc_kr/utf8_and_euc_kr.c,v 1.14 2006/05/21 20:05:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -62,7 +62,7 @@ utf8_to_euc_kr(PG_FUNCTION_ARGS) ...@@ -62,7 +62,7 @@ utf8_to_euc_kr(PG_FUNCTION_ARGS)
Assert(len >= 0); Assert(len >= 0);
UtfToLocal(src, dest, ULmapEUC_KR, UtfToLocal(src, dest, ULmapEUC_KR,
sizeof(ULmapEUC_KR) / sizeof(pg_utf_to_local), len); sizeof(ULmapEUC_KR) / sizeof(pg_utf_to_local), PG_EUC_KR, len);
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_euc_tw/utf8_and_euc_tw.c,v 1.13 2006/03/05 15:58:48 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_euc_tw/utf8_and_euc_tw.c,v 1.14 2006/05/21 20:05:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -62,7 +62,7 @@ utf8_to_euc_tw(PG_FUNCTION_ARGS) ...@@ -62,7 +62,7 @@ utf8_to_euc_tw(PG_FUNCTION_ARGS)
Assert(len >= 0); Assert(len >= 0);
UtfToLocal(src, dest, ULmapEUC_TW, UtfToLocal(src, dest, ULmapEUC_TW,
sizeof(ULmapEUC_TW) / sizeof(pg_utf_to_local), len); sizeof(ULmapEUC_TW) / sizeof(pg_utf_to_local), PG_EUC_TW, len);
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_gb18030/utf8_and_gb18030.c,v 1.13 2006/03/05 15:58:48 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_gb18030/utf8_and_gb18030.c,v 1.14 2006/05/21 20:05:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -62,7 +62,7 @@ utf8_to_gb18030(PG_FUNCTION_ARGS) ...@@ -62,7 +62,7 @@ utf8_to_gb18030(PG_FUNCTION_ARGS)
Assert(len >= 0); Assert(len >= 0);
UtfToLocal(src, dest, ULmapGB18030, UtfToLocal(src, dest, ULmapGB18030,
sizeof(ULmapGB18030) / sizeof(pg_utf_to_local), len); sizeof(ULmapGB18030) / sizeof(pg_utf_to_local), PG_GB18030, len);
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_gbk/utf8_and_gbk.c,v 1.12 2006/03/05 15:58:48 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_gbk/utf8_and_gbk.c,v 1.13 2006/05/21 20:05:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -62,7 +62,7 @@ utf8_to_gbk(PG_FUNCTION_ARGS) ...@@ -62,7 +62,7 @@ utf8_to_gbk(PG_FUNCTION_ARGS)
Assert(len >= 0); Assert(len >= 0);
UtfToLocal(src, dest, ULmapGBK, UtfToLocal(src, dest, ULmapGBK,
sizeof(ULmapGBK) / sizeof(pg_utf_to_local), len); sizeof(ULmapGBK) / sizeof(pg_utf_to_local), PG_GBK, len);
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c,v 1.18 2006/03/05 15:58:48 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_iso8859/utf8_and_iso8859.c,v 1.19 2006/05/21 20:05:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -153,7 +153,7 @@ utf8_to_iso8859(PG_FUNCTION_ARGS) ...@@ -153,7 +153,7 @@ utf8_to_iso8859(PG_FUNCTION_ARGS)
{ {
if (encoding == maps[i].encoding) if (encoding == maps[i].encoding)
{ {
UtfToLocal(src, dest, maps[i].map2, maps[i].size2, len); UtfToLocal(src, dest, maps[i].map2, maps[i].size2, encoding, len);
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
} }
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_iso8859_1/utf8_and_iso8859_1.c,v 1.15 2006/03/05 15:58:48 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_iso8859_1/utf8_and_iso8859_1.c,v 1.16 2006/05/21 20:05:20 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -44,8 +44,11 @@ iso8859_1_to_utf8(PG_FUNCTION_ARGS) ...@@ -44,8 +44,11 @@ iso8859_1_to_utf8(PG_FUNCTION_ARGS)
Assert(PG_GETARG_INT32(1) == PG_UTF8); Assert(PG_GETARG_INT32(1) == PG_UTF8);
Assert(len >= 0); Assert(len >= 0);
while (len-- > 0 && (c = *src++)) while (len > 0)
{ {
c = *src;
if (c == 0)
report_invalid_encoding(PG_LATIN1, (const char *) src, len);
if (!IS_HIGHBIT_SET(c)) if (!IS_HIGHBIT_SET(c))
*dest++ = c; *dest++ = c;
else else
...@@ -53,6 +56,8 @@ iso8859_1_to_utf8(PG_FUNCTION_ARGS) ...@@ -53,6 +56,8 @@ iso8859_1_to_utf8(PG_FUNCTION_ARGS)
*dest++ = (c >> 6) | 0xc0; *dest++ = (c >> 6) | 0xc0;
*dest++ = (c & 0x003f) | HIGHBIT; *dest++ = (c & 0x003f) | HIGHBIT;
} }
src++;
len--;
} }
*dest = '\0'; *dest = '\0';
...@@ -66,32 +71,44 @@ utf8_to_iso8859_1(PG_FUNCTION_ARGS) ...@@ -66,32 +71,44 @@ utf8_to_iso8859_1(PG_FUNCTION_ARGS)
unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3); unsigned char *dest = (unsigned char *) PG_GETARG_CSTRING(3);
int len = PG_GETARG_INT32(4); int len = PG_GETARG_INT32(4);
unsigned short c, unsigned short c,
c1, c1;
c2;
Assert(PG_GETARG_INT32(0) == PG_UTF8); Assert(PG_GETARG_INT32(0) == PG_UTF8);
Assert(PG_GETARG_INT32(1) == PG_LATIN1); Assert(PG_GETARG_INT32(1) == PG_LATIN1);
Assert(len >= 0); Assert(len >= 0);
while (len >= 0 && (c = *src++)) while (len > 0)
{ {
if ((c & 0xe0) == 0xc0) c = *src;
if (c == 0)
report_invalid_encoding(PG_UTF8, (const char *) src, len);
/* fast path for ASCII-subset characters */
if (!IS_HIGHBIT_SET(c))
{ {
c1 = c & 0x1f; *dest++ = c;
c2 = *src++ & 0x3f; src++;
*dest = c1 << 6; len--;
*dest++ |= c2;
len -= 2;
} }
else if ((c & 0xe0) == 0xe0)
ereport(WARNING,
(errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
errmsg("ignoring unconvertible UTF-8 character 0x%04x",
c)));
else else
{ {
*dest++ = c; int l = pg_utf_mblen(src);
len--;
if (l > len || !pg_utf8_islegal(src, l))
report_invalid_encoding(PG_UTF8, (const char *) src, len);
if (l != 2)
report_untranslatable_char(PG_UTF8, PG_LATIN1,
(const char *) src, len);
c1 = src[1] & 0x3f;
c = ((c & 0x1f) << 6) | c1;
if (c >= 0x80 && c <= 0xff)
{
*dest++ = (unsigned char) c;
src += 2;
len -= 2;
}
else
report_untranslatable_char(PG_UTF8, PG_LATIN1,
(const char *) src, len);
} }
} }
*dest = '\0'; *dest = '\0';
......
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_johab/utf8_and_johab.c,v 1.13 2006/03/05 15:58:48 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_johab/utf8_and_johab.c,v 1.14 2006/05/21 20:05:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -62,7 +62,7 @@ utf8_to_johab(PG_FUNCTION_ARGS) ...@@ -62,7 +62,7 @@ utf8_to_johab(PG_FUNCTION_ARGS)
Assert(len >= 0); Assert(len >= 0);
UtfToLocal(src, dest, ULmapJOHAB, UtfToLocal(src, dest, ULmapJOHAB,
sizeof(ULmapJOHAB) / sizeof(pg_utf_to_local), len); sizeof(ULmapJOHAB) / sizeof(pg_utf_to_local), PG_JOHAB, len);
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_sjis/utf8_and_sjis.c,v 1.12 2006/03/05 15:58:48 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_sjis/utf8_and_sjis.c,v 1.13 2006/05/21 20:05:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -62,7 +62,7 @@ utf8_to_sjis(PG_FUNCTION_ARGS) ...@@ -62,7 +62,7 @@ utf8_to_sjis(PG_FUNCTION_ARGS)
Assert(len >= 0); Assert(len >= 0);
UtfToLocal(src, dest, ULmapSJIS, UtfToLocal(src, dest, ULmapSJIS,
sizeof(ULmapSJIS) / sizeof(pg_utf_to_local), len); sizeof(ULmapSJIS) / sizeof(pg_utf_to_local), PG_SJIS, len);
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_uhc/utf8_and_uhc.c,v 1.12 2006/03/05 15:58:48 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_uhc/utf8_and_uhc.c,v 1.13 2006/05/21 20:05:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -62,7 +62,7 @@ utf8_to_uhc(PG_FUNCTION_ARGS) ...@@ -62,7 +62,7 @@ utf8_to_uhc(PG_FUNCTION_ARGS)
Assert(len >= 0); Assert(len >= 0);
UtfToLocal(src, dest, ULmapUHC, UtfToLocal(src, dest, ULmapUHC,
sizeof(ULmapUHC) / sizeof(pg_utf_to_local), len); sizeof(ULmapUHC) / sizeof(pg_utf_to_local), PG_UHC, len);
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
...@@ -6,7 +6,7 @@ ...@@ -6,7 +6,7 @@
* Portions Copyright (c) 1994, Regents of the University of California * Portions Copyright (c) 1994, Regents of the University of California
* *
* IDENTIFICATION * IDENTIFICATION
* $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c,v 1.2 2006/03/05 15:58:48 momjian Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/conversion_procs/utf8_and_win/utf8_and_win.c,v 1.3 2006/05/21 20:05:21 tgl Exp $
* *
*------------------------------------------------------------------------- *-------------------------------------------------------------------------
*/ */
...@@ -143,7 +143,7 @@ utf8_to_win(PG_FUNCTION_ARGS) ...@@ -143,7 +143,7 @@ utf8_to_win(PG_FUNCTION_ARGS)
{ {
if (encoding == maps[i].encoding) if (encoding == maps[i].encoding)
{ {
UtfToLocal(src, dest, maps[i].map2, maps[i].size2, len); UtfToLocal(src, dest, maps[i].map2, maps[i].size2, encoding, len);
PG_RETURN_VOID(); PG_RETURN_VOID();
} }
} }
......
...@@ -4,7 +4,7 @@ ...@@ -4,7 +4,7 @@
* (currently mule internal code (mic) is used) * (currently mule internal code (mic) is used)
* Tatsuo Ishii * Tatsuo Ishii
* *
* $PostgreSQL: pgsql/src/backend/utils/mb/mbutils.c,v 1.55 2006/01/12 22:04:02 neilc Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/mbutils.c,v 1.56 2006/05/21 20:05:19 tgl Exp $
*/ */
#include "postgres.h" #include "postgres.h"
...@@ -362,8 +362,49 @@ pg_client_to_server(const char *s, int len) ...@@ -362,8 +362,49 @@ pg_client_to_server(const char *s, int len)
Assert(DatabaseEncoding); Assert(DatabaseEncoding);
Assert(ClientEncoding); Assert(ClientEncoding);
if (ClientEncoding->encoding == DatabaseEncoding->encoding) if (len <= 0)
return (char *) s;
if (ClientEncoding->encoding == DatabaseEncoding->encoding ||
ClientEncoding->encoding == PG_SQL_ASCII)
{
/*
* No conversion is needed, but we must still validate the data.
*/
(void) pg_verify_mbstr(DatabaseEncoding->encoding, s, len, false);
return (char *) s; return (char *) s;
}
if (DatabaseEncoding->encoding == PG_SQL_ASCII)
{
/*
* No conversion is possible, but we must still validate the data,
* because the client-side code might have done string escaping
* using the selected client_encoding. If the client encoding is
* ASCII-safe then we just do a straight validation under that
* encoding. For an ASCII-unsafe encoding we have a problem:
* we dare not pass such data to the parser but we have no way
* to convert it. We compromise by rejecting the data if it
* contains any non-ASCII characters.
*/
if (PG_VALID_BE_ENCODING(ClientEncoding->encoding))
(void) pg_verify_mbstr(ClientEncoding->encoding, s, len, false);
else
{
int i;
for (i = 0; i < len; i++)
{
if (s[i] == '\0' || IS_HIGHBIT_SET(s[i]))
ereport(ERROR,
(errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
errmsg("invalid byte value for encoding \"%s\": 0x%02x",
pg_enc2name_tbl[PG_SQL_ASCII].name,
(unsigned char) s[i])));
}
}
return (char *) s;
}
return perform_default_encoding_conversion(s, len, true); return perform_default_encoding_conversion(s, len, true);
} }
...@@ -377,9 +418,14 @@ pg_server_to_client(const char *s, int len) ...@@ -377,9 +418,14 @@ pg_server_to_client(const char *s, int len)
Assert(DatabaseEncoding); Assert(DatabaseEncoding);
Assert(ClientEncoding); Assert(ClientEncoding);
if (ClientEncoding->encoding == DatabaseEncoding->encoding) if (len <= 0)
return (char *) s; return (char *) s;
if (ClientEncoding->encoding == DatabaseEncoding->encoding ||
ClientEncoding->encoding == PG_SQL_ASCII ||
DatabaseEncoding->encoding == PG_SQL_ASCII)
return (char *) s; /* assume data is valid */
return perform_default_encoding_conversion(s, len, false); return perform_default_encoding_conversion(s, len, false);
} }
...@@ -398,9 +444,6 @@ perform_default_encoding_conversion(const char *src, int len, bool is_client_to_ ...@@ -398,9 +444,6 @@ perform_default_encoding_conversion(const char *src, int len, bool is_client_to_
dest_encoding; dest_encoding;
FmgrInfo *flinfo; FmgrInfo *flinfo;
if (len <= 0)
return (char *) src;
if (is_client_to_server) if (is_client_to_server)
{ {
src_encoding = ClientEncoding->encoding; src_encoding = ClientEncoding->encoding;
...@@ -417,12 +460,6 @@ perform_default_encoding_conversion(const char *src, int len, bool is_client_to_ ...@@ -417,12 +460,6 @@ perform_default_encoding_conversion(const char *src, int len, bool is_client_to_
if (flinfo == NULL) if (flinfo == NULL)
return (char *) src; return (char *) src;
if (src_encoding == dest_encoding)
return (char *) src;
if (src_encoding == PG_SQL_ASCII || dest_encoding == PG_SQL_ASCII)
return (char *) src;
result = palloc(len * 4 + 1); result = palloc(len * 4 + 1);
FunctionCall5(flinfo, FunctionCall5(flinfo,
......
/* /*
* conversion functions between pg_wchar and multibyte streams. * conversion functions between pg_wchar and multibyte streams.
* Tatsuo Ishii * Tatsuo Ishii
* $PostgreSQL: pgsql/src/backend/utils/mb/wchar.c,v 1.54 2006/02/18 16:15:22 petere Exp $ * $PostgreSQL: pgsql/src/backend/utils/mb/wchar.c,v 1.55 2006/05/21 20:05:19 tgl Exp $
* *
* WIN1250 client encoding updated by Pavel Behal * WIN1250 client encoding updated by Pavel Behal
* *
...@@ -19,17 +19,21 @@ ...@@ -19,17 +19,21 @@
/* /*
* conversion to pg_wchar is done by "table driven." * conversion to pg_wchar is done by "table driven."
* to add an encoding support, define mb2wchar_with_len(), mblen() * to add an encoding support, define mb2wchar_with_len(), mblen(), dsplen()
* for the particular encoding. Note that if the encoding is only * for the particular encoding. Note that if the encoding is only
* supported in the client, you don't need to define * supported in the client, you don't need to define
* mb2wchar_with_len() function (SJIS is the case). * mb2wchar_with_len() function (SJIS is the case).
* *
* These functions generally assume that their input is validly formed.
* The "verifier" functions, further down in the file, have to be more
* paranoid. We expect that mblen() does not need to examine more than
* the first byte of the character to discover the correct length.
*
* Note: for the display output of psql to work properly, the return values * Note: for the display output of psql to work properly, the return values
* of these functions must conform to the Unicode standard. In particular * of the dsplen functions must conform to the Unicode standard. In particular
* the NUL character is zero width and control characters are generally * the NUL character is zero width and control characters are generally
* width -1. It is recommended that non-ASCII encodings refer their ASCII * width -1. It is recommended that non-ASCII encodings refer their ASCII
* subset to the ASCII routines to ensure consistancy. * subset to the ASCII routines to ensure consistency.
*
*/ */
/* /*
...@@ -109,7 +113,7 @@ static int pg_euc2wchar_with_len ...@@ -109,7 +113,7 @@ static int pg_euc2wchar_with_len
return cnt; return cnt;
} }
static int static inline int
pg_euc_mblen(const unsigned char *s) pg_euc_mblen(const unsigned char *s)
{ {
int len; int len;
...@@ -125,7 +129,7 @@ pg_euc_mblen(const unsigned char *s) ...@@ -125,7 +129,7 @@ pg_euc_mblen(const unsigned char *s)
return len; return len;
} }
static int static inline int
pg_euc_dsplen(const unsigned char *s) pg_euc_dsplen(const unsigned char *s)
{ {
int len; int len;
...@@ -316,7 +320,7 @@ pg_euctw_mblen(const unsigned char *s) ...@@ -316,7 +320,7 @@ pg_euctw_mblen(const unsigned char *s)
else if (IS_HIGHBIT_SET(*s)) else if (IS_HIGHBIT_SET(*s))
len = 2; len = 2;
else else
len = pg_ascii_dsplen(s); len = 1;
return len; return len;
} }
...@@ -409,7 +413,7 @@ pg_utf2wchar_with_len(const unsigned char *from, pg_wchar *to, int len) ...@@ -409,7 +413,7 @@ pg_utf2wchar_with_len(const unsigned char *from, pg_wchar *to, int len)
} }
/* /*
* returns the byte length of a UTF8 word pointed to by s * returns the byte length of a UTF8 character pointed to by s
*/ */
int int
pg_utf_mblen(const unsigned char *s) pg_utf_mblen(const unsigned char *s)
...@@ -680,7 +684,20 @@ pg_mule_mblen(const unsigned char *s) ...@@ -680,7 +684,20 @@ pg_mule_mblen(const unsigned char *s)
static int static int
pg_mule_dsplen(const unsigned char *s) pg_mule_dsplen(const unsigned char *s)
{ {
return pg_ascii_dsplen(s); /* XXX fix me! */ int len;
if (IS_LC1(*s))
len = 1;
else if (IS_LCPRV1(*s))
len = 1;
else if (IS_LC2(*s))
len = 2;
else if (IS_LCPRV2(*s))
len = 2;
else
len = 1; /* assume ASCII */
return len;
} }
/* /*
...@@ -860,207 +877,605 @@ pg_gb18030_dsplen(const unsigned char *s) ...@@ -860,207 +877,605 @@ pg_gb18030_dsplen(const unsigned char *s)
return len; return len;
} }
/*
*-------------------------------------------------------------------
* multibyte sequence validators
*
* These functions accept "s", a pointer to the first byte of a string,
* and "len", the remaining length of the string. If there is a validly
* encoded character beginning at *s, return its length in bytes; else
* return -1.
*
* The functions can assume that len > 0 and that *s != '\0', but they must
* test for and reject zeroes in any additional bytes of a multibyte character.
*
* Note that this definition allows the function for a single-byte
* encoding to be just "return 1".
*-------------------------------------------------------------------
*/
pg_wchar_tbl pg_wchar_table[] = { static int
{pg_ascii2wchar_with_len, pg_ascii_mblen, pg_ascii_dsplen, 1}, /* 0; PG_SQL_ASCII */ pg_ascii_verifier(const unsigned char *s, int len)
{pg_eucjp2wchar_with_len, pg_eucjp_mblen, pg_eucjp_dsplen, 3}, /* 1; PG_EUC_JP */ {
{pg_euccn2wchar_with_len, pg_euccn_mblen, pg_euccn_dsplen, 3}, /* 2; PG_EUC_CN */ return 1;
{pg_euckr2wchar_with_len, pg_euckr_mblen, pg_euckr_dsplen, 3}, /* 3; PG_EUC_KR */ }
{pg_euctw2wchar_with_len, pg_euctw_mblen, pg_euctw_dsplen, 3}, /* 4; PG_EUC_TW */
{pg_johab2wchar_with_len, pg_johab_mblen, pg_johab_dsplen, 3}, /* 5; PG_JOHAB */
{pg_utf2wchar_with_len, pg_utf_mblen, pg_utf_dsplen, 4}, /* 6; PG_UTF8 */
{pg_mule2wchar_with_len, pg_mule_mblen, pg_mule_dsplen, 3}, /* 7; PG_MULE_INTERNAL */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 8; PG_LATIN1 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 9; PG_LATIN2 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 10; PG_LATIN3 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 11; PG_LATIN4 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 12; PG_LATIN5 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 13; PG_LATIN6 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 14; PG_LATIN7 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 15; PG_LATIN8 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 16; PG_LATIN9 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 17; PG_LATIN10 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 18; PG_WIN1256 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 19; PG_WIN1258 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 20; PG_WIN874 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 21; PG_KOI8 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 22; PG_WIN1251 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 22; PG_WIN1252 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 23; PG_WIN866 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 24; ISO-8859-5 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 25; ISO-8859-6 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 26; ISO-8859-7 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 27; ISO-8859-8 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 28; PG_WIN1250 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 29; PG_WIN1253 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 30; PG_WIN1254 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 31; PG_WIN1255 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, 1}, /* 32; PG_WIN1257 */
{0, pg_sjis_mblen, pg_sjis_dsplen, 2}, /* 33; PG_SJIS */
{0, pg_big5_mblen, pg_big5_dsplen, 2}, /* 34; PG_BIG5 */
{0, pg_gbk_mblen, pg_gbk_dsplen, 2}, /* 35; PG_GBK */
{0, pg_uhc_mblen, pg_uhc_dsplen, 2}, /* 36; PG_UHC */
{0, pg_gb18030_mblen, pg_gb18030_dsplen, 2} /* 37; PG_GB18030 */
};
/* returns the byte length of a word for mule internal code */ #define IS_EUC_RANGE_VALID(c) ((c) >= 0xa1 && (c) <= 0xfe)
int
pg_mic_mblen(const unsigned char *mbstr) static int
pg_eucjp_verifier(const unsigned char *s, int len)
{ {
return pg_mule_mblen(mbstr); int l;
unsigned char c1, c2;
c1 = *s++;
switch (c1)
{
case SS2: /* JIS X 0201 */
l = 2;
if (l > len)
return -1;
c2 = *s++;
if (c2 < 0xa1 || c2 > 0xdf)
return -1;
break;
case SS3: /* JIS X 0212 */
l = 3;
if (l > len)
return -1;
c2 = *s++;
if (!IS_EUC_RANGE_VALID(c2))
return -1;
c2 = *s++;
if (!IS_EUC_RANGE_VALID(c2))
return -1;
break;
default:
if (IS_HIGHBIT_SET(c1)) /* JIS X 0208? */
{
l = 2;
if (l > len)
return -1;
if (!IS_EUC_RANGE_VALID(c1))
return -1;
c2 = *s++;
if (!IS_EUC_RANGE_VALID(c2))
return -1;
}
else /* must be ASCII */
{
l = 1;
}
break;
}
return l;
} }
/* static int
* Returns the byte length of a multibyte word. pg_euckr_verifier(const unsigned char *s, int len)
*/
int
pg_encoding_mblen(int encoding, const char *mbstr)
{ {
Assert(PG_VALID_ENCODING(encoding)); int l;
unsigned char c1, c2;
return ((encoding >= 0 && c1 = *s++;
encoding < sizeof(pg_wchar_table) / sizeof(pg_wchar_tbl)) ?
((*pg_wchar_table[encoding].mblen) ((const unsigned char *) mbstr)) : if (IS_HIGHBIT_SET(c1))
((*pg_wchar_table[PG_SQL_ASCII].mblen) ((const unsigned char *) mbstr))); {
l = 2;
if (l > len)
return -1;
if (!IS_EUC_RANGE_VALID(c1))
return -1;
c2 = *s++;
if (!IS_EUC_RANGE_VALID(c2))
return -1;
}
else /* must be ASCII */
{
l = 1;
}
return l;
} }
/* /* EUC-CN byte sequences are exactly same as EUC-KR */
* Returns the display length of a multibyte word. #define pg_euccn_verifier pg_euckr_verifier
*/
int static int
pg_encoding_dsplen(int encoding, const char *mbstr) pg_euctw_verifier(const unsigned char *s, int len)
{ {
Assert(PG_VALID_ENCODING(encoding)); int l;
unsigned char c1, c2;
return ((encoding >= 0 && c1 = *s++;
encoding < sizeof(pg_wchar_table) / sizeof(pg_wchar_tbl)) ?
((*pg_wchar_table[encoding].dsplen) ((const unsigned char *) mbstr)) : switch (c1)
((*pg_wchar_table[PG_SQL_ASCII].dsplen) ((const unsigned char *) mbstr))); {
case SS2: /* CNS 11643 Plane 1-7 */
l = 4;
if (l > len)
return -1;
c2 = *s++;
if (c2 < 0xa1 || c2 > 0xa7)
return -1;
c2 = *s++;
if (!IS_EUC_RANGE_VALID(c2))
return -1;
c2 = *s++;
if (!IS_EUC_RANGE_VALID(c2))
return -1;
break;
case SS3: /* unused */
return -1;
default:
if (IS_HIGHBIT_SET(c1)) /* CNS 11643 Plane 1 */
{
l = 2;
if (l > len)
return -1;
/* no further range check on c1? */
c2 = *s++;
if (!IS_EUC_RANGE_VALID(c2))
return -1;
}
else /* must be ASCII */
{
l = 1;
}
break;
}
return l;
} }
/* static int
* fetch maximum length of a char encoding pg_johab_verifier(const unsigned char *s, int len)
*/
int
pg_encoding_max_length(int encoding)
{ {
Assert(PG_VALID_ENCODING(encoding)); int l, mbl;
unsigned char c;
return pg_wchar_table[encoding].maxmblen; l = mbl = pg_johab_mblen(s);
if (len < l)
return -1;
if (!IS_HIGHBIT_SET(*s))
return mbl;
while (--l > 0)
{
c = *++s;
if (!IS_EUC_RANGE_VALID(c))
return -1;
}
return mbl;
} }
#ifndef FRONTEND static int
pg_mule_verifier(const unsigned char *s, int len)
{
int l, mbl;
unsigned char c;
l = mbl = pg_mule_mblen(s);
if (len < l)
return -1;
while (--l > 0)
{
c = *++s;
if (!IS_HIGHBIT_SET(c))
return -1;
}
return mbl;
}
static int
pg_latin1_verifier(const unsigned char *s, int len)
{
return 1;
}
static int
pg_sjis_verifier(const unsigned char *s, int len)
{
int l, mbl;
unsigned char c1, c2;
l = mbl = pg_sjis_mblen(s);
if (len < l)
return -1;
if (l == 1) /* pg_sjis_mblen already verified it */
return mbl;
c1 = *s++;
c2 = *s;
if (!ISSJISHEAD(c1) || !ISSJISTAIL(c2))
return -1;
return mbl;
}
static int
pg_big5_verifier(const unsigned char *s, int len)
{
int l, mbl;
l = mbl = pg_big5_mblen(s);
if (len < l)
return -1;
while (--l > 0)
{
if (*++s == '\0')
return -1;
}
return mbl;
}
static int
pg_gbk_verifier(const unsigned char *s, int len)
{
int l, mbl;
l = mbl = pg_gbk_mblen(s);
if (len < l)
return -1;
while (--l > 0)
{
if (*++s == '\0')
return -1;
}
return mbl;
}
static int
pg_uhc_verifier(const unsigned char *s, int len)
{
int l, mbl;
l = mbl = pg_uhc_mblen(s);
if (len < l)
return -1;
while (--l > 0)
{
if (*++s == '\0')
return -1;
}
return mbl;
}
static int
pg_gb18030_verifier(const unsigned char *s, int len)
{
int l, mbl;
l = mbl = pg_gb18030_mblen(s);
if (len < l)
return -1;
while (--l > 0)
{
if (*++s == '\0')
return -1;
}
return mbl;
}
static int
pg_utf8_verifier(const unsigned char *s, int len)
{
int l = pg_utf_mblen(s);
if (len < l)
return -1;
if (!pg_utf8_islegal(s, l))
return -1;
return l;
}
/*
* Check for validity of a single UTF-8 encoded character
*
* This directly implements the rules in RFC3629. The bizarre-looking
* restrictions on the second byte are meant to ensure that there isn't
* more than one encoding of a given Unicode character point; that is,
* you may not use a longer-than-necessary byte sequence with high order
* zero bits to represent a character that would fit in fewer bytes.
* To do otherwise is to create security hazards (eg, create an apparent
* non-ASCII character that decodes to plain ASCII).
*
* length is assumed to have been obtained by pg_utf_mblen(), and the
* caller must have checked that that many bytes are present in the buffer.
*/
bool bool
pg_utf8_islegal(const unsigned char *source, int length) pg_utf8_islegal(const unsigned char *source, int length)
{ {
unsigned char a; unsigned char a;
const unsigned char *srcptr = source + length;
switch (length) switch (length)
{ {
default: default:
/* reject lengths 5 and 6 for now */
return false; return false;
/* Everything else falls through when "true"... */
case 4: case 4:
if ((a = (*--srcptr)) < 0x80 || a > 0xBF) a = source[3];
if (a < 0x80 || a > 0xBF)
return false; return false;
/* FALL THRU */
case 3: case 3:
if ((a = (*--srcptr)) < 0x80 || a > 0xBF) a = source[2];
if (a < 0x80 || a > 0xBF)
return false; return false;
/* FALL THRU */
case 2: case 2:
if ((a = (*--srcptr)) > 0xBF) a = source[1];
return false;
switch (*source) switch (*source)
{ {
/* no fall-through in this inner switch */
case 0xE0: case 0xE0:
if (a < 0xA0) if (a < 0xA0 || a > 0xBF)
return false; return false;
break; break;
case 0xED: case 0xED:
if (a > 0x9F) if (a < 0x80 || a > 0x9F)
return false; return false;
break; break;
case 0xF0: case 0xF0:
if (a < 0x90) if (a < 0x90 || a > 0xBF)
return false; return false;
break; break;
case 0xF4: case 0xF4:
if (a > 0x8F) if (a < 0x80 || a > 0x8F)
return false; return false;
break; break;
default: default:
if (a < 0x80) if (a < 0x80 || a > 0xBF)
return false; return false;
break;
} }
/* FALL THRU */
case 1: case 1:
if (*source >= 0x80 && *source < 0xC2) a = *source;
if (a >= 0x80 && a < 0xC2)
return false; return false;
} if (a > 0xF4)
if (*source > 0xF4)
return false; return false;
break;
}
return true; return true;
} }
/*
*-------------------------------------------------------------------
* encoding info table
*-------------------------------------------------------------------
*/
pg_wchar_tbl pg_wchar_table[] = {
{pg_ascii2wchar_with_len, pg_ascii_mblen, pg_ascii_dsplen, pg_ascii_verifier, 1}, /* 0; PG_SQL_ASCII */
{pg_eucjp2wchar_with_len, pg_eucjp_mblen, pg_eucjp_dsplen, pg_eucjp_verifier, 3}, /* 1; PG_EUC_JP */
{pg_euccn2wchar_with_len, pg_euccn_mblen, pg_euccn_dsplen, pg_euccn_verifier, 3}, /* 2; PG_EUC_CN */
{pg_euckr2wchar_with_len, pg_euckr_mblen, pg_euckr_dsplen, pg_euckr_verifier, 3}, /* 3; PG_EUC_KR */
{pg_euctw2wchar_with_len, pg_euctw_mblen, pg_euctw_dsplen, pg_euctw_verifier, 3}, /* 4; PG_EUC_TW */
{pg_johab2wchar_with_len, pg_johab_mblen, pg_johab_dsplen, pg_johab_verifier, 3}, /* 5; PG_JOHAB */
{pg_utf2wchar_with_len, pg_utf_mblen, pg_utf_dsplen, pg_utf8_verifier, 4}, /* 6; PG_UTF8 */
{pg_mule2wchar_with_len, pg_mule_mblen, pg_mule_dsplen, pg_mule_verifier, 3}, /* 7; PG_MULE_INTERNAL */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 8; PG_LATIN1 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 9; PG_LATIN2 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 10; PG_LATIN3 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 11; PG_LATIN4 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 12; PG_LATIN5 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 13; PG_LATIN6 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 14; PG_LATIN7 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 15; PG_LATIN8 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 16; PG_LATIN9 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 17; PG_LATIN10 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 18; PG_WIN1256 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 19; PG_WIN1258 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 20; PG_WIN874 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 21; PG_KOI8 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 22; PG_WIN1251 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 22; PG_WIN1252 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 23; PG_WIN866 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 24; ISO-8859-5 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 25; ISO-8859-6 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 26; ISO-8859-7 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 27; ISO-8859-8 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 28; PG_WIN1250 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 29; PG_WIN1253 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 30; PG_WIN1254 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 31; PG_WIN1255 */
{pg_latin12wchar_with_len, pg_latin1_mblen, pg_latin1_dsplen, pg_latin1_verifier, 1}, /* 32; PG_WIN1257 */
{0, pg_sjis_mblen, pg_sjis_dsplen, pg_sjis_verifier, 2}, /* 33; PG_SJIS */
{0, pg_big5_mblen, pg_big5_dsplen, pg_big5_verifier, 2}, /* 34; PG_BIG5 */
{0, pg_gbk_mblen, pg_gbk_dsplen, pg_gbk_verifier, 2}, /* 35; PG_GBK */
{0, pg_uhc_mblen, pg_uhc_dsplen, pg_uhc_verifier, 2}, /* 36; PG_UHC */
{0, pg_gb18030_mblen, pg_gb18030_dsplen, pg_gb18030_verifier, 2} /* 37; PG_GB18030 */
};
/* returns the byte length of a word for mule internal code */
int
pg_mic_mblen(const unsigned char *mbstr)
{
return pg_mule_mblen(mbstr);
}
/*
* Returns the byte length of a multibyte character.
*/
int
pg_encoding_mblen(int encoding, const char *mbstr)
{
Assert(PG_VALID_ENCODING(encoding));
return ((encoding >= 0 &&
encoding < sizeof(pg_wchar_table) / sizeof(pg_wchar_tbl)) ?
((*pg_wchar_table[encoding].mblen) ((const unsigned char *) mbstr)) :
((*pg_wchar_table[PG_SQL_ASCII].mblen) ((const unsigned char *) mbstr)));
}
/*
* Returns the display length of a multibyte character.
*/
int
pg_encoding_dsplen(int encoding, const char *mbstr)
{
Assert(PG_VALID_ENCODING(encoding));
return ((encoding >= 0 &&
encoding < sizeof(pg_wchar_table) / sizeof(pg_wchar_tbl)) ?
((*pg_wchar_table[encoding].dsplen) ((const unsigned char *) mbstr)) :
((*pg_wchar_table[PG_SQL_ASCII].dsplen) ((const unsigned char *) mbstr)));
}
/*
* Verify the first multibyte character of the given string.
* Return its byte length if good, -1 if bad. (See comments above for
* full details of the mbverify API.)
*/
int
pg_encoding_verifymb(int encoding, const char *mbstr, int len)
{
Assert(PG_VALID_ENCODING(encoding));
return ((encoding >= 0 &&
encoding < sizeof(pg_wchar_table) / sizeof(pg_wchar_tbl)) ?
((*pg_wchar_table[encoding].mbverify) ((const unsigned char *) mbstr, len)) :
((*pg_wchar_table[PG_SQL_ASCII].mbverify) ((const unsigned char *) mbstr, len)));
}
/*
* fetch maximum length of a given encoding
*/
int
pg_encoding_max_length(int encoding)
{
Assert(PG_VALID_ENCODING(encoding));
return pg_wchar_table[encoding].maxmblen;
}
#ifndef FRONTEND
/* /*
* Verify mbstr to make sure that it has a valid character sequence. * fetch maximum length of the encoding for the current database
* mbstr is not necessarily NULL terminated; length of mbstr is */
int
pg_database_encoding_max_length(void)
{
return pg_wchar_table[GetDatabaseEncoding()].maxmblen;
}
/*
* Verify mbstr to make sure that it is validly encoded in the current
* database encoding. Otherwise same as pg_verify_mbstr().
*/
bool
pg_verifymbstr(const char *mbstr, int len, bool noError)
{
return pg_verify_mbstr(GetDatabaseEncoding(), mbstr, len, noError);
}
/*
* Verify mbstr to make sure that it is validly encoded in the specified
* encoding.
*
* mbstr is not necessarily zero terminated; length of mbstr is
* specified by len. * specified by len.
* *
* If OK, return TRUE. If a problem is found, return FALSE when noError is * If OK, return TRUE. If a problem is found, return FALSE when noError is
* true; when noError is false, ereport() a descriptive message. * true; when noError is false, ereport() a descriptive message.
*/ */
bool bool
pg_verifymbstr(const char *mbstr, int len, bool noError) pg_verify_mbstr(int encoding, const char *mbstr, int len, bool noError)
{ {
int l; mbverifier mbverify;
int i;
int encoding; Assert(PG_VALID_ENCODING(encoding));
/*
* In single-byte encodings, we need only reject nulls (\0).
*/
if (pg_encoding_max_length(encoding) <= 1)
{
const char *nullpos = memchr(mbstr, 0, len);
/* we do not need any check in single-byte encodings */ if (nullpos == NULL)
if (pg_database_encoding_max_length() <= 1)
return true; return true;
if (noError)
return false;
report_invalid_encoding(encoding, nullpos, 1);
}
encoding = GetDatabaseEncoding(); /* fetch function pointer just once */
mbverify = pg_wchar_table[encoding].mbverify;
while (len > 0 && *mbstr) while (len > 0)
{ {
l = pg_mblen(mbstr); int l;
/* special UTF-8 check */ /* fast path for ASCII-subset characters */
if (encoding == PG_UTF8) if (!IS_HIGHBIT_SET(*mbstr))
{ {
if (!pg_utf8_islegal((const unsigned char *) mbstr, l)) if (*mbstr != '\0')
{ {
mbstr++;
len--;
continue;
}
if (noError) if (noError)
return false; return false;
ereport(ERROR, report_invalid_encoding(encoding, mbstr, len);
(errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
errmsg("invalid UTF-8 byte sequence detected near byte 0x%02x",
(unsigned char) *mbstr)));
}
} }
else
{ l = (*mbverify) ((const unsigned char *) mbstr, len);
for (i = 1; i < l; i++)
if (l < 0)
{ {
/* if (noError)
* we expect that every multibyte char consists of bytes return false;
* having the 8th bit set report_invalid_encoding(encoding, mbstr, len);
}
mbstr += l;
len -= l;
}
return true;
}
/*
* report_invalid_encoding: complain about invalid multibyte character
*
* note: len is remaining length of string, not length of character;
* len must be greater than zero, as we always examine the first byte.
*/ */
if (i >= len || !IS_HIGHBIT_SET(mbstr[i])) void
{ report_invalid_encoding(int encoding, const char *mbstr, int len)
{
int l = pg_encoding_mblen(encoding, mbstr);
char buf[8 * 2 + 1]; char buf[8 * 2 + 1];
char *p = buf; char *p = buf;
int j, int j,
jlimit; jlimit;
if (noError)
return false;
jlimit = Min(l, len); jlimit = Min(l, len);
jlimit = Min(jlimit, 8); /* prevent buffer overrun */ jlimit = Min(jlimit, 8); /* prevent buffer overrun */
...@@ -1070,23 +1485,38 @@ pg_verifymbstr(const char *mbstr, int len, bool noError) ...@@ -1070,23 +1485,38 @@ pg_verifymbstr(const char *mbstr, int len, bool noError)
ereport(ERROR, ereport(ERROR,
(errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE), (errcode(ERRCODE_CHARACTER_NOT_IN_REPERTOIRE),
errmsg("invalid byte sequence for encoding \"%s\": 0x%s", errmsg("invalid byte sequence for encoding \"%s\": 0x%s",
GetDatabaseEncodingName(), buf))); pg_enc2name_tbl[encoding].name,
} buf)));
}
}
len -= l;
mbstr += l;
}
return true;
} }
/* /*
* fetch maximum length of a char encoding for the current database * report_untranslatable_char: complain about untranslatable character
*
* note: len is remaining length of string, not length of character;
* len must be greater than zero, as we always examine the first byte.
*/ */
int void
pg_database_encoding_max_length(void) report_untranslatable_char(int src_encoding, int dest_encoding,
const char *mbstr, int len)
{ {
return pg_wchar_table[GetDatabaseEncoding()].maxmblen; int l = pg_encoding_mblen(src_encoding, mbstr);
char buf[8 * 2 + 1];
char *p = buf;
int j,
jlimit;
jlimit = Min(l, len);
jlimit = Min(jlimit, 8); /* prevent buffer overrun */
for (j = 0; j < jlimit; j++)
p += sprintf(p, "%02x", (unsigned char) mbstr[j]);
ereport(ERROR,
(errcode(ERRCODE_UNTRANSLATABLE_CHARACTER),
errmsg("character 0x%s of encoding \"%s\" has no equivalent in \"%s\"",
buf,
pg_enc2name_tbl[src_encoding].name,
pg_enc2name_tbl[dest_encoding].name)));
} }
#endif #endif
/* $PostgreSQL: pgsql/src/include/mb/pg_wchar.h,v 1.67 2006/02/18 16:15:23 petere Exp $ */ /* $PostgreSQL: pgsql/src/include/mb/pg_wchar.h,v 1.68 2006/05/21 20:05:21 tgl Exp $ */
#ifndef PG_WCHAR_H #ifndef PG_WCHAR_H
#define PG_WCHAR_H #define PG_WCHAR_H
...@@ -23,11 +23,17 @@ typedef unsigned int pg_wchar; ...@@ -23,11 +23,17 @@ typedef unsigned int pg_wchar;
#define SS2 0x8e /* single shift 2 (JIS0201) */ #define SS2 0x8e /* single shift 2 (JIS0201) */
#define SS3 0x8f /* single shift 3 (JIS0212) */ #define SS3 0x8f /* single shift 3 (JIS0212) */
/*
* SJIS validation macros
*/
#define ISSJISHEAD(c) (((c) >= 0x81 && (c) <= 0x9f) || ((c) >= 0xe0 && (c) <= 0xfc))
#define ISSJISTAIL(c) (((c) >= 0x40 && (c) <= 0x7e) || ((c) >= 0x80 && (c) <= 0xfc))
/* /*
* Leading byte types or leading prefix byte for MULE internal code. * Leading byte types or leading prefix byte for MULE internal code.
* See http://www.xemacs.org for more details. (there is a doc titled * See http://www.xemacs.org for more details. (there is a doc titled
* "XEmacs Internals Manual", "MULE Character Sets and Encodings" * "XEmacs Internals Manual", "MULE Character Sets and Encodings"
* section. * section.)
*/ */
/* /*
* Is a leading byte for "official" single byte encodings? * Is a leading byte for "official" single byte encodings?
...@@ -64,7 +70,7 @@ typedef unsigned int pg_wchar; ...@@ -64,7 +70,7 @@ typedef unsigned int pg_wchar;
#define LC_ISO8859_8 0x88 /* Hebrew (not supported yet) */ #define LC_ISO8859_8 0x88 /* Hebrew (not supported yet) */
#define LC_JISX0201K 0x89 /* Japanese 1 byte kana */ #define LC_JISX0201K 0x89 /* Japanese 1 byte kana */
#define LC_JISX0201R 0x8a /* Japanese 1 byte Roman */ #define LC_JISX0201R 0x8a /* Japanese 1 byte Roman */
/* Note that 0x8b seems to be unused in as of Emacs 20.7. /* Note that 0x8b seems to be unused as of Emacs 20.7.
* However, there might be a chance that 0x8b could be used * However, there might be a chance that 0x8b could be used
* in later version of Emacs. * in later version of Emacs.
*/ */
...@@ -135,13 +141,13 @@ typedef unsigned int pg_wchar; ...@@ -135,13 +141,13 @@ typedef unsigned int pg_wchar;
/* #define FREE 0xff free (unused) */ /* #define FREE 0xff free (unused) */
/* /*
* Encoding numeral identificators * PostgreSQL encoding identifiers
* *
* WARNING: the order of this table must be same as order * WARNING: the order of this table must be same as order
* in the pg_enc2name[] (mb/encnames.c) array! * in the pg_enc2name[] (mb/encnames.c) array!
* *
* If you add some encoding don'y forget check * If you add some encoding don't forget to check
* PG_ENCODING_[BE|FE]_LAST macros. * PG_ENCODING_BE_LAST macro.
* *
* The PG_SQL_ASCII is default encoding and must be = 0. * The PG_SQL_ASCII is default encoding and must be = 0.
*/ */
...@@ -208,8 +214,7 @@ typedef enum pg_enc ...@@ -208,8 +214,7 @@ typedef enum pg_enc
#define PG_VALID_ENCODING(_enc) \ #define PG_VALID_ENCODING(_enc) \
((_enc) >= 0 && (_enc) < _PG_LAST_ENCODING_) ((_enc) >= 0 && (_enc) < _PG_LAST_ENCODING_)
/* On FE are possible all encodings /* On FE are possible all encodings */
*/
#define PG_VALID_FE_ENCODING(_enc) PG_VALID_ENCODING(_enc) #define PG_VALID_FE_ENCODING(_enc) PG_VALID_ENCODING(_enc)
/* /*
...@@ -249,18 +254,21 @@ extern const char *pg_encoding_to_char(int encoding); ...@@ -249,18 +254,21 @@ extern const char *pg_encoding_to_char(int encoding);
typedef int (*mb2wchar_with_len_converter) (const unsigned char *from, typedef int (*mb2wchar_with_len_converter) (const unsigned char *from,
pg_wchar *to, pg_wchar *to,
int len); int len);
typedef int (*mblen_converter) (const unsigned char *mbstr); typedef int (*mblen_converter) (const unsigned char *mbstr);
typedef int (*mbdisplaylen_converter) (const unsigned char *mbstr); typedef int (*mbdisplaylen_converter) (const unsigned char *mbstr);
typedef int (*mbverifier) (const unsigned char *mbstr, int len);
typedef struct typedef struct
{ {
mb2wchar_with_len_converter mb2wchar_with_len; /* convert a multibyte mb2wchar_with_len_converter mb2wchar_with_len; /* convert a multibyte
* string to a wchar */ * string to a wchar */
mblen_converter mblen; /* returns the length of a multibyte char */ mblen_converter mblen; /* get byte length of a char */
mbdisplaylen_converter dsplen; /* returns the lenghth of a display mbdisplaylen_converter dsplen; /* get display width of a char */
* length */ mbverifier mbverify; /* verify multibyte sequence */
int maxmblen; /* max bytes for a char in this charset */ int maxmblen; /* max bytes for a char in this encoding */
} pg_wchar_tbl; } pg_wchar_tbl;
extern pg_wchar_tbl pg_wchar_table[]; extern pg_wchar_tbl pg_wchar_table[];
...@@ -293,6 +301,7 @@ extern int pg_mblen(const char *mbstr); ...@@ -293,6 +301,7 @@ extern int pg_mblen(const char *mbstr);
extern int pg_dsplen(const char *mbstr); extern int pg_dsplen(const char *mbstr);
extern int pg_encoding_mblen(int encoding, const char *mbstr); extern int pg_encoding_mblen(int encoding, const char *mbstr);
extern int pg_encoding_dsplen(int encoding, const char *mbstr); extern int pg_encoding_dsplen(int encoding, const char *mbstr);
extern int pg_encoding_verifymb(int encoding, const char *mbstr, int len);
extern int pg_mule_mblen(const unsigned char *mbstr); extern int pg_mule_mblen(const unsigned char *mbstr);
extern int pg_mic_mblen(const unsigned char *mbstr); extern int pg_mic_mblen(const unsigned char *mbstr);
extern int pg_mbstrlen(const char *mbstr); extern int pg_mbstrlen(const char *mbstr);
...@@ -326,21 +335,32 @@ extern char *pg_server_to_client(const char *s, int len); ...@@ -326,21 +335,32 @@ extern char *pg_server_to_client(const char *s, int len);
extern unsigned short BIG5toCNS(unsigned short big5, unsigned char *lc); extern unsigned short BIG5toCNS(unsigned short big5, unsigned char *lc);
extern unsigned short CNStoBIG5(unsigned short cns, unsigned char lc); extern unsigned short CNStoBIG5(unsigned short cns, unsigned char lc);
extern void LocalToUtf(unsigned char *iso, unsigned char *utf, extern void LocalToUtf(const unsigned char *iso, unsigned char *utf,
pg_local_to_utf *map, int size, int encoding, int len); const pg_local_to_utf *map, int size, int encoding, int len);
extern void UtfToLocal(unsigned char *utf, unsigned char *iso, extern void UtfToLocal(const unsigned char *utf, unsigned char *iso,
pg_utf_to_local *map, int size, int len); const pg_utf_to_local *map, int size, int encoding, int len);
extern bool pg_verifymbstr(const char *mbstr, int len, bool noError); extern bool pg_verifymbstr(const char *mbstr, int len, bool noError);
extern bool pg_verify_mbstr(int encoding, const char *mbstr, int len,
extern void pg_ascii2mic(unsigned char *src, unsigned char *dest, int len); bool noError);
extern void pg_mic2ascii(unsigned char *src, unsigned char *dest, int len);
extern void pg_print_bogus_char(unsigned char **mic, unsigned char **p); extern void report_invalid_encoding(int encoding, const char *mbstr, int len);
extern void latin2mic(unsigned char *l, unsigned char *p, int len, int lc); extern void report_untranslatable_char(int src_encoding, int dest_encoding,
extern void mic2latin(unsigned char *mic, unsigned char *p, int len, int lc); const char *mbstr, int len);
extern void latin2mic_with_table(unsigned char *l, unsigned char *p, int len, int lc, unsigned char *tab);
extern void mic2latin_with_table(unsigned char *mic, unsigned char *p, int len, int lc, unsigned char *tab); extern void pg_ascii2mic(const unsigned char *l, unsigned char *p, int len);
extern void pg_mic2ascii(const unsigned char *mic, unsigned char *p, int len);
extern void latin2mic(const unsigned char *l, unsigned char *p, int len,
int lc, int encoding);
extern void mic2latin(const unsigned char *mic, unsigned char *p, int len,
int lc, int encoding);
extern void latin2mic_with_table(const unsigned char *l, unsigned char *p,
int len, int lc, int encoding,
const unsigned char *tab);
extern void mic2latin_with_table(const unsigned char *mic, unsigned char *p,
int len, int lc, int encoding,
const unsigned char *tab);
extern bool pg_utf8_islegal(const unsigned char *source, int length); extern bool pg_utf8_islegal(const unsigned char *source, int length);
......
...@@ -9,7 +9,7 @@ insert into ...@@ -9,7 +9,7 @@ insert into
vacuum גђ; vacuum גђ;
select * from גђ; select * from גђ;
ђ | ʬ | 1a ђ | ʬ | 1a
-----------------------------------------+-----------------+---------------- ----------------------------+------------+------------
Ԓ咡ǒג쒥 | A01 | Ԓ咡ǒג쒥 | A01 |
Ԓ咡钥ՒÒ | ʬB10 | Ԓ咡钥ՒÒ | ʬB10 |
Ԓ咡ג풥钥ޒ | Z01 | Ԓ咡ג풥钥ޒ | Z01 |
...@@ -17,45 +17,45 @@ select * from ...@@ -17,45 +17,45 @@ select * from
select * from גђ where ʬ = 'Z01'; select * from גђ where ʬ = 'Z01';
ђ | ʬ | 1a ђ | ʬ | 1a
--------------------------------------+-----------------+---------------- --------------------------+------------+------------
Ԓ咡ג풥钥ޒ | Z01 | Ԓ咡ג풥钥ޒ | Z01 |
(1 row) (1 row)
select * from גђ where ʬ ~* 'z01'; select * from גђ where ʬ ~* 'z01';
ђ | ʬ | 1a ђ | ʬ | 1a
--------------------------------------+-----------------+---------------- --------------------------+------------+------------
Ԓ咡ג풥钥ޒ | Z01 | Ԓ咡ג풥钥ޒ | Z01 |
(1 row) (1 row)
select * from גђ where ʬ like '_Z01_'; select * from גђ where ʬ like '_Z01_';
ђ | ʬ | 1a ђ | ʬ | 1a
--------------------------------------+-----------------+---------------- --------------------------+------------+------------
Ԓ咡ג풥钥ޒ | Z01 | Ԓ咡ג풥钥ޒ | Z01 |
(1 row) (1 row)
select * from גђ where ʬ like '_Z%'; select * from גђ where ʬ like '_Z%';
ђ | ʬ | 1a ђ | ʬ | 1a
--------------------------------------+-----------------+---------------- --------------------------+------------+------------
Ԓ咡ג풥钥ޒ | Z01 | Ԓ咡ג풥钥ޒ | Z01 |
(1 row) (1 row)
select * from גђ where ђ ~ 'Ԓ咡[ǒ]'; select * from גђ where ђ ~ 'Ԓ咡[ǒ]';
ђ | ʬ | 1a ђ | ʬ | 1a
-----------------------------------------+-----------------+---------------- ----------------------------+------------+------------
Ԓ咡ǒג쒥 | A01 | Ԓ咡ǒג쒥 | A01 |
Ԓ咡钥ՒÒ | ʬB10 | Ԓ咡钥ՒÒ | ʬB10 |
(2 rows) (2 rows)
select * from גђ where ђ ~* 'Ԓ咡[ǒ]'; select * from גђ where ђ ~* 'Ԓ咡[ǒ]';
ђ | ʬ | 1a ђ | ʬ | 1a
-----------------------------------------+-----------------+---------------- ----------------------------+------------+------------
Ԓ咡ǒג쒥 | A01 | Ԓ咡ǒג쒥 | A01 |
Ԓ咡钥ՒÒ | ʬB10 | Ԓ咡钥ՒÒ | ʬB10 |
(2 rows) (2 rows)
select *,character_length(ђ) from גђ; select *,character_length(ђ) from גђ;
ђ | ʬ | 1a | character_length ђ | ʬ | 1a | character_length
-----------------------------------------+-----------------+----------------+------------------ ----------------------------+------------+------------+------------------
Ԓ咡ǒג쒥 | A01 | | 12 Ԓ咡ǒג쒥 | A01 | | 12
Ԓ咡钥ՒÒ | ʬB10 | | 13 Ԓ咡钥ՒÒ | ʬB10 | | 13
Ԓ咡ג풥钥ޒ | Z01 | | 12 Ԓ咡ג풥钥ޒ | Z01 | | 12
...@@ -63,7 +63,7 @@ select *,character_length( ...@@ -63,7 +63,7 @@ select *,character_length(
select *,octet_length(ђ) from גђ; select *,octet_length(ђ) from גђ;
ђ | ʬ | 1a | octet_length ђ | ʬ | 1a | octet_length
-----------------------------------------+-----------------+----------------+-------------- ----------------------------+------------+------------+--------------
Ԓ咡ǒג쒥 | A01 | | 36 Ԓ咡ǒג쒥 | A01 | | 36
Ԓ咡钥ՒÒ | ʬB10 | | 39 Ԓ咡钥ՒÒ | ʬB10 | | 39
Ԓ咡ג풥钥ޒ | Z01 | | 36 Ԓ咡ג풥钥ޒ | Z01 | | 36
...@@ -71,7 +71,7 @@ select *,octet_length( ...@@ -71,7 +71,7 @@ select *,octet_length(
select *,position('' in ђ) from גђ; select *,position('' in ђ) from גђ;
ђ | ʬ | 1a | position ђ | ʬ | 1a | position
-----------------------------------------+-----------------+----------------+---------- ----------------------------+------------+------------+----------
Ԓ咡ǒג쒥 | A01 | | 7 Ԓ咡ǒג쒥 | A01 | | 7
Ԓ咡钥ՒÒ | ʬB10 | | 0 Ԓ咡钥ՒÒ | ʬB10 | | 0
Ԓ咡ג풥钥ޒ | Z01 | | 0 Ԓ咡ג풥钥ޒ | Z01 | | 0
...@@ -79,7 +79,7 @@ select *,position(' ...@@ -79,7 +79,7 @@ select *,position('
select *,substring(ђ from 10 for 4) from גђ; select *,substring(ђ from 10 for 4) from גђ;
ђ | ʬ | 1a | substring ђ | ʬ | 1a | substring
-----------------------------------------+-----------------+----------------+-------------- ----------------------------+------------+------------+-----------
Ԓ咡ǒג쒥 | A01 | | ג쒥 Ԓ咡ǒג쒥 | A01 | | ג쒥
Ԓ咡钥ՒÒ | ʬB10 | | Ò Ԓ咡钥ՒÒ | ʬB10 | | Ò
Ԓ咡ג풥钥ޒ | Z01 | | 钥ޒ Ԓ咡ג풥钥ޒ | Z01 | | 钥ޒ
...@@ -96,7 +96,7 @@ insert into ...@@ -96,7 +96,7 @@ insert into
vacuum Ƒ㑻; vacuum Ƒ㑻;
select * from Ƒ㑻; select * from Ƒ㑻;
| ֑ | ע1a | ֑ | ע1a
-----------------+-----------+---------- ------------+---------+--------
ԑԑʾ | A01 | ԑԑʾ | A01 |
ԑͼ | B01 | ԑͼ | B01 |
ԑ̑Ա | Z01 | ԑ̑Ա | Z01 |
...@@ -104,45 +104,45 @@ select * from ...@@ -104,45 +104,45 @@ select * from
select * from Ƒ㑻 where ֑ = 'Z01'; select * from Ƒ㑻 where ֑ = 'Z01';
| ֑ | ע1a | ֑ | ע1a
-----------------+-----------+---------- ------------+---------+--------
ԑ̑Ա | Z01 | ԑ̑Ա | Z01 |
(1 row) (1 row)
select * from Ƒ㑻 where ֑ ~* 'z01'; select * from Ƒ㑻 where ֑ ~* 'z01';
| ֑ | ע1a | ֑ | ע1a
-----------------+-----------+---------- ------------+---------+--------
ԑ̑Ա | Z01 | ԑ̑Ա | Z01 |
(1 row) (1 row)
select * from Ƒ㑻 where ֑ like '_Z01_'; select * from Ƒ㑻 where ֑ like '_Z01_';
| ֑ | ע1a | ֑ | ע1a
-----------------+-----------+---------- ------------+---------+--------
ԑ̑Ա | Z01 | ԑ̑Ա | Z01 |
(1 row) (1 row)
select * from Ƒ㑻 where ֑ like '_Z%'; select * from Ƒ㑻 where ֑ like '_Z%';
| ֑ | ע1a | ֑ | ע1a
-----------------+-----------+---------- ------------+---------+--------
ԑ̑Ա | Z01 | ԑ̑Ա | Z01 |
(1 row) (1 row)
select * from Ƒ㑻 where ~ '[ԑͼ]'; select * from Ƒ㑻 where ~ '[ԑͼ]';
| ֑ | ע1a | ֑ | ע1a
-----------------+-----------+---------- ------------+---------+--------
ԑԑʾ | A01 | ԑԑʾ | A01 |
ԑͼ | B01 | ԑͼ | B01 |
(2 rows) (2 rows)
select * from Ƒ㑻 where ~* '[ԑͼ]'; select * from Ƒ㑻 where ~* '[ԑͼ]';
| ֑ | ע1a | ֑ | ע1a
-----------------+-----------+---------- ------------+---------+--------
ԑԑʾ | A01 | ԑԑʾ | A01 |
ԑͼ | B01 | ԑͼ | B01 |
(2 rows) (2 rows)
select *,character_length() from Ƒ㑻; select *,character_length() from Ƒ㑻;
| ֑ | ע1a | character_length | ֑ | ע1a | character_length
-----------------+-----------+----------+------------------ ------------+---------+--------+------------------
ԑԑʾ | A01 | | 5 ԑԑʾ | A01 | | 5
ԑͼ | B01 | | 4 ԑͼ | B01 | | 4
ԑ̑Ա | Z01 | | 5 ԑ̑Ա | Z01 | | 5
...@@ -150,7 +150,7 @@ select *,character_length( ...@@ -150,7 +150,7 @@ select *,character_length(
select *,octet_length() from Ƒ㑻; select *,octet_length() from Ƒ㑻;
| ֑ | ע1a | octet_length | ֑ | ע1a | octet_length
-----------------+-----------+----------+-------------- ------------+---------+--------+--------------
ԑԑʾ | A01 | | 15 ԑԑʾ | A01 | | 15
ԑͼ | B01 | | 12 ԑͼ | B01 | | 12
ԑ̑Ա | Z01 | | 15 ԑ̑Ա | Z01 | | 15
...@@ -158,7 +158,7 @@ select *,octet_length( ...@@ -158,7 +158,7 @@ select *,octet_length(
select *,position('' in ) from Ƒ㑻; select *,position('' in ) from Ƒ㑻;
| ֑ | ע1a | position | ֑ | ע1a | position
-----------------+-----------+----------+---------- ------------+---------+--------+----------
ԑԑʾ | A01 | | 3 ԑԑʾ | A01 | | 3
ԑͼ | B01 | | 0 ԑͼ | B01 | | 0
ԑ̑Ա | Z01 | | 0 ԑ̑Ա | Z01 | | 0
...@@ -166,7 +166,7 @@ select *,position(' ...@@ -166,7 +166,7 @@ select *,position('
select *,substring( from 3 for 4) from Ƒ㑻; select *,substring( from 3 for 4) from Ƒ㑻;
| ֑ | ע1a | substring | ֑ | ע1a | substring
-----------------+-----------+----------+----------- ------------+---------+--------+-----------
ԑԑʾ | A01 | | ԑʾ ԑԑʾ | A01 | | ԑʾ
ԑͼ | B01 | | ͼ ԑͼ | B01 | | ͼ
ԑ̑Ա | Z01 | | ̑Ա ԑ̑Ա | Z01 | | ̑Ա
...@@ -183,7 +183,7 @@ insert into ...@@ -183,7 +183,7 @@ insert into
vacuum ͪߩѦ듾; vacuum ͪߩѦ듾;
select * from ͪߩѦ듾; select * from ͪߩѦ듾;
듾 | “׾ړ | 1a󓱸 듾 | “׾ړ | 1a󓱸
--------------------------+--------------+---------------- ------------------+----------+------------
ēǻ͓𓽺Ó | ѦA01߾ | ēǻ͓𓽺Ó | ѦA01߾ |
ēǻ͓דȓ | B10 | ēǻ͓דȓ | B10 |
ēǻ͓Γד | Z01 | ēǻ͓Γד | Z01 |
...@@ -191,45 +191,45 @@ select * from ...@@ -191,45 +191,45 @@ select * from
select * from ͪߩѦ듾 where “׾ړ = 'Z01'; select * from ͪߩѦ듾 where “׾ړ = 'Z01';
듾 | “׾ړ | 1a󓱸 듾 | “׾ړ | 1a󓱸
--------------------------+--------------+---------------- ------------------+----------+------------
ēǻ͓Γד | Z01 | ēǻ͓Γד | Z01 |
(1 row) (1 row)
select * from ͪߩѦ듾 where “׾ړ ~* 'z01'; select * from ͪߩѦ듾 where “׾ړ ~* 'z01';
듾 | “׾ړ | 1a󓱸 듾 | “׾ړ | 1a󓱸
--------------------------+--------------+---------------- ------------------+----------+------------
ēǻ͓Γד | Z01 | ēǻ͓Γד | Z01 |
(1 row) (1 row)
select * from ͪߩѦ듾 where “׾ړ like '_Z01_'; select * from ͪߩѦ듾 where “׾ړ like '_Z01_';
듾 | “׾ړ | 1a󓱸 듾 | “׾ړ | 1a󓱸
--------------------------+--------------+---------------- ------------------+----------+------------
ēǻ͓Γד | Z01 | ēǻ͓Γד | Z01 |
(1 row) (1 row)
select * from ͪߩѦ듾 where “׾ړ like '_Z%'; select * from ͪߩѦ듾 where “׾ړ like '_Z%';
듾 | “׾ړ | 1a󓱸 듾 | “׾ړ | 1a󓱸
--------------------------+--------------+---------------- ------------------+----------+------------
ēǻ͓Γד | Z01 | ēǻ͓Γד | Z01 |
(1 row) (1 row)
select * from ͪߩѦ듾 where 듾 ~ 'ēǻ[]'; select * from ͪߩѦ듾 where 듾 ~ 'ēǻ[]';
듾 | “׾ړ | 1a󓱸 듾 | “׾ړ | 1a󓱸
--------------------------+--------------+---------------- ------------------+----------+------------
ēǻ͓𓽺Ó | ѦA01߾ | ēǻ͓𓽺Ó | ѦA01߾ |
ēǻ͓דȓ | B10 | ēǻ͓דȓ | B10 |
(2 rows) (2 rows)
select * from ͪߩѦ듾 where 듾 ~* 'ēǻ[]'; select * from ͪߩѦ듾 where 듾 ~* 'ēǻ[]';
듾 | “׾ړ | 1a󓱸 듾 | “׾ړ | 1a󓱸
--------------------------+--------------+---------------- ------------------+----------+------------
ēǻ͓𓽺Ó | ѦA01߾ | ēǻ͓𓽺Ó | ѦA01߾ |
ēǻ͓דȓ | B10 | ēǻ͓דȓ | B10 |
(2 rows) (2 rows)
select *,character_length(듾) from ͪߩѦ듾; select *,character_length(듾) from ͪߩѦ듾;
듾 | “׾ړ | 1a󓱸 | character_length 듾 | “׾ړ | 1a󓱸 | character_length
--------------------------+--------------+----------------+------------------ ------------------+----------+------------+------------------
ēǻ͓𓽺Ó | ѦA01߾ | | 8 ēǻ͓𓽺Ó | ѦA01߾ | | 8
ēǻ͓דȓ | B10 | | 7 ēǻ͓דȓ | B10 | | 7
ēǻ͓Γד | Z01 | | 8 ēǻ͓Γד | Z01 | | 8
...@@ -237,7 +237,7 @@ select *,character_length( ...@@ -237,7 +237,7 @@ select *,character_length(
select *,octet_length(듾) from ͪߩѦ듾; select *,octet_length(듾) from ͪߩѦ듾;
듾 | “׾ړ | 1a󓱸 | octet_length 듾 | “׾ړ | 1a󓱸 | octet_length
--------------------------+--------------+----------------+-------------- ------------------+----------+------------+--------------
ēǻ͓𓽺Ó | ѦA01߾ | | 24 ēǻ͓𓽺Ó | ѦA01߾ | | 24
ēǻ͓דȓ | B10 | | 21 ēǻ͓דȓ | B10 | | 21
ēǻ͓Γד | Z01 | | 24 ēǻ͓Γד | Z01 | | 24
...@@ -245,7 +245,7 @@ select *,octet_length( ...@@ -245,7 +245,7 @@ select *,octet_length(
select *,position('' in 듾) from ͪߩѦ듾; select *,position('' in 듾) from ͪߩѦ듾;
듾 | “׾ړ | 1a󓱸 | position 듾 | “׾ړ | 1a󓱸 | position
--------------------------+--------------+----------------+---------- ------------------+----------+------------+----------
ēǻ͓𓽺Ó | ѦA01߾ | | 4 ēǻ͓𓽺Ó | ѦA01߾ | | 4
ēǻ͓דȓ | B10 | | 0 ēǻ͓דȓ | B10 | | 0
ēǻ͓Γד | Z01 | | 0 ēǻ͓Γד | Z01 | | 0
...@@ -253,7 +253,7 @@ select *,position(' ...@@ -253,7 +253,7 @@ select *,position('
select *,substring(듾 from 3 for 4) from ͪߩѦ듾; select *,substring(듾 from 3 for 4) from ͪߩѦ듾;
듾 | “׾ړ | 1a󓱸 | substring 듾 | “׾ړ | 1a󓱸 | substring
--------------------------+--------------+----------------+-------------- ------------------+----------+------------+-----------
ēǻ͓𓽺Ó | ѦA01߾ | | ͓𓽺 ēǻ͓𓽺Ó | ѦA01߾ | | ͓𓽺
ēǻ͓דȓ | B10 | | ͓ד ēǻ͓דȓ | B10 | | ͓ד
ēǻ͓Γד | Z01 | | ͓Γ ēǻ͓Γד | Z01 | | ͓Γ
...@@ -270,7 +270,7 @@ insert into test values('ENGLISH FRAN ...@@ -270,7 +270,7 @@ insert into test values('ENGLISH FRAN
vacuum test; vacuum test;
select * from test; select * from test;
t t
-------------------------------------- -----------------------------------
ENGLISH ENGLISH
FRANAIS FRANAIS
ESPAOL ESPAOL
...@@ -280,20 +280,20 @@ select * from test; ...@@ -280,20 +280,20 @@ select * from test;
select * from test where t = 'ESPAOL'; select * from test where t = 'ESPAOL';
t t
---------- ---------
ESPAOL ESPAOL
(1 row) (1 row)
select * from test where t ~* 'espaol'; select * from test where t ~* 'espaol';
t t
-------------------------------------- -----------------------------------
ESPAOL ESPAOL
ENGLISH FRANAIS ESPAOL SLENSKA ENGLISH FRANAIS ESPAOL SLENSKA
(2 rows) (2 rows)
select *,character_length(t) from test; select *,character_length(t) from test;
t | character_length t | character_length
--------------------------------------+------------------ -----------------------------------+------------------
ENGLISH | 7 ENGLISH | 7
FRANAIS | 8 FRANAIS | 8
ESPAOL | 7 ESPAOL | 7
...@@ -303,7 +303,7 @@ select *,character_length(t) from test; ...@@ -303,7 +303,7 @@ select *,character_length(t) from test;
select *,octet_length(t) from test; select *,octet_length(t) from test;
t | octet_length t | octet_length
--------------------------------------+-------------- -----------------------------------+--------------
ENGLISH | 7 ENGLISH | 7
FRANAIS | 9 FRANAIS | 9
ESPAOL | 8 ESPAOL | 8
...@@ -313,7 +313,7 @@ select *,octet_length(t) from test; ...@@ -313,7 +313,7 @@ select *,octet_length(t) from test;
select *,position('L' in t) from test; select *,position('L' in t) from test;
t | position t | position
--------------------------------------+---------- -----------------------------------+----------
ENGLISH | 4 ENGLISH | 4
FRANAIS | 0 FRANAIS | 0
ESPAOL | 7 ESPAOL | 7
...@@ -323,7 +323,7 @@ select *,position('L' in t) from test; ...@@ -323,7 +323,7 @@ select *,position('L' in t) from test;
select *,substring(t from 3 for 4) from test; select *,substring(t from 3 for 4) from test;
t | substring t | substring
--------------------------------------+----------- -----------------------------------+-----------
ENGLISH | GLIS ENGLISH | GLIS
FRANAIS | ANA FRANAIS | ANA
ESPAOL | PAO ESPAOL | PAO
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment