Visman 7 سال پیش
والد
کامیت
f35e93627c

+ 33 - 46
app/Core/Validator.php

@@ -4,6 +4,7 @@ namespace ForkBB\Core;
 
 
 use ForkBB\Core\Container;
 use ForkBB\Core\Container;
 use ForkBB\Core\File;
 use ForkBB\Core\File;
+use ForkBB\Core\Validators;
 use RuntimeException;
 use RuntimeException;
 
 
 class Validator
 class Validator
@@ -108,12 +109,10 @@ class Validator
             'absent'        => [$this, 'vAbsent'],
             'absent'        => [$this, 'vAbsent'],
             'array'         => [$this, 'vArray'],
             'array'         => [$this, 'vArray'],
             'checkbox'      => [$this, 'vCheckbox'],
             'checkbox'      => [$this, 'vCheckbox'],
-            'email'         => [$this, 'vEmail'],
             'file'          => [$this, 'vFile'],
             'file'          => [$this, 'vFile'],
             'image'         => [$this, 'vImage'],
             'image'         => [$this, 'vImage'],
             'in'            => [$this, 'vIn'],
             'in'            => [$this, 'vIn'],
             'integer'       => [$this, 'vInteger'],
             'integer'       => [$this, 'vInteger'],
-            'login'         => [$this, 'vLogin'],
             'max'           => [$this, 'vMax'],
             'max'           => [$this, 'vMax'],
             'min'           => [$this, 'vMin'],
             'min'           => [$this, 'vMin'],
             'numeric'       => [$this, 'vNumeric'],
             'numeric'       => [$this, 'vNumeric'],
