Как заменить / избежать U + 2028 или U + 2029 символов в PHP, чтобы остановить мой JSONP API

Хорошо, я запускаю публичный JSONP API, данные которого подаются с моего PHP-сервера. Я просто прочитал эту статью:

  • JSON: подмножество JavaScript, которое не является (Магнусом Холмом, май 2011 г.)
    (просьба ознакомиться с разъяснением)

В принципе, если мои строки JSON содержат символ U + 2028 (разделитель строк Unicode) или символ U + 2029 (разделитель абзацев Unicode), то это совершенно допустимый JSON. Однако при использовании JSONP JSON запускается как JavaScript, и никакая строка в JavaScript не может содержать буквальный U + 2028 или U + 2029, так как он разрушит JavaScript. По-видимому, это обычно не проблема, если вы используете правильный JSON-парсер, но в случае JSONP браузер является парсером JSON.

По сути, если эти символы были внутри строк в моих JSONP-данных, отправляемых клиенту, это приведет к перерыву строки или абзаца в строку, которая приведет к поломке JavaScript и прекращению его выполнения. Это возможность, поскольку API отправляет обратно некоторые данные, введенные клиентом. Кто-то может потенциально ввести U + 2028 или U + 2029 в базу данных, поэтому, когда я отправлю это обратно как JSONP, он разрушит любую реализацию, используя мой API.

Итак, мой вопрос: на PHP, как я могу дезинфицировать / выводить данные JSON для удаления или удаления символов U + 2028 и U + 2029 перед отправкой его клиенту?

В настоящее время мой процесс выполняет json_encode в массиве данных и передает эти данные клиенту. Должен ли я избегать данных, перейдя через массив и отфильтровывая его, или сразу же удалите всю закодированную строку JSON?

Другое дело, я не уверен, как избежать символов U + 2028 и U + 2029 на PHP в любом случае. Могу ли я просто сделать str_replace? Я не уверен, что str_replace многобайт безопасен, и нет функции mb_str_replace, если я не использую какую-то пользовательскую. Итак, как вы удаляете / удаляете эти символы Unicode?

Огромное спасибо.

Вы можете заменить U+2028 , U+2029 на "\u2028" , "\u2029" либо на стороне PHP, либо на стороне JavaScript, или на обоих, это не имеет значения, если это происходит хотя бы один раз (это идемпотент) ,

Вы можете просто использовать обычные функции замены строк. Они не обязательно должны быть «многобилетными», и вы можете сделать это так же легко в любой кодировке Unicode (UTF-8, UTF-16, UTF-32 все одинаково хорошо). У PHP не было escape-последовательностей Unicode в прошлый раз, когда я проверил, что является еще одной причиной, по которой PHP является шуткой, но вы можете использовать escape \x с UTF-8 …

(Короче говоря, причина, почему нет функции замены многобайтовой строки, состоит в том, что она будет избыточной – она ​​будет точно такой же, как функция замены не многобайтовых строк).

 // Javascript data = data.replace("\u2028", "\\u2028").replace("\u2029", "\\u2029"); // PHP $data = str_replace("\xe2\x80\xa8", '\\u2028', $data); $data = str_replace("\xe2\x80\xa9", '\\u2029', $data); 

Или вы просто ничего не можете сделать, поскольку PHP по умолчанию json_encode() символы, отличные от Unicode, в json_encode() :

 // Safe echo json_encode("\xe2\x80\xa9"); --> "\u2029" // Correct JSON, but invalid Javascript... // (Well, technically, JSON root must be array or object) echo json_encode("\xe2\x80\xa9", JSON_UNESCAPED_UNICODE); --> " " 

Стоит отметить, что это уже не нужно.

По умолчанию json_encode() кодирует все символы, отличные от ASCII (включая U + 2028 и U + 2029), а также избегает косой черты, даже если это не нужно избегать спецификацией JSON. Это не вредит побегу, и в определенных контекстах это может быть безопаснее. Таким образом, по умолчанию эти символы все равно экранируются.

Константа JSON_UNESCAPED_UNICODE выводит JSON_UNESCAPED_UNICODE Unicode, который может сохранять байты. Тем не менее, так же, как символ слэша экранирован, потому что он может быть опасным в некоторых контекстах, так и U + 2028 и U + 2029 также экранированы, потому что они тоже опасны в некоторых контекстах. Это было не так в то время, когда вы задали свой вопрос: эта функция была добавлена ​​в PHP совсем недавно .

(Эти дополнительные экраны можно отключить с помощью JSON_UNESCAPED_SLASHES и JSON_UNESCAPED_LINE_TERMINATORS , соответственно.)