国际字符的JavaScriptvalidation问题

我们在Stack Overflow上使用jQuery的优秀validation器插件在输入提交到服务器之前对输入进行客户端validation。

它通常运作良好,然而,这个让我们摸不着头脑。

在用户名字段的提问/答案表单上使用以下validation方法(请注意,您必须注销才能在实际站点上查看此字段;它位于每个/question页面和/ask页面上)

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

现在这个正则表达式看起来很奇怪,但它非常简单:

  • 匹配字符串的开头(^)
  • 匹配任何这些..
    • 字符(\ w)
    • 短划线( – )
    • 空间(\ s)
    • 数字(\ d)
    • 疯狂的月亮语言字符(àèìòù等)
  • 现在匹配字符串的结尾($)

是的,我们遇到了国际化正则表达式问题。 JavaScript对“单词字符”的定义根本不包括国际字符。

这是一个奇怪的部分:尽管我们已经麻烦地手动将大量有效的国际字符添加到正则表达式,但它不起作用 。 您无法在用户名的输入框中输入这些国际字符而无法获取..

只能包含AZ,0-9,空格和连字符

..validation回报!

显然,validation正在为正则表达式的其他部分工作 ..所以…给出了什么?

另一个奇怪的部分是,此validation在浏览器的JavaScript控制台中有效,但在作为我们的标准* .js包含的一部分执行时则无效。

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

我们之前在JavaScript代码中遇到了一些非常奇怪的国际角色问题,导致一些非常非常讨厌的黑客攻击。 我们想了解这里发生了什么以及为什么。 请指教!

我认为电子邮件和urlvalidation方法在这里是一个很好的参考,例如。 电子邮件方法:

 email: function(value, element) { return this.optional(element) || /^((([az]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([az]|\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)))@((([az]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([az]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([az]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([az]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([az]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([az]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([az]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([az]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value); }, 

编译该正则表达式的脚本 。

换句话说,用这个替换你的“疯狂月亮”字符的任意列表可能会有所帮助:

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

基本上,这可以通过将需求编码字符替换为更一般的定义来避免您在其他地方遇到的字符编码问题。 虽然不一定更具可读性,但到目前为止它比您的完整列表更短。

这不是一个真正的答案,但我没有50个代表尚未添加评论……它肯定可归因于编码问题。

是的,“ECMA不应该关心编码…”等等等等,如果您使用的是Firefox,请转到View> Character Encoding> Western(ISO-8859-1),然后尝试使用Name字段。

手动更改编码后,它对我来说很好(授予页面的其余部分不喜欢编码开关,:P)

(在IE8上,您可以转到页面>编码>西欧(Windows)以获得相同的效果)

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); 

它的魅力与国际化角色一样。 注意逃脱。 由于这个原因,我只能将JS文件限制为ASCII字符。 因此,在处理ISO-8859与UTF-8字符集时,我不会遇到麻烦。

如果您使用ASCII不是真正子集的字符编码(例如,在亚洲UTF-16中),则不再如此。

干杯,

列出的国际字符是扩展ASCII的一部分。 你添加的那些肯定不是。

看到语句在控制台中工作,是否必须按照.js文件的保存方式(即ascii或UTF-8)进行操作,并且浏览器正在加载它们并在此过程中转换字符?

使用Fiddler或Charles之类的东西(不是Firebug的Net面板,或浏览器中实际存在的任何其他东西)来检查实际上通过网络传输的内容。 这几乎可以肯定是一个编码问题:文件已保存在某些Microsoft字符集中,并以UTF-8格式发送,或者反过来。

对于JS RegExps,您可以像Boldewyn所指出的那样,通过为所需字符指定超出US-ASCII范围的Unicode代码点来避免这些问题。 但是,确保您不会在保存文件的位置和服务位置之间混合编码也是一样。

在这里比赛的后期,但我只是使用了这个表达,它似乎对我有用。 似乎相当全面且相对简单:

 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));