Skip to content

Commit

Permalink
Merge pull request yiisoft#280 from resurtm/validator-idn
Browse files Browse the repository at this point in the history
Fixes yiisoft#143. UrlValidator and EmailValidator IDN support.
  • Loading branch information
qiangxue committed May 15, 2013
2 parents 5dffc75 + 9803b43 commit 992e902
Show file tree
Hide file tree
Showing 17 changed files with 143 additions and 23 deletions.
17 changes: 16 additions & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -69,11 +69,26 @@
"bin": [
"yii/yiic"
],
"repositories": [
{
"type": "package",
"package": {
"name": "bestiejs/punycode.js",
"version": "1.2.1",
"source": {
"url": "git://github.com/bestiejs/punycode.js.git",
"type": "git",
"reference": "1.2.1"
}
}
}
],
"require": {
"php": ">=5.3.0",
"michelf/php-markdown": "1.3",
"twig/twig": "1.12.*",
"smarty/smarty": "3.1.*",
"ezyang/htmlpurifier": "v4.5.0"
"ezyang/htmlpurifier": "v4.5.0",
"bestiejs/punycode.js": "1.2.1"
}
}
12 changes: 11 additions & 1 deletion composer.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

8 changes: 7 additions & 1 deletion yii/assets.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
'js' => array(
'yii.activeForm.js',
),
'depends' => array('yii', 'yii/validation'),
'depends' => array('yii'),
),
'yii/captcha' => array(
'sourcePath' => __DIR__ . '/assets',
Expand All @@ -42,4 +42,10 @@
),
'depends' => array('yii'),
),
'punycode' => array(
'sourcePath' => __DIR__ . '/vendor/bestiejs/punycode.js',
'js' => array(
'punycode.min.js',
),
),
);
28 changes: 25 additions & 3 deletions yii/assets/yii.validation.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,9 +110,19 @@ yii.validation = (function ($) {
return;
}

var valid = value.match(options.pattern) && (!options.allowName || value.match(options.fullPattern));
var valid = true;

if (options.enableIDN) {
var regexp = /^(.*)@(.*)$/,
matches = regexp.exec(value);
if (matches === null) {
valid = false;
} else {
value = punycode.toASCII(matches[1]) + '@' + punycode.toASCII(matches[2]);
}
}

if (!valid) {
if (!valid || !(value.match(options.pattern) && (!options.allowName || value.match(options.fullPattern)))) {
messages.push(options.message);
}
},
Expand All @@ -126,7 +136,19 @@ yii.validation = (function ($) {
value = options.defaultScheme + '://' + value;
}

if (!value.match(options.pattern)) {
var valid = true;

if (options.enableIDN) {
var regexp = /^([^:]+):\/\/([^\/]+)(.*)?/,
matches = regexp.exec(value);
if (matches === null) {
valid = false;
} else {
value = matches[1] + '://' + punycode.toASCII(matches[2]) + matches[3];
}
}

if (!valid || !value.match(options.pattern)) {
messages.push(options.message);
}
},
Expand Down
5 changes: 4 additions & 1 deletion yii/validators/BooleanValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,9 +79,11 @@ public function validateValue($value)
* Returns the JavaScript needed for performing client-side validation.
* @param \yii\base\Model $object the data object being validated
* @param string $attribute the name of the attribute to be validated.
* @param \yii\base\View $view the view object that is going to be used to render views or view files
* containing a model form with this validator applied.
* @return string the client-side validation script.
*/
public function clientValidateAttribute($object, $attribute)
public function clientValidateAttribute($object, $attribute, $view)
{
$options = array(
'trueValue' => $this->trueValue,
Expand All @@ -100,6 +102,7 @@ public function clientValidateAttribute($object, $attribute)
$options['strict'] = 1;
}

$view->registerAssetBundle('yii/validation');
return 'yii.validation.boolean(value, messages, ' . json_encode($options) . ');';
}
}
5 changes: 4 additions & 1 deletion yii/validators/CaptchaValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -91,9 +91,11 @@ public function getCaptchaAction()
* Returns the JavaScript needed for performing client-side validation.
* @param \yii\base\Model $object the data object being validated
* @param string $attribute the name of the attribute to be validated.
* @param \yii\base\View $view the view object that is going to be used to render views or view files
* containing a model form with this validator applied.
* @return string the client-side validation script.
*/
public function clientValidateAttribute($object, $attribute)
public function clientValidateAttribute($object, $attribute, $view)
{
$captcha = $this->getCaptchaAction();
$code = $captcha->getVerifyCode(false);
Expand All @@ -111,6 +113,7 @@ public function clientValidateAttribute($object, $attribute)
$options['skipOnEmpty'] = 1;
}

$view->registerAssetBundle('yii/validation');
return 'yii.validation.captcha(value, messages, ' . json_encode($options) . ');';
}
}
Expand Down
5 changes: 4 additions & 1 deletion yii/validators/CompareValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,9 +178,11 @@ public function validateValue($value)
* @param \yii\base\Model $object the data object being validated
* @param string $attribute the name of the attribute to be validated
* @return string the client-side validation script
* @param \yii\base\View $view the view object that is going to be used to render views or view files
* containing a model form with this validator applied.
* @throws InvalidConfigException if CompareValidator::operator is invalid
*/
public function clientValidateAttribute($object, $attribute)
public function clientValidateAttribute($object, $attribute, $view)
{
$options = array('operator' => $this->operator);

Expand All @@ -203,6 +205,7 @@ public function clientValidateAttribute($object, $attribute)
'{compareValue}' => $compareValue,
)));

