diff options
Diffstat (limited to 'lib/nickname.php')
-rw-r--r-- | lib/nickname.php | 176 |
1 files changed, 176 insertions, 0 deletions
diff --git a/lib/nickname.php b/lib/nickname.php new file mode 100644 index 000000000..48269f3b9 --- /dev/null +++ b/lib/nickname.php @@ -0,0 +1,176 @@ +<?php +/* + * StatusNet - the distributed open-source microblogging tool + * Copyright (C) 2008, 2009, StatusNet, Inc. + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +class Nickname +{ + /** + * Regex fragment for pulling an arbitrarily-formated nickname. + * + * Not guaranteed to be valid after normalization; run the string through + * Nickname::normalize() to get the canonical form, or Nickname::validate() + * if you just need to check if it's properly formatted. + * + * This and CANONICAL_FMT replace the old NICKNAME_FMT, but be aware + * that these should not be enclosed in []s. + */ + const DISPLAY_FMT = '[0-9a-zA-Z_]+'; + + /** + * Regex fragment for checking a canonical nickname. + * + * Any non-matching string is not a valid canonical/normalized nickname. + * Matching strings are valid and canonical form, but may still be + * unavailable for registration due to blacklisting et. + * + * Only the canonical forms should be stored as keys in the database; + * there are multiple possible denormalized forms for each valid + * canonical-form name. + * + * This and DISPLAY_FMT replace the old NICKNAME_FMT, but be aware + * that these should not be enclosed in []s. + */ + const CANONICAL_FMT = '[0-9a-z]{1,64}'; + + /** + * Maximum number of characters in a canonical-form nickname. + */ + const MAX_LEN = 64; + + /** + * Nice simple check of whether the given string is a valid input nickname, + * which can be normalized into an internally canonical form. + * + * Note that valid nicknames may be in use or reserved. + * + * @param string $str + * @return boolean + */ + public static function validate($str) + { + try { + self::normalize($str); + return true; + } catch (NicknameException $e) { + return false; + } + } + + /** + * Validate an input nickname string, and normalize it to its canonical form. + * The canonical form will be returned, or an exception thrown if invalid. + * + * @param string $str + * @return string Normalized canonical form of $str + * + * @throws NicknameException (base class) + * @throws NicknameInvalidException + * @throws NicknameEmptyException + * @throws NicknameTooLongException + */ + public static function normalize($str) + { + $str = trim($str); + $str = str_replace('_', '', $str); + $str = mb_strtolower($str); + + $len = mb_strlen($str); + if ($len < 1) { + throw new NicknameEmptyException(); + } else if ($len > self::MAX_LEN) { + throw new NicknameTooLongException(); + } + if (!self::isCanonical($str)) { + throw new NicknameInvalidException(); + } + + return $str; + } + + /** + * Is the given string a valid canonical nickname form? + * + * @param string $str + * @return boolean + */ + public static function isCanonical($str) + { + return preg_match('/^(?:' . self::CANONICAL_FMT . ')$/', $str); + } +} + +class NicknameException extends ClientException +{ + function __construct($msg=null, $code=400) + { + if ($msg === null) { + $msg = $this->defaultMessage(); + } + parent::__construct($msg, $code); + } + + /** + * Default localized message for this type of exception. + * @return string + */ + protected function defaultMessage() + { + return null; + } +} + +class NicknameInvalidException extends NicknameException { + /** + * Default localized message for this type of exception. + * @return string + */ + protected function defaultMessage() + { + // TRANS: Validation error in form for registration, profile and group settings, etc. + return _('Nickname must have only lowercase letters and numbers and no spaces.'); + } +} + +class NicknameEmptyException extends NicknameException +{ + /** + * Default localized message for this type of exception. + * @return string + */ + protected function defaultMessage() + { + // TRANS: Validation error in form for registration, profile and group settings, etc. + return _('Nickname cannot be empty.'); + } +} + +class NicknameTooLongException extends NicknameInvalidException +{ + /** + * Default localized message for this type of exception. + * @return string + */ + protected function defaultMessage() + { + // TRANS: Validation error in form for registration, profile and group settings, etc. + return sprintf(_m('Nickname cannot be more than %d character long.', + 'Nickname cannot be more than %d characters long.', + Nickname::MAX_LEN), + Nickname::MAX_LEN); + } +} |