]> git.mxchange.org Git - quix0rs-gnu-social.git/blob - lib/nickname.php
Merge remote-tracking branch 'origin/1.0.x' into 1.0.x
[quix0rs-gnu-social.git] / lib / nickname.php
1 <?php
2 /*
3  * StatusNet - the distributed open-source microblogging tool
4  * Copyright (C) 2008, 2009, StatusNet, Inc.
5  *
6  * This program is free software: you can redistribute it and/or modify
7  * it under the terms of the GNU Affero General Public License as published by
8  * the Free Software Foundation, either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU Affero General Public License for more details.
15  *
16  * You should have received a copy of the GNU Affero General Public License
17  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
18  */
19
20 class Nickname
21 {
22     /**
23      * Regex fragment for pulling a formated nickname *OR* ID number.
24      * Suitable for router def of 'id' parameters on API actions.
25      *
26      * Not guaranteed to be valid after normalization; run the string through
27      * Nickname::normalize() to get the canonical form, or Nickname::isValid()
28      * if you just need to check if it's properly formatted.
29      *
30      * This, DISPLAY_FMT, and CANONICAL_FMT replace the old NICKNAME_FMT,
31      * but be aware that these should not be enclosed in []s.
32      *
33      * @fixme would prefer to define in reference to the other constants
34      */
35     const INPUT_FMT = '(?:[0-9]+|[0-9a-zA-Z_]{1,64})';
36
37     /**
38      * Regex fragment for acceptable user-formatted variant of a nickname.
39      * This includes some chars such as underscore which will be removed
40      * from the normalized canonical form, but still must fit within
41      * field length limits.
42      *
43      * Not guaranteed to be valid after normalization; run the string through
44      * Nickname::normalize() to get the canonical form, or Nickname::isValid()
45      * if you just need to check if it's properly formatted.
46      *
47      * This and CANONICAL_FMT replace the old NICKNAME_FMT, but be aware
48      * that these should not be enclosed in []s.
49      */
50     const DISPLAY_FMT = '[0-9a-zA-Z_]{1,64}';
51
52     /**
53      * Regex fragment for checking a canonical nickname.
54      *
55      * Any non-matching string is not a valid canonical/normalized nickname.
56      * Matching strings are valid and canonical form, but may still be
57      * unavailable for registration due to blacklisting et.
58      *
59      * Only the canonical forms should be stored as keys in the database;
60      * there are multiple possible denormalized forms for each valid
61      * canonical-form name.
62      *
63      * This and DISPLAY_FMT replace the old NICKNAME_FMT, but be aware
64      * that these should not be enclosed in []s.
65      */
66     const CANONICAL_FMT = '[0-9a-z]{1,64}';
67
68     /**
69      * Maximum number of characters in a canonical-form nickname.
70      */
71     const MAX_LEN = 64;
72
73     /**
74      * Nice simple check of whether the given string is a valid input nickname,
75      * which can be normalized into an internally canonical form.
76      *
77      * Note that valid nicknames may be in use or reserved.
78      *
79      * @param string $str
80      * @return boolean
81      */
82     public static function isValid($str)
83     {
84         try {
85             self::normalize($str);
86             return true;
87         } catch (NicknameException $e) {
88             return false;
89         }
90     }
91
92     /**
93      * Validate an input nickname string, and normalize it to its canonical form.
94      * The canonical form will be returned, or an exception thrown if invalid.
95      *
96      * @param string $str
97      * @return string Normalized canonical form of $str
98      *
99      * @throws NicknameException (base class)
100      * @throws   NicknameInvalidException
101      * @throws   NicknameEmptyException
102      * @throws   NicknameTooLongException
103      */
104     public static function normalize($str)
105     {
106         if (mb_strlen($str) > self::MAX_LEN) {
107             // Display forms must also fit!
108             throw new NicknameTooLongException();
109         }
110
111         $str = trim($str);
112         $str = str_replace('_', '', $str);
113         $str = mb_strtolower($str);
114
115         if (mb_strlen($str) < 1) {
116             throw new NicknameEmptyException();
117         }
118         if (!self::isCanonical($str)) {
119             throw new NicknameInvalidException();
120         }
121
122         return $str;
123     }
124
125     /**
126      * Is the given string a valid canonical nickname form?
127      *
128      * @param string $str
129      * @return boolean
130      */
131     public static function isCanonical($str)
132     {
133         return preg_match('/^(?:' . self::CANONICAL_FMT . ')$/', $str);
134     }
135 }
136
137 class NicknameException extends ClientException
138 {
139     function __construct($msg=null, $code=400)
140     {
141         if ($msg === null) {
142             $msg = $this->defaultMessage();
143         }
144         parent::__construct($msg, $code);
145     }
146
147     /**
148      * Default localized message for this type of exception.
149      * @return string
150      */
151     protected function defaultMessage()
152     {
153         return null;
154     }
155 }
156
157 class NicknameInvalidException extends NicknameException {
158     /**
159      * Default localized message for this type of exception.
160      * @return string
161      */
162     protected function defaultMessage()
163     {
164         // TRANS: Validation error in form for registration, profile and group settings, etc.
165         return _('Nickname must have only lowercase letters and numbers and no spaces.');
166     }
167 }
168
169 class NicknameEmptyException extends NicknameException
170 {
171     /**
172      * Default localized message for this type of exception.
173      * @return string
174      */
175     protected function defaultMessage()
176     {
177         // TRANS: Validation error in form for registration, profile and group settings, etc.
178         return _('Nickname cannot be empty.');
179     }
180 }
181
182 class NicknameTooLongException extends NicknameInvalidException
183 {
184     /**
185      * Default localized message for this type of exception.
186      * @return string
187      */
188     protected function defaultMessage()
189     {
190         // TRANS: Validation error in form for registration, profile and group settings, etc.
191         return sprintf(_m('Nickname cannot be more than %d character long.',
192                           'Nickname cannot be more than %d characters long.',
193                           Nickname::MAX_LEN),
194                        Nickname::MAX_LEN);
195     }
196 }