@@ -171,11 +170,20 @@ class Validator
             $rules = [];
             $rules = [];
             // перебор правил для текущего поля
             // перебор правил для текущего поля
             foreach (\explode('|', $raw) as $rule) { //???? нужно экранирование для разделителей
             foreach (\explode('|', $raw) as $rule) { //???? нужно экранирование для разделителей
-                 $tmp = \explode(':', $rule, 2);
-                 if (empty($this->validators[$tmp[0]])) {
-                     throw new RuntimeException($tmp[0] . ' validator not found');
+                 $vs = \explode(':', $rule, 2);
+                 if (empty($this->validators[$vs[0]])) {
+                     try {
+                        $validator = $this->c->{'VL' . $vs[0]};
+                     } catch (Exception $e) {
+                        $validator = null;
+                     }
+                     if ($validator instanceof Validators) {
+                        $this->validators[$vs[0]] = [$validator, $vs[0]];
+                     } else {
+                        throw new RuntimeException($vs[0] . ' validator not found');
+                     }
                  }
                  }
-                 $rules[$tmp[0]] = isset($tmp[1]) ? $tmp[1] : '';
+                 $rules[$vs[0]] = isset($vs[1]) ? $vs[1] : '';
             }
             }
             if (isset($suffix)) {
             if (isset($suffix)) {
                 $this->rules[$field]['array'][$suffix] = $rules;
                 $this->rules[$field]['array'][$suffix] = $rules;
@@ -449,7 +457,7 @@ class Validator
      *
      *
      * @return mixed
      * @return mixed
      */
      */
-    protected function vAbsent($v, $value, $attr)
+    protected function vAbsent(Validator $v, $value, $attr)
     {
     {
         if (null !== $value) {
         if (null !== $value) {
             $this->addError('The :alias should be absent');
             $this->addError('The :alias should be absent');
@@ -461,7 +469,7 @@ class Validator
         }
         }
     }
     }
 
 
-    protected function vRequired($v, $value)
+    protected function vRequired(Validator $v, $value)
     {
     {
         if (\is_string($value)) {
         if (\is_string($value)) {
             if (\strlen(\preg_replace('%^\s+|\s+$%u', '', $value)) > 0) {
             if (\strlen(\preg_replace('%^\s+|\s+$%u', '', $value)) > 0) {
@@ -478,7 +486,7 @@ class Validator
         return null;
         return null;
     }
     }
 
 
-    protected function vRequiredWith($v, $value, $attr)  //???????????????????????
+    protected function vRequiredWith(Validator $v, $value, $attr)  //???????????????????????
     {
     {
         foreach (\explode(',', $attr) as $field) {
         foreach (\explode(',', $attr) as $field) {
             if (null !== $this->__get($field)) {     // если есть хотя бы одно поле,
             if (null !== $this->__get($field)) {     // если есть хотя бы одно поле,
@@ -498,7 +506,7 @@ class Validator
 #        }
 #        }
     }
     }
 
 
-    protected function vString($v, $value, $attr)
+    protected function vString(Validator $v, $value, $attr)
     {
     {
         if (null === $value) {
         if (null === $value) {
             return null;
             return null;
@@ -523,7 +531,7 @@ class Validator
         }
         }
     }
     }
 
 
-    protected function vNumeric($v, $value)
+    protected function vNumeric(Validator $v, $value)
     {
     {
         if (null === $value) {
         if (null === $value) {
             return null;
             return null;
@@ -535,7 +543,7 @@ class Validator
         }
         }
     }
     }
 
 
-    protected function vInteger($v, $value)
+    protected function vInteger(Validator $v, $value)
     {
     {
         if (null === $value) {
         if (null === $value) {
             return null;
             return null;
@@ -547,7 +555,7 @@ class Validator
         }
         }
     }
     }
 
 
-    protected function vArray($v, $value, $attr)
+    protected function vArray(Validator $v, $value, $attr)
     {
     {
         if (null !== $value && ! \is_array($value)) {
         if (null !== $value && ! \is_array($value)) {
             $this->addError('The :alias must be array');
             $this->addError('The :alias must be array');
@@ -598,9 +606,7 @@ class Validator
         }
         }
     }
     }
 
 
-
-
-    protected function vMin($v, $value, $attr)
+    protected function vMin(Validator $v, $value, $attr)
     {
     {
         if (\is_string($value)) {
         if (\is_string($value)) {
             $isBytes = \strpos($attr, 'bytes');
             $isBytes = \strpos($attr, 'bytes');
@@ -624,7 +630,7 @@ class Validator
         return $value;
         return $value;
     }
     }
 
 
-    protected function vMax($v, $value, $attr)
+    protected function vMax(Validator $v, $value, $attr)
     {
     {
         if (\is_string($value)) {
         if (\is_string($value)) {
             $isBytes = \strpos($attr, 'bytes');
             $isBytes = \strpos($attr, 'bytes');
@@ -661,7 +667,7 @@ class Validator
         return $value;
         return $value;
     }
     }
 
 
-    protected function vToken($v, $value, $attr, $args)
+    protected function vToken(Validator $v, $value, $attr, $args)
     {
     {
         if (! \is_array($args)) {
         if (! \is_array($args)) {
             $args = [];
             $args = [];
@@ -674,12 +680,12 @@ class Validator
         }
         }
     }
     }
 
 
-    protected function vCheckbox($v, $value)
+    protected function vCheckbox(Validator $v, $value)
     {
     {
         return null === $value ? false : (string) $value;
         return null === $value ? false : (string) $value;
     }
     }
 
 
-    protected function vReferer($v, $value, $attr, $args)
+    protected function vReferer(Validator $v, $value, $attr, $args)
     {
     {
         if (! \is_array($args)) {
         if (! \is_array($args)) {
             $args = [];
             $args = [];
@@ -687,21 +693,7 @@ class Validator
         return $this->c->Router->validate($value, $attr, $args);
         return $this->c->Router->validate($value, $attr, $args);
     }
     }
 
 
-    protected function vEmail($v, $value)
-    {
-        if (null === $value || '' === $value) { //???? перед правилом должно стоять правило `required`
-            return null;
-        }
-        $email = $this->c->Mail->valid($value, true);
-        if (false === $email) {
-            $this->addError('The :alias is not valid email');
-            return $value;
-        } else {
-            return $email;
-        }
-    }
-
-    protected function vSame($v, $value, $attr)
+    protected function vSame(Validator $v, $value, $attr)
     {
     {
         if (! $this->getStatus($attr) || $value === $this->__get($attr)) {
         if (! $this->getStatus($attr) || $value === $this->__get($attr)) {
             return $value;
             return $value;
@@ -711,7 +703,7 @@ class Validator
         }
         }
     }
     }
 
 
-    protected function vRegex($v, $value, $attr)
+    protected function vRegex(Validator $v, $value, $attr)
     {
     {
         if (null !== $value
         if (null !== $value
             && (! \is_string($value) || ! \preg_match($attr, $value))
             && (! \is_string($value) || ! \preg_match($attr, $value))
@@ -723,17 +715,12 @@ class Validator
         }
         }
     }
     }
 
 
-    protected function vPassword($v, $value)
+    protected function vPassword(Validator $v, $value)
     {
     {
         return $this->vRegex($v, $value, '%[^\x20][\x20][^\x20]%');
         return $this->vRegex($v, $value, '%[^\x20][\x20][^\x20]%');
     }
     }
 
 
-    protected function vLogin($v, $value)
-    {
-        return $this->vRegex($v, $value, '%^\p{L}[\p{L}\p{N}\x20\._-]+$%uD');
-    }
-
-    protected function vIn($v, $value, $attr)
+    protected function vIn(Validator $v, $value, $attr)
     {
     {
         if (null !== $value && ! \in_array($value, \explode(',', $attr))) {
         if (null !== $value && ! \in_array($value, \explode(',', $attr))) {
             $this->addError('The :alias contains an invalid value');
             $this->addError('The :alias contains an invalid value');
@@ -741,7 +728,7 @@ class Validator
         return $value;
         return $value;
     }
     }
 
 
-    protected function vNotIn($v, $value, $attr)
+    protected function vNotIn(Validator $v, $value, $attr)
     {
     {
         if (null !== $value && \in_array($value, \explode(',', $attr))) {
         if (null !== $value && \in_array($value, \explode(',', $attr))) {
             $this->addError('The :alias contains an invalid value');
             $this->addError('The :alias contains an invalid value');
@@ -750,7 +737,7 @@ class Validator
     }
     }
 
 
 
 
-    protected function vFile($v, $value, $attr)
+    protected function vFile(Validator $v, $value, $attr)
     {
     {
         if (null === $value) {
         if (null === $value) {
             return null;
             return null;
@@ -776,7 +763,7 @@ class Validator
         return $value;
         return $value;
     }
     }
 
 
-    protected function vImage($v, $value, $attr)
+    protected function vImage(Validator $v, $value, $attr)
     {
     {
         $value = $this->vFile($v, $value, $attr);
         $value = $this->vFile($v, $value, $attr);
 
 

+ 38 - 0
app/Core/Validators.php

@@ -0,0 +1,38 @@
+<?php
+
+namespace ForkBB\Core;
+
+use ForkBB\Core\Container;
+use RuntimeException;
+
+abstract class Validators
+{
+    /**
+     * Контейнер
+     * @var Container
+     */
+    protected $c;
+
+    /**
+     * Конструктор
+     *
+     * @param Container $container
+     */
+    public function __construct(Container $container)
+    {
+        $this->c = $container;
+    }
+
+    /**
+     * Выбрасывает исключение при отсутствии метода
+     *
+     * @param string $name
+     * @param array $args
+     *
+     * @throws RuntimeException
+     */
+    public function __call($name, array $args)
+    {
+        throw new RuntimeException($name . ' validator not found');
+    }
+}

+ 2 - 2
app/Models/Pages/Admin/Options.php

@@ -70,8 +70,8 @@ class Options extends Admin
                     'o_avatars_width'         => 'required|integer|min:50|max:999',
                     'o_avatars_width'         => 'required|integer|min:50|max:999',
                     'o_avatars_height'        => 'required|integer|min:50|max:999',
                     'o_avatars_height'        => 'required|integer|min:50|max:999',
                     'o_avatars_size'          => 'required|integer|min:0|max:9999999',
                     'o_avatars_size'          => 'required|integer|min:0|max:9999999',
-                    'o_admin_email'           => 'required|string:trim,lower|max:80|email',
-                    'o_webmaster_email'       => 'required|string:trim,lower|max:80|email',
+                    'o_admin_email'           => 'required|string:trim,lower|email',
+                    'o_webmaster_email'       => 'required|string:trim,lower|email',
                     'o_forum_subscriptions'   => 'required|integer|in:0,1',
                     'o_forum_subscriptions'   => 'required|integer|in:0,1',
                     'o_topic_subscriptions'   => 'required|integer|in:0,1',
                     'o_topic_subscriptions'   => 'required|integer|in:0,1',
                     'o_smtp_host'             => 'string:trim|max:255',
                     'o_smtp_host'             => 'string:trim|max:255',

+ 2 - 3
app/Models/Pages/Auth.php

@@ -156,15 +156,14 @@ class Auth extends Page
 
 
             $v = $this->c->Validator->reset()
             $v = $this->c->Validator->reset()
                 ->addValidators([
                 ->addValidators([
-                    'check_email' => [$this->c->Validators, 'vCheckEmail'],
                 ])->addRules([
                 ])->addRules([
                     'token' => 'token:Forget',
                     'token' => 'token:Forget',
-                    'email' => 'required|string:trim,lower|email|check_email:exists,flood',
+                    'email' => 'required|string:trim,lower|email:banned,exists,flood',
                 ])->addAliases([
                 ])->addAliases([
                 ])->addMessages([
                 ])->addMessages([
                     'email.email' => 'Invalid email',
                     'email.email' => 'Invalid email',
                 ])->addArguments([
                 ])->addArguments([
-                    'email.check_email' => $tmpUser, // сюда идет возрат данных по найденному пользователю
+                    'email.email' => $tmpUser, // сюда идет возрат данных по найденному пользователю
                 ]);
                 ]);
 
 
             if ($v->validation($_POST)) {
             if ($v->validation($_POST)) {

+ 9 - 13
app/Models/Pages/PostValidatorTrait.php

@@ -27,8 +27,6 @@ trait PostValidatorTrait
             && ! \preg_match('%\p{Ll}%u', $subject)
             && ! \preg_match('%\p{Ll}%u', $subject)
         ) {
         ) {
             $v->addError('All caps subject');
             $v->addError('All caps subject');
-        } elseif (! $executive) {
-            $this->c->Validators->vNoURL($v, $subject, null, null);
         }
         }
         return $subject;
         return $subject;
     }
     }
@@ -102,19 +100,13 @@ trait PostValidatorTrait
     protected function messageValidator(Model $model, $marker, array $args, $editPost = false, $editSubject = false)
     protected function messageValidator(Model $model, $marker, array $args, $editPost = false, $editSubject = false)
     {
     {
         if ($this->user->isGuest) {
         if ($this->user->isGuest) {
-            $ruleEmail    = ('1' == $this->c->config->p_force_guest_email ? 'required|' : '') . 'string:trim,lower|email|check_email';
-            $ruleUsername = 'required|string:trim,spaces|min:2|max:25|login|check_username';
+            $ruleEmail    = ('1' == $this->c->config->p_force_guest_email ? 'required|' : '') . 'string:trim,lower|email:banned';
+            $ruleUsername = 'required|string:trim,spaces|username';
         } else {
         } else {
             $ruleEmail    = 'absent';
             $ruleEmail    = 'absent';
             $ruleUsername = 'absent';
             $ruleUsername = 'absent';
         }
         }
 
 
-        if ($editSubject) {
-            $ruleSubject = 'required|string:trim,spaces|min:1|max:70|check_subject';
-        } else {
-            $ruleSubject = 'absent';
-        }
-
         if ($this->user->isAdmin || $this->user->isModerator($model)) {
         if ($this->user->isAdmin || $this->user->isModerator($model)) {
             if ($editSubject) {
             if ($editSubject) {
                 $ruleStickTopic = 'checkbox';
                 $ruleStickTopic = 'checkbox';
@@ -142,6 +134,12 @@ trait PostValidatorTrait
             $executive          = false;
             $executive          = false;
         }
         }
 
 
+        if ($editSubject) {
+            $ruleSubject = 'required|string:trim,spaces|min:1|max:70|' . ($executive ? '' : 'noURL|') . 'check_subject';
+        } else {
+            $ruleSubject = 'absent';
+        }
+
         if ('1' == $this->c->config->o_smilies) {
         if ('1' == $this->c->config->o_smilies) {
             $ruleHideSmilies = 'checkbox';
             $ruleHideSmilies = 'checkbox';
         } else {
         } else {
@@ -150,8 +148,6 @@ trait PostValidatorTrait
 
 
         $v = $this->c->Validator->reset()
         $v = $this->c->Validator->reset()
             ->addValidators([
             ->addValidators([
-                'check_email'    => [$this->c->Validators, 'vCheckEmail'],
-                'check_username' => [$this->c->Validators, 'vCheckUsername'],
                 'check_subject'  => [$this, 'vCheckSubject'],
                 'check_subject'  => [$this, 'vCheckSubject'],
                 'check_message'  => [$this, 'vCheckMessage'],
                 'check_message'  => [$this, 'vCheckMessage'],
                 'check_timeout'  => [$this, 'vCheckTimeout'],
                 'check_timeout'  => [$this, 'vCheckTimeout'],
@@ -176,7 +172,7 @@ trait PostValidatorTrait
                 'token'                 => $args,
                 'token'                 => $args,
                 'subject.check_subject' => $executive,
                 'subject.check_subject' => $executive,
                 'message.check_message' => $executive,
                 'message.check_message' => $executive,
-                'email.check_email'     => $this->user,
+                'email.email'           => $this->user,
             ])->addMessages([
             ])->addMessages([
                 'username.login' => 'Login format',
                 'username.login' => 'Login format',
             ]);
             ]);

+ 9 - 12
app/Models/Pages/Profile.php

@@ -56,13 +56,13 @@ class Profile extends Page
 
 
         if ($isEdit && 'POST' === $method) {
         if ($isEdit && 'POST' === $method) {
             if ($this->rules->rename) {
             if ($this->rules->rename) {
-                $ruleUsername = 'required|string:trim,spaces|min:2|max:25|login|check_username';
+                $ruleUsername = 'required|string:trim,spaces|username';
             } else {
             } else {
                 $ruleUsername = 'absent';
                 $ruleUsername = 'absent';
             }
             }
 
 
             if ($this->rules->setTitle) {
             if ($this->rules->setTitle) {
-                $ruleTitle = 'string:trim|max:50|no_url';
+                $ruleTitle = 'string:trim|max:50|noURL';
             } else {
             } else {
                 $ruleTitle = 'absent';
                 $ruleTitle = 'absent';
             }
             }
@@ -95,8 +95,6 @@ class Profile extends Page
 
 
             $v = $this->c->Validator->reset()
             $v = $this->c->Validator->reset()
                 ->addValidators([
                 ->addValidators([
-                    'no_url'          => [$this->c->Validators, 'vNoURL'],
-                    'check_username'  => [$this->c->Validators, 'vCheckUsername'],
                     'check_signature' => [$this, 'vCheckSignature'],
                     'check_signature' => [$this, 'vCheckSignature'],
                 ])->addRules([
                 ])->addRules([
                     'token'         => 'token:EditUserProfile',
                     'token'         => 'token:EditUserProfile',
@@ -105,9 +103,9 @@ class Profile extends Page
                     'upload_avatar' => $ruleAvatar,
                     'upload_avatar' => $ruleAvatar,
                     'delete_avatar' => $ruleDelAvatar,
                     'delete_avatar' => $ruleDelAvatar,
                     'admin_note'    => $ruleAdminNote,
                     'admin_note'    => $ruleAdminNote,
-                    'realname'      => 'string:trim|max:40|no_url',
+                    'realname'      => 'string:trim|max:40|noURL:1',
                     'gender'        => 'required|integer|in:0,1,2',
                     'gender'        => 'required|integer|in:0,1,2',
-                    'location'      => 'string:trim|max:30|no_url',
+                    'location'      => 'string:trim|max:30|noURL:1',
                     'email_setting' => 'required|integer|in:0,1,2',
                     'email_setting' => 'required|integer|in:0,1,2',
                     'url'           => $ruleWebsite,
                     'url'           => $ruleWebsite,
                     'signature'     => $ruleSignature,
                     'signature'     => $ruleSignature,
@@ -124,8 +122,8 @@ class Profile extends Page
                     'url'           => 'Website',
                     'url'           => 'Website',
                     'signature'     => 'Signature',
                     'signature'     => 'Signature',
                 ])->addArguments([
                 ])->addArguments([
-                    'token'                   => ['id' => $this->curUser->id],
-                    'username.check_username' => $this->curUser,
+                    'token'             => ['id' => $this->curUser->id],
+                    'username.username' => $this->curUser,
                 ])->addMessages([
                 ])->addMessages([
                 ]);
                 ]);
 
 
@@ -210,17 +208,16 @@ class Profile extends Page
             $v = $this->c->Validator->reset()
             $v = $this->c->Validator->reset()
                 ->addValidators([
                 ->addValidators([
                     'check_password' => [$this, 'vCheckPassword'],
                     'check_password' => [$this, 'vCheckPassword'],
-                    'check_email'    => [$this->c->Validators, 'vCheckEmail'],
                 ])->addRules([
                 ])->addRules([
                     'token'     => 'token:ChangeUserEmail',
                     'token'     => 'token:ChangeUserEmail',
                     'password'  => 'required|string:trim|check_password',
                     'password'  => 'required|string:trim|check_password',
-                    'new_email' => 'required|string:trim,lower|email|check_email:unique,flood',
+                    'new_email' => 'required|string:trim,lower|email:banned,unique,flood',
                 ])->addAliases([
                 ])->addAliases([
                     'new_email' => 'New email',
                     'new_email' => 'New email',
                     'password'  => 'Your password',
                     'password'  => 'Your password',
                 ])->addArguments([
                 ])->addArguments([
-                    'token'                 => ['id' => $this->curUser->id],
-                    'new_email.check_email' => $this->curUser,
+                    'token'           => ['id' => $this->curUser->id],
+                    'new_email.email' => $this->curUser,
                 ])->addMessages([
                 ])->addMessages([
                 ]);
                 ]);
 
 

+ 2 - 4
app/Models/Pages/Register.php

@@ -20,14 +20,12 @@ class Register extends Page
 
 
         $v = $this->c->Validator->reset()
         $v = $this->c->Validator->reset()
             ->addValidators([
             ->addValidators([
-                'check_email'    => [$this->c->Validators, 'vCheckEmail'],
-                'check_username' => [$this->c->Validators, 'vCheckUsername'],
             ])->addRules([
             ])->addRules([
                 'token'    => 'token:RegisterForm',
                 'token'    => 'token:RegisterForm',
                 'agree'    => 'required|token:Register',
                 'agree'    => 'required|token:Register',
                 'on'       => 'integer',
                 'on'       => 'integer',
-                'email'    => 'required_with:on|string:trim,lower|email|check_email:unique',
-                'username' => 'required_with:on|string:trim,spaces|min:2|max:25|login|check_username',
+                'email'    => 'required_with:on|string:trim,lower|email:banned,unique',
+                'username' => 'required_with:on|string:trim,spaces|username',
                 'password' => 'required_with:on|string|min:16|password',
                 'password' => 'required_with:on|string|min:16|password',
             ])->addAliases([
             ])->addAliases([
                 'email'    => 'Email',
                 'email'    => 'Email',

+ 0 - 160
app/Models/Validators.php

@@ -1,160 +0,0 @@
-<?php
-
-namespace ForkBB\Models;
-
-use ForkBB\Core\Container;
-use ForkBB\Core\Validator;
-use ForkBB\Models\User\Model as User;
-
-class Validators
-{
-    /**
-     * Контейнер
-     * @var Container
-     */
-    protected $c;
-
-    /**
-     * Конструктор
-     *
-     * @param Container $container
-     */
-    public function __construct(Container $container)
-    {
-        $this->c = $container;
-    }
-
-    /**
-     * Дополнительная проверка username
-     *
-     * @param Validator $v
-     * @param string $username
-     * @param string $z
-     * @param mixed $originalUser
-     *
-     * @return string
-     */
-    public function vCheckUsername(Validator $v, $username, $z, $originalUser)
-    {
-        if ($originalUser instanceof User) {
-            $id   = $originalUser->id;
-            $old  = $originalUser->username;
-        } else {
-            $id   = null;
-            $old  = null;
-        }
-
-        if ($old !== $username) {
-
-            $user = $this->c->users->create(['id' => $id, 'username' => $username]);
-
-            // username = Гость
-            if (\preg_match('%^(guest|' . \preg_quote(\ForkBB\__('Guest'), '%') . ')$%iu', $username)) { // ???? а зачем?
-                $v->addError('Username guest');
-            // цензура
-            } elseif ($this->c->censorship->censor($username) !== $username) {
-                $v->addError('Username censor');
-            // username забанен
-            } elseif ($this->c->bans->isBanned($user) > 0) {
-                $v->addError('Banned username');
-            // есть пользователь с похожим именем
-            } elseif (empty($v->getErrors()) && ! $this->c->users->isUniqueName($user)) {
-                $v->addError('Username not unique');
-            }
-        }
-
-        return $username;
-    }
-
-    /**
-     * Дополнительная проверка email
-     * WARNING!!!
-     * Если передан гость 4-ым параметром, то проверка уникальности email не проводится
-     *
-     * @param Validator $v
-     * @param string $email
-     * @param string $attrs
-     * @param mixed $originalUser
-     *
-     * @return string
-     */
-    public function vCheckEmail(Validator $v, $email, $attrs, $originalUser)
-    {
-        // email забанен
-        if ($this->c->bans->isBanned($this->c->users->create(['email' => $email])) > 0) {
-            $v->addError('Banned email');
-        // остальные проверки
-        } elseif (empty($v->getErrors())) {
-            $attrs = \array_flip(\explode(',', $attrs));
-            $ok    = true;
-            $user  = true;
-
-            // наличие
-            if (isset($attrs['exists'])) {
-                $user = $this->c->users->load($email, 'email');
-
-                if (! $user instanceof User) {
-                    $v->addError('Invalid email');
-                    $ok = false;
-                }
-            }
-
-            // уникальность
-            if ($ok && isset($attrs['unique']) && (! $originalUser instanceof User || ! $originalUser->isGuest)) {
-                if (true === $user) {
-                    $user = $this->c->users->load($email, 'email');
-                }
-
-                $id = $originalUser instanceof User ? $originalUser->id : true;
-
-                if (($user instanceof User && $id !== $user->id) || (! $user instanceof User && 0 !== $user)) {
-                    $v->addError('Dupe email');
-                    $ok = false;
-                }
-            }
-
-            // флуд
-            if ($ok && isset($attrs['flood'])) {
-                $min = 3600;
-
-                if ($originalUser instanceof User && ! $originalUser->isGuest) {
-                    $flood = \time() - $originalUser->last_email_sent;
-                } elseif ($user instanceof User) {
-                    $flood = \time() - $user->last_email_sent;
-                } else {
-                    $flood = $min;
-                }
-                if ($flood < $min) {
-                    $v->addError(\ForkBB\__('Email flood', (int) (($min - $flood) / 60)), 'e');
-                    $ok = false;
-                }
-            }
-
-            // возврат данных пользователя через 4-ый параметр
-            if ($ok && $originalUser instanceof User && $originalUser->id < 1 && $user instanceof User) {
-                $originalUser->setAttrs($user->getAttrs());
-            }
-        }
-        return $email;
-    }
-
-    /**
-     * Дополнительная проверка на отсутствие url в значении
-     *
-     * @param Validator $v
-     * @param mixed $value
-     * @param string $flag
-     *
-     * @return mixed
-     */
-    public function vNoURL(Validator $v, $value, $flag)
-    {
-        $flag = empty($flag) || '1' != $this->c->user->g_post_links;
-
-        if ($flag && \preg_match('%https?://|www\.%i', $value)) {
-            $v->addError('The :alias contains a link');
-        }
-        return $value;
-    }
-
-}

+ 92 - 0
app/Models/Validators/Email.php

@@ -0,0 +1,92 @@
+<?php
+
+namespace ForkBB\Models\Validators;
+
+use ForkBB\Core\Validator;
+use ForkBB\Core\Validators;
+use ForkBB\Models\User\Model as User;
+
+class Email extends Validators
+{
+    const FLOOD = 3600;
+
+    /**
+     * Проверяет email
+     * WARNING!!!
+     * Если передан гость 4-ым параметром, то проверка уникальности email не проводится
+     *
+     * @param Validator $v
+     * @param string $email
+     * @param string $attrs
+     * @param mixed $originalUser
+     *
+     * @return string
+     */
+    public function email(Validator $v, $email, $attrs, $originalUser)
+    {
+        // поле отсутствует
+        if (null === $email) {
+            return null;
+        // это не email
+        } elseif (false === ($result = $this->c->Mail->valid($email, true))) {
+            $v->addError('The :alias is not valid email');
+            return $email;
+        // есть другие ошибки
+        } elseif (! empty($v->getErrors())) {
+            return $result;
+        }
+
+        $email = $result;
+        $attrs = \array_flip(\explode(',', $attrs));
+        $ok    = true;
+        $user  = true;
+
+        // email забанен
+        if ($ok && isset($attrs['banned']) && $this->c->bans->isBanned($this->c->users->create(['email' => $email])) > 0) {
+            $v->addError('Banned email');
+            $ok = false;
+        }
+        // отсутствует пользователь с таким email (или их больше одного O_o)
+        if (isset($attrs['exists'])) {
+            $user = $this->c->users->load($email, 'email');
+
+            if (! $user instanceof User) {
+                $v->addError('Invalid email');
+                $ok = false;
+            }
+        }
+        // email не уникален
+        if ($ok && isset($attrs['unique']) && (! $originalUser instanceof User || ! $originalUser->isGuest)) {
+            if (true === $user) {
+                $user = $this->c->users->load($email, 'email');
+            }
+
+            $id = $originalUser instanceof User ? $originalUser->id : true;
+
+            if (($user instanceof User && $id !== $user->id) || (! $user instanceof User && 0 !== $user)) {
+                $v->addError('Dupe email');
+                $ok = false;
+            }
+        }
+        // проверка на флуд интервал
+        if ($ok && isset($attrs['flood'])) {
+            if ($originalUser instanceof User && ! $originalUser->isGuest) {
+                $flood = \time() - $originalUser->last_email_sent;
+            } elseif ($user instanceof User) {
+                $flood = \time() - $user->last_email_sent;
+            } else {
+                $flood = self::FLOOD;
+            }
+            if ($flood < self::FLOOD) {
+                $v->addError(\ForkBB\__('Email flood', (int) ((self::FLOOD - $flood) / 60)), 'e');
+                $ok = false;
+            }
+        }
+        // возврат данных пользователя через 4-ый параметр
+        if ($ok && $originalUser instanceof User && $originalUser->id < 1 && $user instanceof User) {
+            $originalUser->setAttrs($user->getAttrs());
+        }
+
+        return $email;
+    }
+}

+ 28 - 0
app/Models/Validators/NoURL.php

@@ -0,0 +1,28 @@
+<?php
+
+namespace ForkBB\Models\Validators;
+
+use ForkBB\Core\Validator;
+use ForkBB\Core\Validators;
+
+class NoURL extends Validators
+{
+    /**
+     * Проверяет значение на отсутствие ссылки, если пользователю запрещено использовать ссылки или включен флаг принудительной проверки
+     *
+     * @param Validator $v
+     * @param mixed $value
+     * @param string $flag
+     *
+     * @return mixed
+     */
+    public function noURL(Validator $v, $value, $flag)
+    {
+        if ((! empty($flag) || '1' != $this->c->user->g_post_links)
+            && \preg_match('%https?://|www\.%i', $value)
+        ) {
+            $v->addError('The :alias contains a link');
+        }
+        return $value;
+    }
+}

+ 55 - 0
app/Models/Validators/Username.php

@@ -0,0 +1,55 @@
+<?php
+
+namespace ForkBB\Models\Validators;
+
+use ForkBB\Core\Validator;
+use ForkBB\Core\Validators;
+use ForkBB\Models\User\Model as User;
+
+class Username extends Validators
+{
+    /**
+     * Проверяет имя пользователя
+     *
+     * @param Validator $v
+     * @param string $username
+     * @param string $z
+     * @param mixed $originalUser
+     *
+     * @return string
+     */
+    public function username(Validator $v, $username, $z, $originalUser)
+    {
+        if ($originalUser instanceof User) {
+            $id   = $originalUser->id;
+            $old  = $originalUser->username;
+        } else {
+            $id   = null;
+            $old  = null;
+        }
+
+        if ($old !== $username) {
+
+            $user = $this->c->users->create(['id' => $id, 'username' => $username]);
+
+            // 2-25 символов, буквы, цифры, пробел, подчеркивание, точка и тире
+            if (! \preg_match('%^(?=.{2,25}$)\p{L}[\p{L}\p{N}\x20\._-]+$%uD', $username)) {
+                $v->addError('The :alias is not valid format'); // ???? выводить отдельное сообщение для username
+            // username = Гость
+            } elseif (\preg_match('%^(guest|' . \preg_quote(\ForkBB\__('Guest'), '%') . ')$%iu', $username)) { // ???? а зачем?
+                $v->addError('Username guest');
+            // цензура
+            } elseif ($this->c->censorship->censor($username) !== $username) {
+                $v->addError('Username censor');
+            // username забанен
+            } elseif ($this->c->bans->isBanned($user) > 0) {
+                $v->addError('Banned username');
+            // есть пользователь с похожим именем
+            } elseif (empty($v->getErrors()) && ! $this->c->users->isUniqueName($user)) {
+                $v->addError('Username not unique');
+            }
+        }
+
+        return $username;
+    }
+}

+ 4 - 1
app/config/main.dist.php

@@ -117,7 +117,10 @@ return [
             'file'  => '%MAX_FILE_SIZE%',
             'file'  => '%MAX_FILE_SIZE%',
             'img'   => '%MAX_IMG_SIZE%',
             'img'   => '%MAX_IMG_SIZE%',
         ],
         ],
-        'Validators' => \ForkBB\Models\Validators::class,
+
+        'VLnoURL'    => \ForkBB\Models\Validators\NoURL::class,
+        'VLusername' => \ForkBB\Models\Validators\Username::class,
+        'VLemail'    => \ForkBB\Models\Validators\Email::class,
 
 
     ],
     ],
     'multiple'  => [
     'multiple'  => [