Я конвертирую данные, такие как html, css, из текстовой области браузера в шестнадцатеричный формат, чтобы отправить их через ajax на сервер. Это сделано для того, чтобы избежать срабатывания правил брандмауэра modsecurity xss.
На сервере я использую hex2bin PHP для преобразования шестнадцатеричного значения обратно в HTML.
Все работает так, как должно, НО не преобразуются некоторые символы, такие как £
, шестнадцатеричный код которых равен a3
, PHP hex2bin
отображает их как �
в браузере.
Есть много других подобных шестнадцатеричных кодов hex2bin
, которые не конвертируются. Я делаю что-то не так или есть какая-то другая библиотека, которую я могу использовать, чтобы получить полное шестнадцатеричное покрытие?
<head>
<meta charset = "utf-8">
</head>
//javascript
var str = '£';
var hex = str.charCodeAt(0).toString(16);
alert(hex); // a3
//php
echo hex2bin('a3'); // �
echo hex2bin('24'); // $
echo hex2bin('ae'); // � should be ®
Используете ли вы ASCII в js и UTF8 в PHP? c2a3
должно быть utf8. Не могли бы вы добавить больше контекста к вопросу.
смотрите мой вопрос, я добавил код js и php, который использую
Вы делаете это просто в качестве упражнения или это должно служить какой-то реальной цели? (Просто пытаюсь выяснить, не пытаетесь ли вы заново изобрести здесь какие-то колеса.)
hex2bin()
работает отлично. Вы просто не создаете действительную последовательность байтов UTF-8.
Я конвертирую html, css и javascript из текстовой области браузера в шестнадцатеричный формат, чтобы отправить его через ajax на сервер и сохранить в базе данных. Это сделано для того, чтобы избежать срабатывания правил брандмауэра modsecurity xss.
Решение состоит в том, чтобы использовать функцию utf8ToHex()
, указанную здесь. utf8ToHex('£')
возвращает c2a3
, что дает ожидаемый результат при декодировании с помощью hex2bin()
.
Для справки: £
— это U+00A3 «ЗНАК ФУТА». a3
— это кодовая точка Юникода, которая по сути представляет собой каталожный номер и отличается от фактической используемой кодировки.
String.prototype.charCodeAt() производит:
целое число от 0 до 65535, представляющее кодовую единицу UTF-16 по данному индексу.
Поскольку ваш HTML-документ объявляет UTF-8, вам необходимо выполнить преобразование между кодировками. Но вам также не хватает информации, когда первый байт равен нулю, поэтому вам нужно сначала дополнить значение:
$utf16 = hex2bin(str_pad('a3', 4, '0', STR_PAD_LEFT));
echo mb_convert_encoding($utf16, 'UTF-8', 'UTF-16');
Делать это по одному персонажу за раз не получится. Если вам вообще нужна сериализация (т. е. вы не можете использовать необработанный UTF-8 по какой-либо причине), я бы предложил вам использовать другой механизм сериализации, например Base64:
function bytesToBase64(bytes) {
const binString = Array.from(bytes, (byte) =>
String.fromCodePoint(byte),
).join("");
return btoa(binString);
}
const message = 'We accept £ and €';
console.info(bytesToBase64(new TextEncoder().encode(message)));
(Код взят из MDN).
echo base64_decode('V2UgYWNjZXB0IMKjIGFuZCDigqw=');
mb_convert_encoding
набивка hex2bin
решает проблему в этом вопросе. Однако метод bytesToBase64
, предложенный Альваро, является лучшим решением для приложения, над которым я работаю. Спасибо за ответ.
Я опубликовал функцию, полученную на основе этого ответа на этот вопрос stackoverflow.com/questions/78723233/…
Похоже, вы отображаете неправильную кодировку.