/** * @param IFile $file * @param bool $foldersFirst * @return int A negative value if the current file should be placed before $file, * zero (0) if they are equals, a positive value otherwise. */ public function compareTo(IFile $file, $foldersFirst = false) { if ($foldersFirst) { $isDirThis = $this->isDirectory(); $isDirFile = $file->isDirectory(); if ($isDirThis && !$isDirFile) { return -1; } else { if ($isDirFile && !$isDirThis) { return 1; } } } $urlParts = $file->getURLComponents(); $urlParts['path'] = $file->getPathFromRoot(); //needed to resolve the path (if relative) $absolutePathFile = AdvancedPathLib::buildURL($urlParts); $urlParts = $this->getURLComponents(); $urlParts['path'] = $this->getPathFromRoot(); //needed to resolve the path (if relative) $absolutePathThis = AdvancedPathLib::buildURL($urlParts); return utf8_strcasecmp($absolutePathThis, $absolutePathFile); }
/** * UTF-8/LOCALE aware alternative to strcasecmp * A case insensitive string comparison * * @param string $str1 string 1 to compare * @param string $str2 string 2 to compare * @param mixed $locale The locale used by strcoll or false to use classical comparison * * @return integer < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal. * * @see http://www.php.net/strcasecmp * @see http://www.php.net/strcoll * @see http://www.php.net/setlocale * @since 11.1 */ public static function strcasecmp($str1, $str2, $locale = false) { if ($locale) { // Get current locale $locale0 = setlocale(LC_COLLATE, 0); if (!($locale = setlocale(LC_COLLATE, $locale))) { $locale = $locale0; } // See if we have successfully set locale to UTF-8 if (!stristr($locale, 'UTF-8') && stristr($locale, '_') && preg_match('~\\.(\\d+)$~', $locale, $m)) { $encoding = 'CP' . $m[1]; } elseif (stristr($locale, 'UTF-8')) { $encoding = 'UTF-8'; } else { $encoding = 'nonrecodable'; } // If we successfully set encoding it to utf-8 or encoding is sth weird don't recode if ($encoding == 'UTF-8' || $encoding == 'nonrecodable') { return strcoll(utf8_strtolower($str1), utf8_strtolower($str2)); } else { return strcoll(self::transcode(utf8_strtolower($str1), 'UTF-8', $encoding), self::transcode(utf8_strtolower($str2), 'UTF-8', $encoding)); } } else { return utf8_strcasecmp($str1, $str2); } }
/** compare two arrays by the title member (for sorting modules) * * @param array $a * @param array $b * $return int indicating the ordering of $a and $b like strcmp() */ function modulemanager_cmp($a, $b) { return utf8_strcasecmp($a['title'], $b['title']); }
function testLinefeed() { $strX = "iñtërnâtiôn\nàlizætiøn"; $strY = "IÑTËRNÂTIÔN\nÀLIZÆTIØN"; $this->assertTrue(utf8_strcasecmp($strX, $strY) == 0); }
/** perform actual update to version 2011051100 * * this is a substantial change in the database: we (finally) standardise on UTF-8 * including the database. Up until now we still only have a choice of exactly one * database driver: MySQL. Therefore the upgrade we do here can be more or less * MySQL-specific. (So much for database-independency). * * What needs to be done here? * * The most important task (in fact: the only task) is to change the collation (and * implicitly the default charset) to utf8_unicode_ci (4.1.x <= MySQL < 5.5.2) or * utf8mb4_unicode_ci (MySQL 5.5.3+). See {@link mysql.class.php} for more information * on these UTF-8 & MySQL issues. * * Strategy here is as follows. * <code> * for all 'our' tables (ie. "LIKE '{$prefix}%'" do * if table default charset is already utf8 (or utf8mb4) * continue; * for appropriate columns in this table * change column type to binary * change column type back to non-binary with correct charset and collation * if no trouble sofar * change default charset/collation of the table too * else * return failure * return success * </code> * * This way we _might_ be able to work our way through huge tables: if the PHP * max processing time kicks in, we can rerun the upgrade and start (again) with * the table we had in our hands the previous time. I don't expect this to happen, * but it still the way to do it IMHO. * * Note that I assume that I cannot change the default charset of the DATABASE * for the same reason the Installation Wizard expects the database to be ready * before installation commences. (I cannot be sure that I have the privilege to * execute 'ALTER DATABASE $db_name DEFAULT CHARSET utf8 COLLATE utf8_unicode_ci'). * * A useful reference for solving this problem of converting to utf8 can be found * here: http://codex.wordpress.org/Converting_Database_Character_Sets. * * In the case of W@S we do not have to deal with enum-fields because those are not used * at this time. In fact it boils down to changing char, varchar, text and longtext. * * Let goforit... * * @param object &$output collects the html output * @return bool TRUE on success, FALSE otherwise */ function update_core_2011051100(&$output) { global $CFG, $DB; // 0 -- get outta here when already upgraded $version = 2011051100; if ($CFG->version >= $version) { return TRUE; } // 1 -- can we do anything at all with upgrading to UTF-8 and all? $utf8_level = isset($DB->utf8_support) ? $DB->utf8_support : FALSE; if ($utf8_level === FALSE) { $msg = sprintf('%s(): cannot determine UTF-8 support in MySQL: utf8_level is not 0, 3 or 4', __FUNCTION__); logger($msg); $output->add_message(htmlspecialchars($msg)); $output->add_message(t('update_core_error', 'admin', array('{VERSION}' => strval($version)))); return FALSE; } elseif ($utf8_level == 0) { $db_version = mysql_get_server_info(); logger(sprintf('%s(): MySQL \'%s\' too old for UTF-8 update', __FUNCTION__, $db_version)); $params = array('{VERSION}' => $db_version); $output->add_message(t('warning_mysql_obsolete', 'i_install', $params)); return update_core_version($output, $version); } // 2A -- prepare to step through all tables and all columns changing collation (and implicit charset) $charset = $utf8_level == 3 ? 'utf8' : 'utf8mb4'; $collation = $charset . '_unicode_ci'; $pattern = str_replace(array('_', '%'), array('\\_', '\\%'), $DB->escape($DB->prefix)) . '%'; // e.g. 'was\_%' $sql = sprintf("SHOW TABLE STATUS LIKE '%s'", $pattern); if (($DBResult = $DB->query($sql)) === FALSE) { $msg = sprintf('%s(): cannot show tables: %d/%s', __FUNCTION__, $DB->errno, $DB->error); logger($msg); $output->add_message(htmlspecialchars($msg)); $output->add_message(t('update_core_error', 'admin', array('{VERSION}' => strval($version)))); return FALSE; } $tables = $DBResult->fetch_all_assoc('Name'); $DBResult->close(); $overtime = max(intval(ini_get('max_execution_time')), 30); // request this additional processing time after a table // 2B -- visit all tables foreach ($tables as $table) { if (isset($table['Collation']) && utf8_strcasecmp($table['Collation'], $collation) == 0) { logger(sprintf('%s(): table \'%s\' is already \'%s\'', __FUNCTION__, $table['Name'], $collation), WLOG_DEBUG); continue; // somehow someone already changed this table; carry on with the next one } // 3A -- prepare to step through all columns of this table $sql = sprintf('SHOW FULL COLUMNS FROM `%s`', $table['Name']); if (($DBResult = $DB->query($sql)) === FALSE) { $msg = sprintf('%s(): cannot show columns from %s: %d/%s', __FUNCTION__, $table['Name'], $DB->errno, $DB->error); logger($msg); $output->add_message(htmlspecialchars($msg)); $output->add_message(t('update_core_error', 'admin', array('{VERSION}' => strval($version)))); return FALSE; } $columns = $DBResult->fetch_all_assoc('Field'); // 3B -- visit all columns in this table foreach ($columns as $column) { if (isset($column['Collation'])) { if (is_null($column['Collation'])) { continue; // nothing to do; no collation to change } elseif (utf8_strcasecmp($column['Collation'], $collation) == 0) { logger(sprintf('%s(): column \'%s.%s\' is already converted to \'%s\'', __FUNCTION__, $table['Name'], $column['Field'], $collation), WLOG_DEBUG); continue; // somehow someone already changed this column; carry on with the next one } } else { continue; // this field has no collation whatsoever. Weird but we'll let it pass. } $sql1 = sprintf('ALTER TABLE `%s` CHANGE `%s` `%s` ', $table['Name'], $column['Field'], $column['Field']); $sql2 = $sql1; $vtype = explode("(", $column['Type']); // split 'varchar(n)' into components switch (strtolower($vtype[0])) { case 'varchar': $len = intval($vtype[1]); $sql1 .= sprintf('VARBINARY(%d)', $len); $sql2 .= sprintf('VARCHAR(%d)', $len); break; case 'char': $len = intval($vtype[1]); $sql1 .= sprintf('BINARY(%d)', $len); $sql2 .= sprintf('CHAR(%d)', $len); break; case 'text': $sql1 .= 'BLOB'; $sql2 .= 'TEXT'; break; case 'longtext': $sql1 .= 'LONGBLOB'; $sql2 .= 'LONGTEXT'; break; default: logger(sprintf('%s(): cannot handle \'%s.%s\' type \'%s\'; skipping', __FUNCTION__, $table['Name'], $column['Field'], $vtype[0]), WLOG_DEBUG); continue; break; } $sql2 .= sprintf(' CHARACTER SET %s COLLATE %s', $charset, $collation); $sql2 .= $column['Null'] == 'YES' ? ' NULL' : ' NOT NULL'; $sql2 .= is_null($column['Default']) ? '' : sprintf(' DEFAULT \'%s\'', $DB->escape($column['Default'])); $sql2 .= empty($column['Comment']) ? '' : sprintf(' COMMENT \'%s\'', $DB->escape($column['Comment'])); // Do back-and-forth in one go so we don't write to 'log_messages' while that table is being converted // We report any errors/do logging after we're back on track again $retval1 = $DB->exec($sql1); $errno1 = $DB->errno; $error1 = $DB->error; // text (latin1) -> binary $retval2 = $DB->exec($sql2); $errno2 = $DB->errno; $error2 = $DB->error; // binary -> text (utf8) if ($retval1 === FALSE || $retval2 === FALSE) { // oops, failure! gotta get out of this place! $msg = sprintf('%s(): cannot change \'%s.%s\': \'%s\': \'%d/%s\', \'%s\': \'%d/%s\'; bailing out', __FUNCTION__, $table['Name'], $column['Field'], $sql1, $errno1, $error1, $sql2, $errno2, $error2); logger($msg); $output->add_message(htmlspecialchars($msg)); $output->add_message(t('update_core_error', 'admin', array('{VERSION}' => strval($version)))); return FALSE; } else { logger(sprintf('%s(): alter column \'%s.%s\': changed collation from \'%s\' to \'%s\'', __FUNCTION__, $table['Name'], $column['Field'], $column['Collation'], $collation), WLOG_DEBUG); } } // Only if all columns went OK, we change the table; this is a quick and dirty sentinel to work // through a long converstion (at worst we do 1 table per round) Eventually the conversion will be complete... $sql = sprintf('ALTER TABLE `%s` DEFAULT CHARSET %s COLLATE %s', $table['Name'], $charset, $collation); if ($DB->exec($sql) === FALSE) { $msg = sprintf('%s(): cannot alter \'%s\' with \'%s\': %d/%s; bailing out', __FUNCTION__, $table['Name'], $sql, $DB->errno, $DB->error); logger($msg); $output->add_message(htmlspecialchars($msg)); $output->add_message(t('update_core_error', 'admin', array('{VERSION}' => strval($version)))); return FALSE; } else { logger(sprintf('%s(): alter table \'%s\': changed collation from \'%s\' to \'%s\'', __FUNCTION__, $table['Name'], $table['Collation'], $collation), WLOG_DEBUG); } @set_time_limit($overtime); // try to get additional processing time after every processed table } return update_core_version($output, $version); }
/** convert a fielddef array to a MySQL specific column definition * * this creates a MySQL specific column definition based on a generic field * description. The following keywords are recognised: * - name: the name of the field (required) * - type: the generic type of the field (see table below for supported types) (required) * - length: the size of a numeric field or the length of a textual field * - decimals: the number of decimals in real numbers (implies length) * - unsigned: used for numeric fields that don't need negative values (see note 5 below) * - notnull: if true, the field is not allowed/able to contain the NULL value * - default: the default value for the field * - enum_values: an array with allowable values for the enum field * - comment: a string that can be used to document the field definition * * The generic field types are mapped to actual MySQL data types via a lookup table. * Most types have a number of boolean flags which indicate how the field definition * must be interpreted. Entries with an empty type are considered special cases. * * - len = 1: look for a length parameter and use it if it is defined. * - dec = 1: look for a decimals parameter and use it if it is defined. Implies len. * - unsigned = 1: look for an unsigned parameter and use it if it is defined and true (see note 5 below). * - default = 1: look for a default parameter, and use it if it is defined. * - quote = 1: if a default is allowed AND defined, use single quotes + escaped string. * * Note 1: a 1 in the table means that the field type _allows_ the corresponding parameter, * and 0 means that this parameter is NOT allowed. It doesn't say anything about parameters * being _required_ (e.g. a varchar must have a length). It is the responsability of the * author of the field definition to provide all necessary parameters. * * Note 2: enum_values are not used at this time; an enum-field simply maps to a * varchar field and that's it. Adding the enum_values to a data definition does help * to document the purpose of the field. The reason for not (yet) implementing enums * in full is the issues associated with the translations in the UI. Furthermore, using * native enums in MySQL is a royal PITA. For now the application should know what it is * doing when using and updating enums in a table. * * Note 3: at this time it is not possible to set the default value of a text-type field * to the string consisting of the letters N, U, L and L: that caseinsensitive string is * always interpreted as the NULL-value in the database, ie. it yields "DEFAULT NULL" and * not "DEFAULT 'NULL'" or "DEFAULT 'Null'" or "DEFAULT 'null'". * * Note 4: even though comments may or may not be stored in the MySQL database, the corresponding * COMMENT-clauses are generated, if only for documentation/debugging purposes. These * clauses are correctly parsed by MySQL but they are subsequently discarded in old MySQL-versions. * * Note 5: * As of version 2009051401 (0.0.5) the parameter 'unsigned' is deprecated. * This is because even though MySQL implements an unsigned attribute for numeric fields, * other RDBMSs might not. Therefore we stay away from this MySQL-specific construct as * much as possible. Also, the translation from the 'serial' fieldrtype no longer adds * the unsigned attribute to the actual MySQL definition. * * @param array an array that describes a field in a generic way * @return bool|string FALSE on failure or a MySQL-specific string defining the column * @todo should we allow both int and integer? * @todo 'enum' type equivalent with varchar, enum_values[] array is not used at all, only as a form of documentation */ function column_definition($fielddef) { static $type_map = array('short' => array('type' => 'SMALLINT', 'len' => 1, 'dec' => 0, 'unsigned' => 1, 'default' => 1, 'quote' => 0), 'int' => array('type' => 'INT', 'len' => 1, 'dec' => 0, 'unsigned' => 1, 'default' => 1, 'quote' => 0), 'long' => array('type' => 'BIGINT', 'len' => 1, 'dec' => 0, 'unsigned' => 1, 'default' => 1, 'quote' => 0), 'float' => array('type' => 'FLOAT', 'len' => 1, 'dec' => 1, 'unsigned' => 1, 'default' => 1, 'quote' => 0), 'double' => array('type' => 'DOUBLE', 'len' => 1, 'dec' => 1, 'unsigned' => 1, 'default' => 1, 'quote' => 0), 'decimal' => array('type' => 'DECIMAL', 'len' => 1, 'dec' => 1, 'unsigned' => 1, 'default' => 1, 'quote' => 0), 'number' => array('type' => 'DECIMAL', 'len' => 1, 'dec' => 1, 'unsigned' => 1, 'default' => 1, 'quote' => 0), 'varchar' => array('type' => 'VARCHAR', 'len' => 1, 'dec' => 0, 'unsigned' => 0, 'default' => 1, 'quote' => 1), 'enum' => array('type' => 'VARCHAR', 'len' => 1, 'dec' => 0, 'unsigned' => 0, 'default' => 1, 'quote' => 1), 'char' => array('type' => 'CHAR', 'len' => 1, 'dec' => 0, 'unsigned' => 0, 'default' => 1, 'quote' => 1), 'text' => array('type' => 'TEXT', 'len' => 0, 'dec' => 0, 'unsigned' => 0, 'default' => 0, 'quote' => 0), 'longtext' => array('type' => 'LONGTEXT', 'len' => 0, 'dec' => 0, 'unsigned' => 0, 'default' => 0, 'quote' => 0), 'blob' => array('type' => 'BLOB', 'len' => 0, 'dec' => 0, 'unsigned' => 0, 'default' => 0, 'quote' => 0), 'longblob' => array('type' => 'LONGBLOB', 'len' => 0, 'dec' => 0, 'unsigned' => 0, 'default' => 0, 'quote' => 0), 'date' => array('type' => 'DATE', 'len' => 0, 'dec' => 0, 'unsigned' => 0, 'default' => 1, 'quote' => 1), 'time' => array('type' => 'TIME', 'len' => 0, 'dec' => 0, 'unsigned' => 0, 'default' => 1, 'quote' => 1), 'datetime' => array('type' => 'DATETIME', 'len' => 0, 'dec' => 0, 'unsigned' => 0, 'default' => 1, 'quote' => 1), 'timestamp' => array('type' => 'TIMESTAMP', 'len' => 0, 'dec' => 0, 'unsigned' => 0, 'default' => 1, 'quote' => 1), 'serial' => array('type' => ''), 'bool' => array('type' => '')); if (!isset($type_map[$fielddef['type']])) { trigger_error('internal error: unknown field type \'' . $fielddef['type'] . '\'', E_USER_ERROR); return FALSE; } $column_def = $fielddef['name'] . ' '; // collect the output, start with the field's name $field = $type_map[$fielddef['type']]; if (empty($field['type'])) { // special case, e.g. bool or serial switch ($fielddef['type']) { case 'serial': $column_def .= 'INT NOT NULL AUTO_INCREMENT UNIQUE'; // Note: no implied PRIMARY KEY break; case 'bool': $column_def .= 'TINYINT(1)'; if (isset($fielddef['notnull']) && $fielddef['notnull']) { $column_def .= " NOT NULL"; } if (isset($fielddef['default'])) { $column_def .= ' DEFAULT '; if (is_null($fielddef['default']) || strcasecmp($fielddef['default'], 'null') == 0) { $column_def .= 'NULL'; } else { $column_def .= $fielddef['default'] ? SQL_TRUE : SQL_FALSE; } } break; default: trigger_error('internal error: \'' . $fielddef['name'] . '\' is no special case', E_USER_ERROR); return FALSE; break; } } else { $column_def .= $field['type']; /* if this field is allowed to have a length, maybe pickup the specified length and optional decimals */ if ($field['len']) { if (isset($fielddef['length'])) { if ($field['dec'] && isset($fielddef['decimals'])) { $column_def .= '(' . $fielddef['length'] . ',' . $fielddef['decimals'] . ')'; } else { $column_def .= '(' . $fielddef['length'] . ')'; } } } if ($field['unsigned']) { // See note 5 above: 'unsigned' is deprecated. if (isset($fielddef['unsigned']) && $fielddef['unsigned']) { $column_def .= " UNSIGNED"; } } if (isset($fielddef['notnull']) && $fielddef['notnull']) { $column_def .= " NOT NULL"; } if ($field['default']) { if (isset($fielddef['default'])) { if (utf8_strcasecmp($fielddef['default'], 'null') == 0) { // see the note above $column_def .= ' DEFAULT NULL'; } elseif ($field['quote']) { $column_def .= ' DEFAULT \'' . $this->escape($fielddef['default']) . '\''; } else { $column_def .= ' DEFAULT ' . $fielddef['default']; } } } } if (isset($fielddef['comment'])) { $column_def .= ' COMMENT \'' . $this->escape($fielddef['comment']) . '\''; } return $column_def; }
public function check_username($username, $errors, $exclude_id = null) { // Include UTF-8 function require_once ForumEnv::get('FEATHER_ROOT') . 'featherbb/Helpers/utf8/strcasecmp.php'; translate('register'); translate('prof_reg'); // Convert multiple whitespace characters into one (to prevent people from registering with indistinguishable usernames) $username = preg_replace('%\\s+%s', ' ', $username); // Validate username if (Utils::strlen($username) < 2) { $errors[] = __('Username too short'); } elseif (Utils::strlen($username) > 25) { // This usually doesn't happen since the form element only accepts 25 characters $errors[] = __('Username too long'); } elseif (!strcasecmp($username, 'Guest') || !utf8_strcasecmp($username, __('Guest'))) { $errors[] = __('Username guest'); } elseif (filter_var($username, FILTER_VALIDATE_IP)) { $errors[] = __('Username IP'); } elseif ((strpos($username, '[') !== false || strpos($username, ']') !== false) && strpos($username, '\'') !== false && strpos($username, '"') !== false) { $errors[] = __('Username reserved chars'); } elseif (preg_match('%(?:\\[/?(?:b|u|s|ins|del|em|i|h|colou?r|quote|code|img|url|email|list|\\*|topic|post|forum|user)\\]|\\[(?:img|url|quote|list)=)%i', $username)) { $errors[] = __('Username BBCode'); } // Check username for any censored words if (ForumSettings::get('o_censoring') == '1' && Utils::censor($username) != $username) { $errors[] = __('Username censor'); } // Check that the username (or a too similar username) is not already registered $query = !is_null($exclude_id) ? ' AND id!=' . $exclude_id : ''; $result = DB::for_table('online')->raw_query('SELECT username FROM ' . ForumSettings::get('db_prefix') . 'users WHERE (UPPER(username)=UPPER(:username1) OR UPPER(username)=UPPER(:username2)) AND id>1' . $query, array(':username1' => $username, ':username2' => Utils::ucp_preg_replace('%[^\\p{L}\\p{N}]%u', '', $username)))->find_one(); if ($result) { $busy = $result['username']; $errors[] = __('Username dupe 1') . ' ' . Utils::escape($busy) . '. ' . __('Username dupe 2'); } // Check username for any banned usernames foreach (Container::get('bans') as $cur_ban) { if ($cur_ban['username'] != '' && utf8_strtolower($username) == utf8_strtolower($cur_ban['username'])) { $errors[] = __('Banned username'); break; } } return $errors; }
/** * UTF-8 aware alternative to strcasecmp * A case insensivite string comparison * * @static * @access public * @param string string 1 to compare * @param string string 2 to compare * @return int < 0 if str1 is less than str2; > 0 if str1 is greater than str2, and 0 if they are equal. * @see http://www.php.net/strcasecmp */ public static function strcasecmp($str1, $str2) { jimport('phputf8.strcasecmp'); return utf8_strcasecmp($str1, $str2); }
function check_username($username, $exclude_id = null) { global $db, $pun_config, $errors, $lang_prof_reg, $lang_register, $lang_common, $pun_bans; // Include UTF-8 function require_once PUN_ROOT . 'include/utf8/strcasecmp.php'; // Convert multiple whitespace characters into one (to prevent people from registering with indistinguishable usernames) $username = preg_replace('%\\s+%s', ' ', $username); // Validate username if (pun_strlen($username) < 2) { $errors[] = $lang_prof_reg['Username too short']; } else { if (pun_strlen($username) > 25) { // This usually doesn't happen since the form element only accepts 25 characters $errors[] = $lang_prof_reg['Username too long']; } else { if (!strcasecmp($username, 'Guest') || !utf8_strcasecmp($username, $lang_common['Guest'])) { $errors[] = $lang_prof_reg['Username guest']; } else { if (preg_match('%[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}%', $username) || preg_match('%((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b)\\.){3}(\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b)\\.){3}(\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b)\\.){3}(\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))%', $username)) { $errors[] = $lang_prof_reg['Username IP']; } else { if ((strpos($username, '[') !== false || strpos($username, ']') !== false) && strpos($username, '\'') !== false && strpos($username, '"') !== false) { $errors[] = $lang_prof_reg['Username reserved chars']; } else { if (preg_match('%(?:\\[/?(?:b|u|s|ins|del|em|i|h|colou?r|quote|code|img|url|email|list|\\*|topic|post|forum|user)\\]|\\[(?:img|url|quote|list)=)%i', $username)) { $errors[] = $lang_prof_reg['Username BBCode']; } } } } } } // Check username for any censored words if ($pun_config['o_censoring'] == '1' && censor_words($username) != $username) { $errors[] = $lang_register['Username censor']; } // Check that the username (or a too similar username) is not already registered $query = !is_null($exclude_id) ? ' AND id!=' . $exclude_id : ''; $result = $db->query('SELECT username FROM ' . $db->prefix . 'users WHERE (UPPER(username)=UPPER(\'' . $db->escape($username) . '\') OR UPPER(username)=UPPER(\'' . $db->escape(ucp_preg_replace('%[^\\p{L}\\p{N}]%u', '', $username)) . '\')) AND id>1' . $query) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error()); if ($db->num_rows($result)) { $busy = $db->result($result); $errors[] = $lang_register['Username dupe 1'] . ' ' . pun_htmlspecialchars($busy) . '. ' . $lang_register['Username dupe 2']; } // Check username for any banned usernames foreach ($pun_bans as $cur_ban) { if ($cur_ban['username'] != '' && utf8_strtolower($username) == utf8_strtolower($cur_ban['username'])) { $errors[] = $lang_prof_reg['Banned username']; break; } } }
function check_username($username, $exclude_id = null) { global $db, $luna_config, $errors, $luna_bans; // Include UTF-8 function require_once FORUM_ROOT . 'include/utf8/strcasecmp.php'; // Convert multiple whitespace characters into one (to prevent people from registering with indistinguishable usernames) $username = preg_replace('%\\s+%s', ' ', $username); // Validate username if (luna_strlen($username) < 2) { $errors[] = __('Usernames must be at least 2 characters long. Please choose another (longer) username.', 'luna'); } elseif (luna_strlen($username) > 25) { // This usually doesn't happen since the form element only accepts 25 characters $errors[] = __('Usernames must not be more than 25 characters long. Please choose another (shorter) username.', 'luna'); } elseif (!strcasecmp($username, 'Guest') || !utf8_strcasecmp($username, __('Guest', 'luna'))) { $errors[] = __('The username guest is reserved. Please choose another username.', 'luna'); } elseif (preg_match('%[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}%', $username) || preg_match('%((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b)\\.){3}(\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b)\\.){3}(\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b)\\.){3}(\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))%', $username)) { $errors[] = __('Usernames may not be in the form of an IP address. Please choose another username.', 'luna'); } elseif ((strpos($username, '[') !== false || strpos($username, ']') !== false) && strpos($username, '\'') !== false && strpos($username, '"') !== false) { $errors[] = __('Usernames may not contain all the characters \', " and [ or ] at once. Please choose another username.', 'luna'); } elseif (preg_match('%(?:\\[/?(?:b|u|s|ins|del|em|i|h|colou?r|quote|code|img|url|email|list|\\*|topic|post|forum|user)\\]|\\[(?:img|url|quote|list)=)%i', $username)) { $errors[] = __('Usernames may not contain any of the text formatting tags (BBCode) that the forum uses. Please choose another username.', 'luna'); } // Check username for any censored words if ($luna_config['o_censoring'] == '1' && censor_words($username) != $username) { $errors[] = __('The username you entered contains one or more censored words. Please choose a different username.', 'luna'); } // Check that the username (or a too similar username) is not already registered $query = !is_null($exclude_id) ? ' AND id!=' . $exclude_id : ''; $result = $db->query('SELECT username FROM ' . $db->prefix . 'users WHERE (UPPER(username)=UPPER(\'' . $db->escape($username) . '\') OR UPPER(username)=UPPER(\'' . $db->escape(ucp_preg_replace('%[^\\p{L}\\p{N}]%u', '', $username)) . '\')) AND id>1' . $query) or error('Unable to fetch user info', __FILE__, __LINE__, $db->error()); if ($db->num_rows($result)) { $busy = $db->result($result); $errors[] = __('Someone is already registered with the username', 'luna') . ' ' . luna_htmlspecialchars($busy) . '. ' . __('The username you entered is too similar. The username must differ from that by at least one alphanumerical character (a-z or 0-9). Please choose a different username.', 'luna'); } // Check username for any banned usernames foreach ($luna_bans as $cur_ban) { if ($cur_ban['username'] != '' && utf8_strtolower($username) == utf8_strtolower($cur_ban['username'])) { $errors[] = __('The username you entered is banned in this forum. Please choose another username.', 'luna'); break; } } }
public static function strcasecmp($str1, $str2, $locale = false) { if ($locale) { $locale0 = setlocale(LC_COLLATE, 0); if (!($locale = setlocale(LC_COLLATE, $locale))) { $locale = $locale0; } if (!stristr($locale, 'UTF-8') && stristr($locale, '_') && preg_match('~\\.(\\d+)$~', $locale, $m)) { $encoding = 'CP' . $m[1]; } elseif (stristr($locale, 'UTF-8')) { $encoding = 'UTF-8'; } else { $encoding = 'nonrecodable'; } if ($encoding == 'UTF-8' || $encoding == 'nonrecodable') { return strcoll(utf8_strtolower($str1), utf8_strtolower($str2)); } else { return strcoll(self::transcode(utf8_strtolower($str1), 'UTF-8', $encoding), self::transcode(utf8_strtolower($str2), 'UTF-8', $encoding)); } } else { return utf8_strcasecmp($str1, $str2); } }
/** check if the user accepts the licences * * This is the companion routine for {@link show_dialog_license()}. * It checks whether the user dutyfully typed 'I agree'. * Note that we check caseINsensitive, so 'i agree' is acceptable, as is 'I aGrEe'. * Also note that we accept non-ascii UTF-8, say "J'accept'ee" or "J'ACCEPT'EE" * which has an e-acute. Case folding to lowercase accepts all those variants. * * @return bool TRUE on success, otherwise FALSE + error information in $this->messages array */ function check_license() { $iagree = $this->t('dialog_license_i_agree'); $license = trim($this->get_utf8_parameter_string($_POST, 'license')); $_SESSION['INSTALL']['license_accepted'] = utf8_strcasecmp(trim($iagree), $license) == 0 ? TRUE : FALSE; $retval = $_SESSION['INSTALL']['license_accepted']; if ($retval != TRUE) { $a = array('{IAGREE}' => $iagree); $this->messages[] = $this->t('dialog_license_you_must_accept', $a); } return $retval; }
function check_username($username, $exclude_id = null) { global $db, $panther_config, $errors, $lang_prof_reg, $lang_register, $lang_common, $panther_bans; // Include UTF-8 function require_once PANTHER_ROOT . 'include/utf8/strcasecmp.php'; // Convert multiple whitespace characters into one (to prevent people from registering with indistinguishable usernames) $username = preg_replace('%\\s+%s', ' ', $username); // Validate username if (panther_strlen($username) < 2) { $errors[] = $lang_prof_reg['Username too short']; } else { if (panther_strlen($username) > 25) { // This usually doesn't happen since the form element only accepts 25 characters $errors[] = $lang_prof_reg['Username too long']; } else { if (!strcasecmp($username, 'Guest') || !utf8_strcasecmp($username, $lang_common['Guest'])) { $errors[] = $lang_prof_reg['Username guest']; } else { if (preg_match('%[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}%', $username) || preg_match('%((([0-9A-Fa-f]{1,4}:){7}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}:[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){5}:([0-9A-Fa-f]{1,4}:)?[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){4}:([0-9A-Fa-f]{1,4}:){0,2}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){3}:([0-9A-Fa-f]{1,4}:){0,3}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){2}:([0-9A-Fa-f]{1,4}:){0,4}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){6}((\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b)\\.){3}(\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b))|(([0-9A-Fa-f]{1,4}:){0,5}:((\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b)\\.){3}(\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b))|(::([0-9A-Fa-f]{1,4}:){0,5}((\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b)\\.){3}(\\b((25[0-5])|(1\\d{2})|(2[0-4]\\d)|(\\d{1,2}))\\b))|([0-9A-Fa-f]{1,4}::([0-9A-Fa-f]{1,4}:){0,5}[0-9A-Fa-f]{1,4})|(::([0-9A-Fa-f]{1,4}:){0,6}[0-9A-Fa-f]{1,4})|(([0-9A-Fa-f]{1,4}:){1,7}:))%', $username)) { $errors[] = $lang_prof_reg['Username IP']; } else { if ((strpos($username, '[') !== false || strpos($username, ']') !== false) && strpos($username, '\'') !== false && strpos($username, '"') !== false) { $errors[] = $lang_prof_reg['Username reserved chars']; } else { if (preg_match('%(?:\\[/?(?:b|u|s|ins|del|em|i|h|colou?r|quote|code|img|url|email|list|\\*|topic|post|forum|user)\\]|\\[(?:img|url|quote|list)=)%i', $username)) { $errors[] = $lang_prof_reg['Username BBCode']; } } } } } } // Check username for any censored words if ($panther_config['o_censoring'] == '1' && censor_words($username) != $username) { $errors[] = $lang_register['Username censor']; } $where_cond = '(UPPER(username)=UPPER(:username) OR UPPER(username)=UPPER(:username2)) AND id>1'; $data = array(':username' => $username, ':username2' => ucp_preg_replace('%[^\\p{L}\\p{N}]%u', '', $username)); // Check that the username (or a too similar username) is not already registered if (!is_null($exclude_id)) { $where_cond .= ' AND id!=:id'; $data[':id'] = $exclude_id; } $ps = $db->select('users', 'username', $data, $where_cond); if ($ps->rowCount()) { $busy = $ps->fetchColumn(); $errors[] = $lang_register['Username dupe 1'] . ' ' . $busy . '. ' . $lang_register['Username dupe 2']; } // Check username for any banned usernames foreach ($panther_bans as $cur_ban) { if ($cur_ban['username'] != '' && utf8_strtolower($username) == utf8_strtolower($cur_ban['username'])) { $errors[] = $lang_prof_reg['Banned username']; break; } } }