What you're asking for is extremely hard. If possible, getting the user to specify the encoding is the best. Preventing an attack shouldn't be much easier or harder that way.
However, you could try doing this:
iconv(mb_detect_encoding($text, mb_detect_order(), true), "UTF-8", $text);
Setting it to strict might help you get a better result.
Answer from Jeff Day on Stack OverflowWhat you're asking for is extremely hard. If possible, getting the user to specify the encoding is the best. Preventing an attack shouldn't be much easier or harder that way.
However, you could try doing this:
iconv(mb_detect_encoding($text, mb_detect_order(), true), "UTF-8", $text);
Setting it to strict might help you get a better result.
In motherland Russia we have four popular encodings, so your question is in great demand here.
Only by character codes of symbols you can not detect the encoding, because code pages intersect. Some codepages in different languages have even full intersection. So, we need another approach.
The only way to work with unknown encodings is working with probabilities. So, we do not want to answer the question "what is encoding of this text?", we are trying to understand "what is most likely encoding of this text?".
One guy here in a popular Russian tech blog invented this approach:
Build the probability range of character codes in every encoding you want to support. You can build it using some big texts in your language (e.g., some fiction, use Shakespeare for English and Tolstoy for Russian, LOL). You will get something like this:
encoding_1:
190 => 0.095249209893009,
222 => 0.095249209893009,
...
encoding_2:
239 => 0.095249209893009,
207 => 0.095249209893009,
...
encoding_N:
charcode => probabilty
Next, you take text in an unknown encoding and for every encoding in your "probability dictionary" you search for the frequency of every symbol in the unknown-encoded text. Sum the probabilities of symbols. Encoding with the bigger rating is likely the winner. There are better results for bigger texts.
Btw, mb_detect_encoding certainly does not work. Yes, at all. Please, take a look of the mb_detect_encoding source code in "ext/mbstring/libmbfl/mbfl/mbfl_ident.c".
How to insert Unicode characters in MySQL using PHP?
What is UTF-8 character set?
What does UTF-8 stand for?
Many languages use UTF-8 for their strings. As languages progress, UTF-8 has become the default (e.g. Java)
PHP has mb_str* , str functions. Why are they separate? can't UTF-8 be the default, and these functions be combined?
just curious about this.
We know that utf8_encode is deprecated since PHP 8.2.0 and will be removed in PHP 9 https://php.watch/versions/8.2/utf8_encode-utf8_decode-deprecated
So the alternative can be:
$oldSample = ["\x5A\x6F\xEB"];
$result= array_map
(
function ($item){
return mb_convert_encoding($item, "UTF-8", mb_detect_encoding($item));
},
$oldSample
);
var_dump($result);
Documentation:
- https://www.php.net/manual/en/function.mb-convert-encoding.php
- https://www.php.net/manual/en/function.mb-detect-encoding.php
Use mb_convert_encoding to convert from ISO-8859-1 to UTF-8
Example:
$iso = "\x5A\x6F\xEB";
echo mb_convert_encoding($iso, 'UTF-8', 'ISO-8859-1'); // Zoë