Problem/Motivation
In #614124: Bootstrap should reset locale settings a line was added to set the locale to a sane default: setlocale(LC_ALL, 'C');
Since that time however, C.UTF-8 has been officially adopted as the C locale with UTF-8 encoding. See e.g. https://sourceware.org/glibc/wiki/Proposals/C.UTF-8 (C.UTF-8 has also been adopted by non-Linux operating systems such as FreeBSD, and other programming languages such as Python.)
One place where the C locale fails is the PHP function escapeshellarg(): non-ASCII characters will be removed unless a UTF-8 locale is set. See https://bugs.php.net/bug.php?id=44945
Steps to reproduce
Call an affected function such as escapeshellarg() or escapeshellcmd() with a string containing non-ASCII UTF-8 characters; they will be silently removed.
Proposed resolution
Update setlocale(LC_ALL, 'C'); to setlocale(LC_ALL, 'C.UTF-8', 'C');
Meaning, if the environment does not have the C.UTF-8 locale installed, the C locale will be used as a fallback.
Remaining tasks
Test in various environments and use cases, including macOS. If macOS does not have C.UTF-8 installed, we could try setlocale(LC_ALL, 'C.UTF-8', 'UTF-8', 'C');
User interface changes
API changes
The locale will be set to C.UTF-8 if available, otherwise the C locale will continue to be used.
Data model changes
N/A
Release notes snippet
TBD
| Comment | File | Size | Author |
|---|
Issue fork drupal-1561214
Show commands
Start within a Git clone of the project using the version control instructions.
Or, if you do not have SSH keys set up on git.drupalcode.org:
- 1561214-bootstrap-sets-c
changes, plain diff MR !7434
Comments
Comment #1
fietserwinLet's see what the tests say.
Comment #2
drzraf commentedDrupal should not affect the locale except for the bare minimum like
LC_NUMERICto work around some PHP bugs.First, let's see if this line is needed at all (eg : if tests about floats are here)
Comment #3
fietserwinThis is a "PHP bug" (see my link) though classified as a feature: escapeshellarg works locale and codepage dependent.
Subsequently this is a Drupal bug, as Drupal provides a standardized environment where developers can do things independent from antique server settings. This ranges from anything like register globals to utf-8 all over the place.
When I am developing under Drupal, I am expected to work with UTF-8, from database to browser, and Drupal is the environment providing it. So If I pass on some UTF-8 strings to the database I may expect them to stay as they are. That's why Drupal does things like sending "SET NAMES utf8" to the database. If I send an UTF-8 string to the browser I may expect Drupal to have outputted a <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> meta tag.
Thus when I want to call some external commands and am using escapeshellarg(), I may expect Drupal to have called setlocale() in such a way that escapeshellarg() will leave my utf-8 string intact (except of course for the shell escaping I am asking for). Either this, or Drupal should provide its own escapeshellarg.
If you would want to reduce it to the bare minimum, we will thus also have to include LC_CTYPE with an 'UTF-8' "code page".
Comment #4
drzraf commentedI do agree on assuming (and setting) an UTF-8 character encoding. I only disagree on the
LC_ALL+Ccombination.I'm sorry but I can not take the time to provide patches for the testsuite (for which tests are missing as bugs currently *exist* on this subject), as illustrated by
drush ev 'echo iconv("utf8", "ascii//translit", " héllô") . "\n";'.Comment #5
fietserwinI read about your iconv problems, and am pretty sure that with a (ok, probably any) utf-8 locale setting, thus the patch from #1, your problem will be solved.
Comment #6
sunThe patch in #2 is definitely wrong, which has been sufficiently discussed in #614124: Bootstrap should reset locale settings already.
Example bug report: #1502924: escapeshellarg() has problems with non-ASCII filenames
Clarifying the issue title.
I agree with the patch in #1.
But alas, it doesn't make a difference on my local Windows machine, which appears to retain UTF-8 correctly. Let's see what the testbot thinks.
Comment #7
sunComment #7.0
sunUpdated issue summary.
Comment #9
hass commentedIf this is the bugfix for #371495: Error message from drupal_http_request() not UTF8 encoded, this needs backport to D6, too.
Comment #10
fietserwin#9: see #614124: Bootstrap should reset locale settings.
#6: Linux escapes with a single quote, Windows with a double quote. The test should pass on both systems I guess, thus need to take that into account.
#6: I ran the test below on different systems. The results are a bit strange to put it mildly. I cannot understand how I got this to work on Linux variant 3: See the accented characters in the polaroids on http://www.locations-mont-dore.fr/. these are created by Imagemagick (thus the texts got passed to Imagemagick via a shell command).
Anyway, it looks that choosing 'en_US' as locale gives the best results.
Test code
Everybody can run this on his/her own system to see which locale gives good results. If you have different results please post them. Save this code to, e.g., phpinfo.php and run the test by visiting the page in your browser.
Results
Windows
Linux variant
Linux variant 2
Linux variant 3
Comment #11
drzraf commentedAccording to this post, C.UTF-8 does not appear to be a valid locale : there's no non-ascii "POSIX" locale. The most standard being en_EN (http://sources.redhat.com/ml/libc-alpha/2009-09/msg00042.html)
Anyway :
php -r "setlocale(LC_CTYPE, 'C.UTF-8'); echo escapeshellarg('äöüß');"'äöüß'
php -r "setlocale(LC_CTYPE, 'C'); echo escapeshellarg('äöüß');"''
I'm personally fine with UTF-8 LC_ALL, but more theoretically, once again, why use LC_ALL if LC_CTYPE is sufficient.
To fix both this and #614124: Bootstrap should reset locale settings, I'd replace the
setlocale()line byComment #12
OnkelTem commentedDamn PHP...
It is 2012 outside and we still have this backward issues with stripping non-latin characters.
I vote for a PHP independent solution, like implementing our own
escapeshellarg()(drupal_escapeshellarg()) to not couple with PHP anymore.Just for reference, this is PHP implemenation of escapeshellarg:
Comment #13
sdrycroft commentedIt is worth noting that on a Debian 6.0.6 system the C.UTF-8 locale is not provided by default, but can be generated using the following command.
This may be of issue on other systems, and may require picking a locale that is available e.g. en_GB.UTF-8.
Comment #13.0
sdrycroft commentedUpdated issue summary.
Comment #16
juliencarnot commentedComment #28
quietone commentedIt has been 7 years since there has been discussion here.
Is this still relevant to Drupal 10?
Since we need more information to move forward with this issue, I am setting the status to Postponed (maintainer needs more info). If we don't receive additional information to help with the issue, it may be closed after three months.
Thanks!
Comment #31
mfbAFAIK this is still a valid issue as originally described. I created a merge request with the setlocale() change to see if tests pass. The test from the patch would still need to be ported, however.
Comment #32
mfbSetting to needs work as the test still needs to be ported from patch to merge request.
Comment #33
mfbI added a test so this is ready for review.
Since this issue was created, a C.UTF-8 locale was officially added so should be even more common across different environments.
However, I changed the setlocale() to use good ol' C as a fallback for older systems:
setlocale(LC_ALL, 'C.UTF-8', 'C');As a result there will be some behavioral differences across environments, but it seems like a net win to enable correct UTF-8 handling on newer systems, while still supporting older systems.
Comment #34
mfbHiding obsolete patch files
Comment #35
smustgrave commentedGot the issue summary started but seems original summary was written for D7 if that could be cleaned up some.
Wonder if this kind of change will require a CR or be disruptive?
Clearly an old issue so will keep on my radar
Comment #36
mfbUpdated the summary. I think this issue makes more sense now than when originally proposed, as C.UTF-8 has been much more widely standardized and adopted than it was back then. However, should still be thoroughly tested.
Comment #37
mfbComment #38
smustgrave commentedDoubt we are backporting to D6 or D7
Applied locally and did random things like create content, media, views, etc. But didn't see any issues. Not sure how else to test.
Comment #39
mfb@smustgrave were you able to run the newly-added test on macOS - that would be the main thing worth testing.
Comment #40
smustgrave commentedIt's a ddev setup on my mac but ran DrupalKernelTest without issue if that's what you mean.
Comment #41
mfbOk, but that might essentially be Linux if docker-based? Would be excellent if someone could test directly on raw macOS
Comment #42
alexpottWe definitely should have a change record for this. I can run Kernel tests fine on a Mac.
Comment #43
mfbChange record ready for review.
Comment #44
smustgrave commentedSince it was just a CR was needed going to put back into RTBC.
Comment #45
quietone commented@smustgrave, The change record should be reviewed before setting to RTBC. Has that been done?
Comment #46
nicxvan commentedI reviewed the CR and the code, I did tweak the CR a little for clarity. I think this looks good!
I'll let @smustgrave respond to your question, but I've independently reviewed it so RTBC should be good either way.
Comment #49
longwaveCommitted and pushed 79eed4acc5 to 11.x and dcfd0488b8 to 10.3.x. Thanks!
Also published the change record.