Commit 8c49454c authored by Tom Lane's avatar Tom Lane

Be more careful about extracting encoding from locale strings on Windows.

GetLocaleInfoEx() can fail on strings that setlocale() was perfectly
happy with.  A common way for that to happen is if the locale string
is actually a Unix-style string, say "et_EE.UTF-8".  In that case,
what's after the dot is an encoding name, not a Windows codepage number;
blindly treating it as a codepage number led to failure, with a fairly
silly error message.  Hence, check to see if what's after the dot is
all digits, and if not, treat it as a literal encoding name rather than
a codepage number.  This will do the right thing with many Unix-style
locale strings, and produce a more sensible error message otherwise.

Somewhat independently of that, treat a zero (CP_ACP) result from
GetLocaleInfoEx() as meaning that we must use UTF-8 encoding.

Back-patch to all supported branches.

Juan José Santamaría Flecha

Discussion: https://postgr.es/m/24905.1585445371@sss.pgh.pa.us
parent 24566b35
...@@ -239,25 +239,44 @@ win32_langinfo(const char *ctype) ...@@ -239,25 +239,44 @@ win32_langinfo(const char *ctype)
{ {
r = malloc(16); /* excess */ r = malloc(16); /* excess */
if (r != NULL) if (r != NULL)
sprintf(r, "CP%u", cp); {
/*
* If the return value is CP_ACP that means no ANSI code page is
* available, so only Unicode can be used for the locale.
*/
if (cp == CP_ACP)
strcpy(r, "utf8");
else
sprintf(r, "CP%u", cp);
}
} }
else else
#endif #endif
{ {
/* /*
* Locale format on Win32 is <Language>_<Country>.<CodePage> . For * Locale format on Win32 is <Language>_<Country>.<CodePage>. For
* example, English_United States.1252. * example, English_United States.1252. If we see digits after the
* last dot, assume it's a codepage number. Otherwise, we might be
* dealing with a Unix-style locale string; Windows' setlocale() will
* take those even though GetLocaleInfoEx() won't, so we end up here.
* In that case, just return what's after the last dot and hope we can
* find it in our table.
*/ */
codepage = strrchr(ctype, '.'); codepage = strrchr(ctype, '.');
if (codepage != NULL) if (codepage != NULL)
{ {
int ln; size_t ln;
codepage++; codepage++;
ln = strlen(codepage); ln = strlen(codepage);
r = malloc(ln + 3); r = malloc(ln + 3);
if (r != NULL) if (r != NULL)
sprintf(r, "CP%s", codepage); {
if (strspn(codepage, "0123456789") == ln)
sprintf(r, "CP%s", codepage);
else
strcpy(r, codepage);
}
} }
} }
......
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