Вопрос по javascript, validation, jquery – Проблема проверки JavaScript с международными символами

22

Мы используем отличныеплагин валидатора для jQuery здесь для переполнения стека, чтобы выполнить проверку входных данных на стороне клиента перед их отправкой на сервер.

Это обычно работает хорошо, однако, этот заставляет нас чесать голову.

Следующий метод проверки используется в форме запроса / ответа для поля имени пользователя (обратите внимание, что вы должны бытьlogged out увидеть это поле на живом сайте; это на каждом/question страница и/ask страница)

$.validator.addMethod("validUserName",
  function(value, element) {
  return this.optional(element) || 
  /^[\w\-\s\dÀÈÌÒÙàèìòùÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûÃÑÕãñõÄËÏÖÜäëïöüçÇßØøÅåÆæÞþÐð]+$/.test(value); },
  "Can only contain A-Z, 0-9, spaces, and hyphens.");  

Теперь это регулярное выражение выглядит странно, но довольно просто:

match the beginning of the string (^) match any of these.. word character (\w) dash (-) space (\s) digit (\d) crazy moon language characters (àèìòù etc) now match the end of the string ($)

Да, мы столкнулись сИнтернационализированные регулярные выражения проблема. JavaScript-определение слова "символ" & quot; не включает международные символы .. вообще.

Вот странная часть: хотя мы и столкнулись с проблемой ручного добавления в регулярное выражение множества допустимых международных символов, этоdoesn't work, Вы не можете ввести эти международные символы в поле ввода имени пользователя, не получив ..

Can only contain A-Z, 0-9, spaces, and hyphens

.. подтверждение возврата!

очевидноthe validation is working for the other parts of the regex.. так .. что дает?

Другая странная часть заключается в том, что эта проверка работает в консоли JavaScript браузера, но не при выполнении в качестве части нашего стандартного включения * .js.

/^[\w-\sÀÈÌÒÙàèìòùÁÉÍÓÚÝáéíóúýÂÊÎÔÛâêîôûÃÑÕãñõÄËÏÖÜäëïöüçÇßØøÅåÆæÞþÐð]+$/ .test('ÓBill de hÓra') === true

Ранее мы сталкивались с некоторыми действительно странными международными проблемами символов в коде JavaScript, что приводило к некоторым очень и очень неприятным взломам. Мы хотели бы понять, что здесь происходит и почему. Пожалуйста, просветите нас!

Может ли это быть проблемой кодировки символов? То есть сумасшедшая луна "& # xC4;" исходящий от пользователя не является & quot; & # xC4; & quot; в вашем регулярном выражении? balpha♦
Я не знаю ответа, но это хороший способ написать вопрос. Onorio Catenacci
@ Оорио Джефф всегда выступает за то, чтобы задавать хорошо написанные вопросы, поэтому ему лучше делать это и самому :-) Но вы, безусловно, правы. balpha♦
& # XE9; это не символ лунного языка, pok & # xE9; mon в английском алфавите, не так ли? Также проверьте мой комментарий ответ Jorn Hoffmann

Ваш Ответ

7   ответов
2

перечисленные международные символы являются частью расширенного ASCII. добавленные вами, конечно, нет.

13

Это на самом деле не ответ, но у меня нет 50 представителей, чтобы добавить комментарий ... Это может быть определенно связано с проблемами кодирования.

Да, ECMA не должно заботиться о кодировании ... бла-бла, хорошо, если вы на Firefox, перейдите кView > Character Encoding > Western (ISO-8859-1) затем попробуйте использовать поле Имя.

Это работает нормально для меня после изменения кодировки вручную (при условии, что остальная часть страницы не похожа на переключатель кодирования: P)

(на IE8 вы можете перейти кPage > Encoding > Western European (Windows) чтобы получить тот же эффект)

он прав, это волшебным образом заставляет Имя: проверка работоспособности (!) Jeff Atwood
36

Я думаю, что методы проверки электронной почты и URL-адреса являются хорошим справочником, например. метод электронной почты:

email: function(value, element) {
    return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value);
},

Скрипт для компиляции этого регулярного выражения.

Другими словами, замена вашего произвольного списка «сумасшедшая луна» персонажи с этим могут помочь:

[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]

По сути, это позволяет избежать проблем с кодировкой символов, возникающих в других местах, заменив символы кодировки потребностей более общими определениями. Хотя это не обязательно более читабельно, пока он короче, чем ваш полный список.