$view->registerAssetBundle('yii/validation');
return 'yii.validation.compare(value, messages, ' . json_encode($options) . ');';
}
}
29 changes: 25 additions & 4 deletions yii/validators/EmailValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,12 @@ class EmailValidator extends Validator
* Defaults to false.
*/
public $checkPort = false;
/**
* @var boolean whether validation process should take into account IDN (internationalized domain
* names). Defaults to false meaning that validation of emails containing IDN will always fail.
*/
public $enableIDN = false;


/**
* Initializes the validator.
Expand Down Expand Up @@ -81,10 +87,18 @@ public function validateAttribute($object, $attribute)
public function validateValue($value)
{
// make sure string length is limited to avoid DOS attacks
$valid = is_string($value) && strlen($value) <= 254
&& (preg_match($this->pattern, $value) || $this->allowName && preg_match($this->fullPattern, $value));
if (!is_string($value) || strlen($value) >= 255) {
return false;
}
if (($atPosition = strpos($value, '@')) === false) {
return false;
}
$domain = rtrim(substr($value, $atPosition + 1), '>');
if ($this->enableIDN) {
$value = idn_to_ascii(ltrim(substr($value, 0, $atPosition), '<')) . '@' . idn_to_ascii($domain);
}
$valid = preg_match($this->pattern, $value) || $this->allowName && preg_match($this->fullPattern, $value);
if ($valid) {
$domain = rtrim(substr($value, strpos($value, '@') + 1), '>');
if ($this->checkMX && function_exists('checkdnsrr')) {
$valid = checkdnsrr($domain, 'MX');
}
Expand All @@ -99,9 +113,11 @@ public function validateValue($value)
* Returns the JavaScript needed for performing client-side validation.
* @param \yii\base\Model $object the data object being validated
* @param string $attribute the name of the attribute to be validated.
* @param \yii\base\View $view the view object that is going to be used to render views or view files
* containing a model form with this validator applied.
* @return string the client-side validation script.
*/
public function clientValidateAttribute($object, $attribute)
public function clientValidateAttribute($object, $attribute, $view)
{
$options = array(
'pattern' => new JsExpression($this->pattern),
Expand All @@ -111,11 +127,16 @@ public function clientValidateAttribute($object, $attribute)
'{attribute}' => $object->getAttributeLabel($attribute),
'{value}' => $object->$attribute,
))),
'enableIDN' => (boolean)$this->enableIDN,
);
if ($this->skipOnEmpty) {
$options['skipOnEmpty'] = 1;
}