Обе ссылки в ответе битые.
Другое дело, попробуйте оповещение (& quot; & # xE1; & # xE9; & # xED; & # xF3; & # xFA; & quot;), если оно показывает, что ваш файл javascript закодирован в той же кодировке, что и ваша страница. Еще одно решение состоит в том, чтобы просто включить ваши javascripts с помощью: & lt; script src = & quot; myscripts.js & quot; кодировка = & Quot; ISOsomething & Quot; / & GT; где ISOsomething - кодировка вашего файла .js. Это распространенная ошибка, потому что большинство IDE создают файлы .js в кодировке по умолчанию, которая по умолчанию почти никогда не является UTF-8.
это помогло мне, поддерживает символы i18n и никаких двойных кавычек:^[[email protected]#$%^~&*/?:'\, \\ | {} () -_ + \ s \ u00A0- \ uD7FF \ uF900- \ uFDCF \ uFDF0- \ uFFEF] * $ `
Просто чтобы уточнить, почему это работает. Если ваш файл .js заключен в символьную кодировку, все символы внутри выражений регулярного выражения внутри него будут представлены в этой кодировке, даже если ваша веб-страница использует другую кодировку. В своих проектах я просто кодирую ВСЕ, что может содержать международные строки в UTF-8. Это включает в себя файлы .js. Вероятно, с Джеффом произошло то, что его файлы .js были закодированы в кодировке, а его страница была проанализирована с другой кодировкой, его HTTP-запросы / ответ, вероятно, были закодированы с той же кодировкой, что и страница. Это объясняет, почему он работал на отладчике.
3

Какова кодировка символов файла JS?

Для XML QNames я использую этот RegExp:

/**
 * Definition of an XML Name
 */
var NameStartChar = "A-Za-z:_\u00C0-\u00D6\u00D8-\u00F6\u00F8-\u02FF\u0370-\u037D"+
                    "\u037F-\u1FFF\u200C-\u200D\u2070-\u218F\u2C00-\u2FEF\u3001-\uD7FF"+
                    "\uF900-\uFDCF\uFDF0-\uFFFD\u010000-\u0EFFFF";
var NameChar = NameStartChar+"\\-\\.0-9\u00B7\u0300-\u036F\u203F-\u2040";
var Name = "^["+NameStartChar+"]["+NameChar+"]*$";
RegExp (Name).test (value);

Он работает как шарм и с интернациональными персонажами. Обратите внимание на побег. Благодаря этому я могу ограничить файл JSASCII только персонажи. Поэтому у меня не возникает проблем при работе с кодировками ISO-8859 и UTF-8.

Это больше не так, если вы используете кодировки символов, где ASCII не является реальным подмножеством (как, например, в Азии UTF-16).

Ура,

Это не может быть. ANSI "& # xC4;" (== ISO-8859-1) имеет однобайтовое представление "C4", тогда как UTF-8 "& # xC4;" выглядит в шестнадцатеричном редакторе наподобие «C3 84». Что вы имеете в виду под «переключателем»? Это реальное преобразование между кодировками?
Я открываю файл на диске в Notepad2, и он выглядит правильно, т. Е. Идентично тому, что вы видите выше в ANSI, и когда я переключаюсь на Unicode, кодировки UTF-8 также идентичны. Jeff Atwood
Как я понял, правила валидатора находятся во внешнем файле JS. Тогда я держу пари, что этот файл находится в неправильной кодировке (т.е. не в кодировке UTF-8).
странно, это соответствует true для строки, содержащей & quot; & lt; & quot ;. По-видимому, из-за последнего бита NameStartChar & quot; \ u010000- \ u0EFFFF & quot; даже несмотря на то, что & lt; не в этом диапазоне. Точно так же @,?, = И другие символы между '9' и 'A'. мысли о том, почему?
2

Видя, как оператор работает в консоли, может ли это быть связано с тем, как сохраняются ваши файлы .js (например, ascii или UTF-8) и что браузер загружает их таким образом и в процессе переводит символы?

JS ничего не знает о UTF-8, даже если кодировка установлена так.
s / браузер заботится / браузер и, следовательно, движок JS заботится /
Да, браузер заботится. Если вы сохраните & quot; & # xC4; & quot; как не-Unicode, это приведет к неверному потоку байтов UTF-8. Следовательно, он никогда не может соответствовать байтовому потоку UTF-8, соответствующему «& # xC4;».
Но браузер делает, не так ли? Что, если файл загружен как UTF-8, а механизм JS браузера неправильно интерпретирует символы, потому что браузер загрузил файл неправильно?
2

Используйте что-то вроде Fiddler или Charles (не панель Net Firebug или что-то еще, что на самом деле внутри браузера), чтобы проверить, что на самом деле происходит по проводам. Это почти наверняка проблема кодирования: файл был сохранен в некотором наборе символов Microsoft и отправляется как UTF-8, или, может быть, наоборот.

В случае JS RegExps вы можете, как указывает Болдевин, избежать этих проблем, указав кодовую точку Unicode для символов, которые вы хотите, которые находятся вне диапазона US-ASCII. Тем не менее, было бы также хорошо убедиться, что вы не смешиваете кодировки между местом сохранения файла и местом его хранения.

gzip через провод, так что делать неловко Jeff Atwood
И Фидлер, и Чарльз могут с этим справиться. IIRC Fiddler (по крайней мере, в версии 2) предложит вам кнопку в области просмотра Ответов, чтобы вы могли просматривать разархивированный контент.
2

Позже к игре здесь, но я просто использовал это выражение, и мне показалось, что оно хорошо работает. Кажется, довольно всеобъемлющий и относительно простой:

var re = /^[A-zÀ-ÿ\s\d-]*$/g; 
var str1 = 'casa-me,pois 99 estou farto! Eis a lista:uma;duas;três';
var str2 = 'casa-me pois 99 estou farto Eis a lista uma duas três';

alert(re.test(str1));
alert(re.test(str2));

Похожие вопросы