$view->registerAssetBundle('yii/validation');
if ($this->enableIDN) {
$view->registerAssetBundle('punycode');
}
return 'yii.validation.email(value, messages, ' . Json::encode($options) . ');';
}
}
4 changes: 3 additions & 1 deletion yii/validators/InlineValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,12 +79,14 @@ public function validateAttribute($object, $attribute)
*
* @param \yii\base\Model $object the data object being validated
* @param string $attribute the name of the attribute to be validated.
* @param \yii\base\View $view the view object that is going to be used to render views or view files
* containing a model form with this validator applied.
* @return string the client-side validation script. Null if the validator does not support
* client-side validation.
* @see enableClientValidation
* @see \yii\web\ActiveForm::enableClientValidation
*/
public function clientValidateAttribute($object, $attribute)
public function clientValidateAttribute($object, $attribute, $view)
{
if ($this->clientValidate !== null) {
$method = $this->clientValidate;
Expand Down
5 changes: 4 additions & 1 deletion yii/validators/NumberValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,11 @@ public function validateValue($value)
* Returns the JavaScript needed for performing client-side validation.
* @param \yii\base\Model $object the data object being validated
* @param string $attribute the name of the attribute to be validated.
* @param \yii\base\View $view the view object that is going to be used to render views or view files
* containing a model form with this validator applied.
* @return string the client-side validation script.
*/
public function clientValidateAttribute($object, $attribute)
public function clientValidateAttribute($object, $attribute, $view)
{
$label = $object->getAttributeLabel($attribute);
$value = $object->$attribute;
Expand Down Expand Up @@ -149,6 +151,7 @@ public function clientValidateAttribute($object, $attribute)
$options['skipOnEmpty'] = 1;
}

$view->registerAssetBundle('yii/validation');
return 'yii.validation.number(value, messages, ' . Json::encode($options) . ');';
}
}
5 changes: 4 additions & 1 deletion yii/validators/RangeValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -81,9 +81,11 @@ public function validateValue($value)
* Returns the JavaScript needed for performing client-side validation.
* @param \yii\base\Model $object the data object being validated
* @param string $attribute the name of the attribute to be validated.
* @param \yii\base\View $view the view object that is going to be used to render views or view files
* containing a model form with this validator applied.
* @return string the client-side validation script.
*/
public function clientValidateAttribute($object, $attribute)
public function clientValidateAttribute($object, $attribute, $view)
{
$range = array();
foreach ($this->range as $value) {
Expand All @@ -101,6 +103,7 @@ public function clientValidateAttribute($object, $attribute)
$options['skipOnEmpty'] = 1;
}

$view->registerAssetBundle('yii/validation');
return 'yii.validation.range(value, messages, ' . json_encode($options) . ');';
}
}
5 changes: 4 additions & 1 deletion yii/validators/RegularExpressionValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -79,10 +79,12 @@ public function validateValue($value)
* Returns the JavaScript needed for performing client-side validation.
* @param \yii\base\Model $object the data object being validated
* @param string $attribute the name of the attribute to be validated.
* @param \yii\base\View $view the view object that is going to be used to render views or view files
* containing a model form with this validator applied.
* @return string the client-side validation script.
* @throws InvalidConfigException if the "pattern" is not a valid regular expression
*/
public function clientValidateAttribute($object, $attribute)
public function clientValidateAttribute($object, $attribute, $view)
{
$pattern = $this->pattern;
$pattern = preg_replace('/\\\\x\{?([0-9a-fA-F]+)\}?/', '\u$1', $pattern);
Expand Down Expand Up @@ -110,6 +112,7 @@ public function clientValidateAttribute($object, $attribute)
$options['skipOnEmpty'] = 1;
}

$view->registerAssetBundle('yii/validation');
return 'yii.validation.regularExpression(value, messages, ' . Json::encode($options) . ');';
}
}
5 changes: 4 additions & 1 deletion yii/validators/RequiredValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -102,9 +102,11 @@ public function validateValue($value)
* Returns the JavaScript needed for performing client-side validation.
* @param \yii\base\Model $object the data object being validated
* @param string $attribute the name of the attribute to be validated.
* @param \yii\base\View $view the view object that is going to be used to render views or view files
* containing a model form with this validator applied.
* @return string the client-side validation script.
*/
public function clientValidateAttribute($object, $attribute)
public function clientValidateAttribute($object, $attribute, $view)
{
$options = array();
if ($this->requiredValue !== null) {
Expand All @@ -124,6 +126,7 @@ public function clientValidateAttribute($object, $attribute)
'{value}' => $object->$attribute,
)));

$view->registerAssetBundle('yii/validation');
return 'yii.validation.required(value, messages, ' . json_encode($options) . ');';
}
}
5 changes: 4 additions & 1 deletion yii/validators/StringValidator.php
Original file line number Diff line number Diff line change
Expand Up @@ -126,9 +126,11 @@ public function validateValue($value)
* Returns the JavaScript needed for performing client-side validation.
* @param \yii\base\Model $object the data object being validated
* @param string $attribute the name of the attribute to be validated.
* @param \yii\base\View $view the view object that is going to be used to render views or view files
* containing a model form with this validator applied.
* @return string the client-side validation script.
*/
public function clientValidateAttribute($object, $attribute)
public function clientValidateAttribute($object, $attribute, $view)
{
$label = $object->getAttributeLabel($attribute);
$value = $object->$attribute;
Expand Down Expand Up @@ -168,6 +170,7 @@ public function clientValidateAttribute($object, $attribute)
$options['skipOnEmpty'] = 1;
}

$view->registerAssetBundle('yii/validation');
return 'yii.validation.string(value, messages, ' . json_encode($options) . ');';
}
}
Expand Down
Loading

0 comments on commit 992e902

Please sign in to comment.