diff options
Diffstat (limited to 'phpBB/includes')
115 files changed, 0 insertions, 70461 deletions
diff --git a/phpBB/includes/acm/acm_apc.php b/phpBB/includes/acm/acm_apc.php deleted file mode 100644 index fa92de2b50..0000000000 --- a/phpBB/includes/acm/acm_apc.php +++ /dev/null @@ -1,388 +0,0 @@ -<?php -/** -* -* @package acm -* @version $Id$ -* @copyright (c) 2009 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* ACM File Based Caching -* @package acm -*/ -class acm -{ - var $vars = array(); - var $is_modified = false; - - var $sql_rowset = array(); - var $sql_row_pointer = array(); - var $cache_dir = ''; - - /** - * Set cache path - */ - function acm() - { - $this->cache_dir = $phpbb_root_path . 'cache/'; - } - - /** - * Load global cache - */ - function load() - { - // grab the global cache - $this->vars = apc_fetch('global'); - - if ($this->vars !== false) - { - return true; - } - - return false; - } - - /** - * Unload cache object - */ - function unload() - { - $this->save(); - unset($this->vars); - unset($this->sql_rowset); - unset($this->sql_row_pointer); - - $this->vars = array(); - $this->sql_rowset = array(); - $this->sql_row_pointer = array(); - } - - /** - * Save modified objects - */ - function save() - { - if (!$this->is_modified) - { - return; - } - - apc_store('global', $this->vars, 31536000); - - $this->is_modified = false; - } - - /** - * Tidy cache - */ - function tidy() - { - // cache has auto GC, no need to have any code here :) - - set_config('cache_last_gc', time(), true); - } - - /** - * Get saved cache object - */ - function get($var_name) - { - if ($var_name[0] == '_') - { - if (!$this->_exists($var_name)) - { - return false; - } - - return apc_fetch($var_name); - } - else - { - return ($this->_exists($var_name)) ? $this->vars[$var_name] : false; - } - } - - /** - * Put data into cache - */ - function put($var_name, $var, $ttl = 31536000) - { - if ($var_name[0] == '_') - { - apc_store($var_name, $var, $ttl); - } - else - { - $this->vars[$var_name] = $var; - $this->is_modified = true; - } - } - - /** - * Purge cache data - */ - function purge() - { - // Purge all phpbb cache files - $dir = @opendir($this->cache_dir); - - if (!$dir) - { - return; - } - - while (($entry = readdir($dir)) !== false) - { - if (strpos($entry, 'sql_') !== 0 && strpos($entry, 'data_') !== 0 && strpos($entry, 'ctpl_') !== 0 && strpos($entry, 'tpl_') !== 0) - { - continue; - } - - $this->remove_file($this->cache_dir . $entry); - } - closedir($dir); - - apc_clear_cache('user'); - - unset($this->vars); - unset($this->sql_rowset); - unset($this->sql_row_pointer); - - $this->vars = array(); - $this->sql_rowset = array(); - $this->sql_row_pointer = array(); - - $this->is_modified = false; - } - - /** - * Destroy cache data - */ - function destroy($var_name, $table = '') - { - if ($var_name == 'sql' && !empty($table)) - { - if (!is_array($table)) - { - $table = array($table); - } - - foreach ($table as $table_name) - { - // gives us the md5s that we want - $temp = apc_fetch('sql_' . $table_name); - - if ($temp === false) - { - continue; - } - - // delete each query ref - foreach ($temp as $md5_id => $void) - { - apc_delete('sql_' . $md5_id); - } - - // delete the table ref - apc_delete('sql_' . $table_name); - } - - return; - } - - if (!$this->_exists($var_name)) - { - return; - } - - if ($var_name[0] == '_') - { - apc_delete($var_name); - } - else if (isset($this->vars[$var_name])) - { - $this->is_modified = true; - unset($this->vars[$var_name]); - - // We save here to let the following cache hits succeed - $this->save(); - } - } - - /** - * Check if a given cache entry exist - */ - function _exists($var_name) - { - if ($var_name[0] == '_') - { - return true; - } - else - { - if (!sizeof($this->vars)) - { - $this->load(); - } - - return isset($this->vars[$var_name]); - } - } - - /** - * Load cached sql query - */ - function sql_load($query) - { - // Remove extra spaces and tabs - $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); - $query_id = sizeof($this->sql_rowset); - - $temp = apc_fetch('sql_' . md5($query)); - - if ($temp === false) - { - return false; - } - - $this->sql_rowset[$query_id] = $temp; - $this->sql_row_pointer[$query_id] = 0; - - return $query_id; - } - - /** - * Save sql query - */ - function sql_save($query, &$query_result, $ttl) - { - // Remove extra spaces and tabs - $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); - - // determine which tables this query belongs to - preg_match('/FROM \\(?(\\w+(?: \\w+)?(?:, ?\\w+(?: \\w+)?)*)\\)?/', $query, $regs); - $tables = array_map('trim', explode(',', $regs[1])); - - foreach ($tables as $table_name) - { - if (($pos = strpos($table_name, ' ')) !== false) - { - $table_name = substr($table_name, 0, $pos); - } - - $temp = apc_fetch('sql_' . $table_name); - if ($temp === false) - { - $temp = array(); - } - $temp[md5($query)] = true; - apc_store('sql_' . $table_name, $temp, $ttl); - } - - // store them in the right place - $query_id = sizeof($this->sql_rowset); - $this->sql_rowset[$query_id] = array(); - $this->sql_row_pointer[$query_id] = 0; - - while ($row = phpbb::$db->sql_fetchrow($query_result)) - { - $this->sql_rowset[$query_id][] = $row; - } - phpbb::$db->sql_freeresult($query_result); - - apc_store('sql_' . md5($query), $this->sql_rowset[$query_id], $ttl); - - $query_result = $query_id; - } - - /** - * Ceck if a given sql query exist in cache - */ - function sql_exists($query_id) - { - return isset($this->sql_rowset[$query_id]); - } - - /** - * Fetch row from cache (database) - */ - function sql_fetchrow($query_id) - { - if ($this->sql_row_pointer[$query_id] < sizeof($this->sql_rowset[$query_id])) - { - return $this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]++]; - } - - return false; - } - - /** - * Fetch a field from the current row of a cached database result (database) - */ - function sql_fetchfield($query_id, $field) - { - if ($this->sql_row_pointer[$query_id] < sizeof($this->sql_rowset[$query_id])) - { - return (isset($this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]][$field])) ? $this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]][$field] : false; - } - - return false; - } - - /** - * Seek a specific row in an a cached database result (database) - */ - function sql_rowseek($rownum, $query_id) - { - if ($rownum >= sizeof($this->sql_rowset[$query_id])) - { - return false; - } - - $this->sql_row_pointer[$query_id] = $rownum; - return true; - } - - /** - * Free memory used for a cached database result (database) - */ - function sql_freeresult($query_id) - { - if (!isset($this->sql_rowset[$query_id])) - { - return false; - } - - unset($this->sql_rowset[$query_id]); - unset($this->sql_row_pointer[$query_id]); - - return true; - } - - /** - * Removes/unlinks file - */ - function remove_file($filename, $check = false) - { - if ($check && !@is_writable($this->cache_dir)) - { - // E_USER_ERROR - not using language entry - intended. - trigger_error('Unable to remove files within ' . $this->cache_dir . '. Please check directory permissions.', E_USER_ERROR); - } - - return @unlink($filename); - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/acm/acm_eaccelerator.php b/phpBB/includes/acm/acm_eaccelerator.php deleted file mode 100644 index c6d83da049..0000000000 --- a/phpBB/includes/acm/acm_eaccelerator.php +++ /dev/null @@ -1,352 +0,0 @@ -<?php -/** -* -* @package acm -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* ACM Memcache Based Caching -* @package acm -*/ -class acm -{ - var $vars = array(); - var $is_modified = false; - - var $sql_rowset = array(); - var $sql_row_pointer = array(); - var $cache_dir = ''; - - /** - * Set cache path - */ - function acm() - { - $this->cache_dir = $phpbb_root_path . 'cache/'; - } - - /** - * Load global cache - */ - function load() - { - // grab the global cache - $temp = eaccelerator_get('global'); - - if ($temp !== null) - { - $this->vars = $temp; - } - else - { - return false; - } - - return true; - } - - /** - * Unload cache object - */ - function unload() - { - $this->save(); - unset($this->vars); - unset($this->sql_rowset); - unset($this->sql_row_pointer); - } - - /** - * Save modified objects - */ - function save() - { - if (!$this->is_modified) - { - return; - } - - eaccelerator_put('global', $this->vars, 31536000); - - $this->is_modified = false; - } - - /** - * Tidy cache - */ - function tidy() - { - eaccelerator_gc(); - - set_config('cache_last_gc', time(), true); - } - - /** - * Get saved cache object - */ - function get($var_name) - { - if ($var_name[0] == '_') - { - $temp = eaccelerator_get($var_name); - - if ($temp !== null) - { - return $temp; - } - else - { - return false; - } - } - else - { - if (!sizeof($this->vars)) - { - $this->load(); - } - return (isset($this->vars[$var_name])) ? $this->vars[$var_name] : false; - } - } - - /** - * Put data into cache - */ - function put($var_name, $var, $ttl = 31536000) - { - if ($var_name[0] == '_') - { - eaccelerator_put($var_name, $var, $ttl); - } - else - { - $this->vars[$var_name] = $var; - $this->is_modified = true; - } - } - - /** - * Purge cache data - */ - function purge() - { - // Purge all phpbb cache files - $dir = @opendir($this->cache_dir); - - if (!$dir) - { - return; - } - - while (($entry = readdir($dir)) !== false) - { - if (strpos($entry, 'sql_') !== 0 && strpos($entry, 'data_') !== 0 && strpos($entry, 'ctpl_') !== 0 && strpos($entry, 'tpl_') !== 0) - { - continue; - } - - @unlink($this->cache_dir . $entry); - } - closedir($dir); - - foreach (eaccelerator_list_keys() as $var) - { - eaccelerator_rm(substr($var['name'], 1)); - } - - unset($this->vars); - unset($this->sql_rowset); - unset($this->sql_row_pointer); - - $this->is_modified = false; - } - - /** - * Destroy cache data - */ - function destroy($var_name, $table = '') - { - if ($var_name == 'sql' && !empty($table)) - { - if (!is_array($table)) - { - $table = array($table); - } - - foreach ($table as $table_name) - { - // gives us the md5s that we want - eaccelerator_lock('sql_' . $table_name); - $temp = eaccelerator_get('sql_' . $table_name); - if ($temp === null) - { - continue; - } - - // delete each query ref - foreach ($temp as $md5_id => $void) - { - eaccelerator_lock('sql_' . $md5_id); - eaccelerator_rm('sql_' . $md5_id); - eaccelerator_unlock('sql_' . $md5_id); - } - - // delete the table ref - eaccelerator_rm('sql_' . $table_name); - eaccelerator_unlock('sql_' . $table_name); - } - - return; - } - - if ($var_name[0] == '_') - { - eaccelerator_rm($var_name); - } - else if (isset($this->vars[$var_name])) - { - $this->is_modified = true; - unset($this->vars[$var_name]); - - // We save here to let the following cache hits succeed - $this->save(); - } - } - - /** - * Load cached sql query - */ - function sql_load($query) - { - // Remove extra spaces and tabs - $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); - $query_id = sizeof($this->sql_rowset); - - $temp = eaccelerator_get('sql_' . md5($query)); - - if ($temp === null) - { - return false; - } - - $this->sql_rowset[$query_id] = $temp; - - $this->sql_row_pointer[$query_id] = 0; - - return $query_id; - } - - /** - * Save sql query - */ - function sql_save($query, &$query_result, $ttl) - { - // Remove extra spaces and tabs - $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); - - // determine which tables this query belongs to - preg_match('/FROM \\(?(\\w+(?: \\w+)?(?:, ?\\w+(?: \\w+)?)*)\\)?/', $query, $regs); - $tables = array_map('trim', explode(',', $regs[1])); - - foreach ($tables as $table_name) - { - if (($pos = strpos($table_name, ' ')) !== false) - { - $table_name = substr($table_name, 0, $pos); - } - - $temp = eaccelerator_get('sql_' . $table_name); - if ($temp === null) - { - $temp = array(); - } - $temp[md5($query)] = true; - eaccelerator_put('sql_' . $table_name, $temp, $ttl); - } - - // store them in the right place - $query_id = sizeof($this->sql_rowset); - $this->sql_rowset[$query_id] = array(); - $this->sql_row_pointer[$query_id] = 0; - - while ($row = phpbb::$db->sql_fetchrow($query_result)) - { - $this->sql_rowset[$query_id][] = $row; - } - phpbb::$db->sql_freeresult($query_result); - - eaccelerator_put('sql_' . md5($query), $this->sql_rowset[$query_id], $ttl); - - $query_result = $query_id; - } - - /** - * Ceck if a given sql query exist in cache - */ - function sql_exists($query_id) - { - return isset($this->sql_rowset[$query_id]); - } - - /** - * Fetch row from cache (database) - */ - function sql_fetchrow($query_id) - { - if ($this->sql_row_pointer[$query_id] < sizeof($this->sql_rowset[$query_id])) - { - return $this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]++]; - } - - return false; - } - - /** - * Fetch a field from the current row of a cached database result (database) - */ - function sql_fetchfield($query_id, $field) - { - if ($this->sql_row_pointer[$query_id] < sizeof($this->sql_rowset[$query_id])) - { - return (isset($this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]][$field])) ? $this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]][$field] : false; - } - - return false; - } - - /** - * Seek a specific row in an a cached database result (database) - */ - function sql_rowseek($rownum, $query_id) - { - if ($rownum >= sizeof($this->sql_rowset[$query_id])) - { - return false; - } - - $this->sql_row_pointer[$query_id] = $rownum; - return true; - } - - /** - * Free memory used for a cached database result (database) - */ - function sql_freeresult($query_id) - { - if (!isset($this->sql_rowset[$query_id])) - { - return false; - } - - unset($this->sql_rowset[$query_id]); - unset($this->sql_row_pointer[$query_id]); - - return true; - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/acm/acm_file.php b/phpBB/includes/acm/acm_file.php deleted file mode 100644 index e073230d49..0000000000 --- a/phpBB/includes/acm/acm_file.php +++ /dev/null @@ -1,344 +0,0 @@ -<?php -/** -* -* @package acm -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Define file-based cache. -* @package acm -*/ -class phpbb_acm_file extends phpbb_acm_abstract -{ - /** - * @var string The cache directory to use - */ - public $cache_dir = ''; - - /** - * @var array|bool The cache types this class supports. True indicates support for all types. - */ - public $supported = true; - - /** - * Set cache directory - * - * @param string $cache_prefix The cache prefix the instance is responsible for - * @access public - */ - public function __construct($cache_prefix) - { - $this->cache_dir = PHPBB_ROOT_PATH . 'cache/'; - $this->cache_prefix = $cache_prefix; - } - - /** - * {@link phpbb_acm_abstract::get() get()} - */ - public function get($var_name) - { - if ($var_name[0] === '#') - { - $var_name = substr($var_name, 1); - return $this->get_global($var_name); - } - - if (!$this->exists($var_name)) - { - return false; - } - - @include($this->cache_dir . $this->cache_prefix . '_' . $var_name . '.' . PHP_EXT); - - // If no data there, then the file expired... - if ($expired) - { - // Destroy - $this->destroy($var_name); - return false; - } - - return $data; - } - - /** - * {@link phpbb_acm_abstract::put() put()} - */ - public function put($var_name, $data, $ttl = 31536000) - { - if ($var_name[0] === '#') - { - $var_name = substr($var_name, 1); - return $this->put_global($var_name, $data, $ttl); - } - - $filename = $this->cache_dir . $this->cache_prefix . '_' . $var_name . '.' . PHP_EXT; - - if ($fp = @fopen($filename, 'wb')) - { - @flock($fp, LOCK_EX); - fwrite($fp, "<?php\nif (!defined('IN_PHPBB')) exit;\n\$expired = (time() > " . (time() + $ttl) . ") ? true : false;\nif (\$expired) { return; }\n\$data = " . (sizeof($data) ? "unserialize(" . var_export(serialize($data), true) . ");" : 'array();')); - @flock($fp, LOCK_UN); - fclose($fp); - - phpbb::$system->chmod($filename, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); - } - - return $data; - } - - - /** - * {@link phpbb_acm_abstract::exists() exists()} - */ - public function exists($var_name) - { - if ($var_name[0] === '#') - { - $var_name = substr($var_name, 1); - return $this->exists_global($var_name); - } - - return file_exists($this->cache_dir . $this->cache_prefix . '_' . $var_name . '.' . PHP_EXT); - } - - /** - * {@link phpbb_acm_abstract::destroy() destroy()} - */ - public function destroy($var_name) - { - if ($var_name[0] === '#') - { - $var_name = substr($var_name, 1); - $this->destroy_global($var_name); - } - - if (!$this->exists($var_name)) - { - return false; - } - - $this->remove_file($this->cache_dir . $this->cache_prefix . '_' . $var_name . '.' . PHP_EXT, true); - } - - /** - * {@link phpbb_acm_abstract::load() load()} - */ - public function load() - { - // grab the global cache - if (file_exists($this->cache_dir . $this->cache_prefix . '_global.' . PHP_EXT)) - { - @include($this->cache_dir . $this->cache_prefix . '_global.' . PHP_EXT); - return true; - } - - return false; - } - - /** - * {@link phpbb_acm_abstract::unload() unload()} - */ - public function unload() - { - if (!$this->is_modified) - { - return; - } - - $filename = $this->cache_dir . $this->cache_prefix . '_global.' . PHP_EXT; - - if ($fp = @fopen($filename, 'wb')) - { - @flock($fp, LOCK_EX); - fwrite($fp, "<?php\nif (!defined('IN_PHPBB')) exit;\n\$this->vars = unserialize(" . var_export(serialize($this->vars), true) . ");\n\$this->var_expires = unserialize(" . var_export(serialize($this->var_expires), true) . ");"); - @flock($fp, LOCK_UN); - fclose($fp); - - phpbb::$system->chmod($filename, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); - } - else - { - // Now, this occurred how often? ... phew, just tell the user then... - if (!@is_writable($this->cache_dir)) - { - // We need to use die() here, because else we may encounter an infinite loop (the message handler calls $cache->unload()) - die($this->cache_dir . ' is NOT writable.'); - exit; - } - - die('Not able to open ' . $filename); - exit; - } - - $this->is_modified = false; - - // To reset the global vars - $this->vars = $this->var_expires = array(); - } - - /** - * Tidy local cache data. Also see {@link phpbb_acm_abstract::tidy() tidy()} - * @access protected - */ - protected function tidy_local() - { - $dir = @opendir($this->cache_dir); - - if (!$dir) - { - return; - } - - while (($entry = readdir($dir)) !== false) - { - if (strpos($entry, $this->cache_prefix . '_') !== 0 || strpos($entry, $this->cache_prefix . '_global') === 0) - { - continue; - } - - $expired = true; - @include($this->cache_dir . $entry); - - if ($expired) - { - $this->remove_file($this->cache_dir . $entry); - } - } - closedir($dir); - } - - /** - * Purge local cache data. Also see {@link phpbb_acm_abstract::purge() purge()} - * @access protected - */ - protected function purge_local() - { - $dir = @opendir($this->cache_dir); - - if (!$dir) - { - return; - } - - while (($entry = readdir($dir)) !== false) - { - if (strpos($entry, $this->cache_prefix . '_') !== 0 || strpos($entry, $this->cache_prefix . '_global') === 0) - { - continue; - } - - $this->remove_file($this->cache_dir . $entry); - } - closedir($dir); - } - - /** - * Get modified date for cache entry - * - * @param string $var_name The cache variable name - * @access public - */ - public function get_modified_date($var_name) - { - return @filemtime($this->cache_dir . $this->cache_prefix . '_' . $var_name . '.' . PHP_EXT); - } - - /** - * Removes/unlinks file - * - * @param string $filename The filename to remove - * @param bool $check If true the cache directory is checked for correct directory permissions. - * @access protected - */ - protected function remove_file($filename, $check = false) - { - if ($check && !@is_writable($this->cache_dir)) - { - // E_USER_ERROR - not using language entry - intended. - trigger_error('Unable to remove files within ' . $this->cache_dir . '. Please check directory permissions.', E_USER_ERROR); - } - - return @unlink($filename); - } -} - -/** -* Special implementation for cache type 'sql' -* @package acm -*/ -class phpbb_acm_file_sql extends phpbb_acm_file -{ - /** - * {@link phpbb_acm_abstract::destroy() destroy()} - */ - public function destroy($var_name) - { - if ($var_name[0] === '#') - { - $var_name = substr($var_name, 1); - $this->destroy_global($var_name); - } - - $table = (!is_array($var_name)) ? array($var_name) : $var_name; - $dir = @opendir($this->cache_dir); - - if (!$dir) - { - return; - } - - while (($entry = readdir($dir)) !== false) - { - if (strpos($entry, $this->cache_prefix . '_') !== 0) - { - continue; - } - - // The following method is more failproof than simply assuming the query is on line 3 (which it should be) - @include($this->cache_dir . $entry); - - if (empty($data)) - { - $this->remove_file($this->cache_dir . $entry); - continue; - } - - // Get the query - $data = $data['query']; - - $found = false; - foreach ($table as $check_table) - { - // Better catch partial table names than no table names. ;) - if (strpos($data, $check_table) !== false) - { - $found = true; - break; - } - } - - if ($found) - { - $this->remove_file($this->cache_dir . $entry); - } - } - closedir($dir); - - return; - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/acm/acm_memcache.php b/phpBB/includes/acm/acm_memcache.php deleted file mode 100644 index 175d0663a0..0000000000 --- a/phpBB/includes/acm/acm_memcache.php +++ /dev/null @@ -1,392 +0,0 @@ -<?php -/** -* -* @package acm -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* ACM File Based Caching -* @package acm -*/ -class acm -{ - var $vars = array(); - var $is_modified = false; - - var $sql_rowset = array(); - var $sql_row_pointer = array(); - var $cache_dir = ''; - - var $memcache; - - /** - * Set cache path - */ - function acm() - { - $this->cache_dir = $phpbb_root_path . 'cache/'; - $this->memcache = memcache_connect('localhost', 11211); - } - - /** - * Load global cache - */ - function load() - { - // grab the global cache - $this->vars = memcache_get($this->memcache, 'global'); - - if ($this->vars !== false) - { - return true; - } - - return false; - } - - /** - * Unload cache object - */ - function unload() - { - $this->save(); - unset($this->vars); - unset($this->sql_rowset); - unset($this->sql_row_pointer); - - $this->vars = array(); - $this->sql_rowset = array(); - $this->sql_row_pointer = array(); - } - - /** - * Save modified objects - */ - function save() - { - if (!$this->is_modified) - { - return; - } - - memcache_set($this->memcache, 'global', $this->vars, 0, 2592000); - - $this->is_modified = false; - } - - /** - * Tidy cache - */ - function tidy() - { - // cache has auto GC, no need to have any code here :) - - set_config('cache_last_gc', time(), true); - } - - /** - * Get saved cache object - */ - function get($var_name) - { - if ($var_name[0] == '_') - { - if (!$this->_exists($var_name)) - { - return false; - } - - return memcache_get($this->memcache, $var_name); - } - else - { - return ($this->_exists($var_name)) ? $this->vars[$var_name] : false; - } - } - - /** - * Put data into cache - */ - function put($var_name, $var, $ttl = 2592000) - { - if ($var_name[0] == '_') - { - memcache_set($this->memcache, $var_name, $var, 0, $ttl); - } - else - { - $this->vars[$var_name] = $var; - $this->is_modified = true; - } - } - - /** - * Purge cache data - */ - function purge() - { - // Purge all phpbb cache files - $dir = @opendir($this->cache_dir); - - if (!$dir) - { - return; - } - - while (($entry = readdir($dir)) !== false) - { - if (strpos($entry, 'sql_') !== 0 && strpos($entry, 'data_') !== 0 && strpos($entry, 'ctpl_') !== 0 && strpos($entry, 'tpl_') !== 0) - { - continue; - } - - $this->remove_file($this->cache_dir . $entry); - } - closedir($dir); - - memcache_flush($this->memcache); - - unset($this->vars); - unset($this->sql_rowset); - unset($this->sql_row_pointer); - - $this->vars = array(); - $this->sql_rowset = array(); - $this->sql_row_pointer = array(); - - $this->is_modified = false; - } - - - /** - * Destroy cache data - */ - function destroy($var_name, $table = '') - { - if ($var_name == 'sql' && !empty($table)) - { - if (!is_array($table)) - { - $table = array($table); - } - - foreach ($table as $table_name) - { - // gives us the md5s that we want - $temp = memcache_get($this->memcache, 'sql_' . $table_name); - - if ($temp === false) - { - continue; - } - - // delete each query ref - foreach ($temp as $md5_id => $void) - { - memcache_delete($this->memcache, 'sql_' . $md5_id); - } - - // delete the table ref - memcache_delete($this->memcache, 'sql_' . $table_name); - } - - return; - } - - if (!$this->_exists($var_name)) - { - return; - } - - if ($var_name[0] == '_') - { - memcache_delete($this->memcache, $var_name); - } - else if (isset($this->vars[$var_name])) - { - $this->is_modified = true; - unset($this->vars[$var_name]); - - // We save here to let the following cache hits succeed - $this->save(); - } - } - - /** - * Check if a given cache entry exist - */ - function _exists($var_name) - { - if ($var_name[0] == '_') - { - return true; - } - else - { - if (!sizeof($this->vars)) - { - $this->load(); - } - - return isset($this->vars[$var_name]); - } - } - - /** - * Load cached sql query - */ - function sql_load($query) - { - // Remove extra spaces and tabs - $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); - $query_id = sizeof($this->sql_rowset); - - $temp = memcache_get($this->memcache, 'sql_' . md5($query)); - - if ($temp === false) - { - return false; - } - - $this->sql_rowset[$query_id] = $temp; - $this->sql_row_pointer[$query_id] = 0; - - return $query_id; - } - - /** - * Save sql query - */ - function sql_save($query, &$query_result, $ttl) - { - // Remove extra spaces and tabs - $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); - - // determine which tables this query belongs to - preg_match('/FROM \\(?(\\w+(?: \\w+)?(?:, ?\\w+(?: \\w+)?)*)\\)?/', $query, $regs); - $tables = array_map('trim', explode(',', $regs[1])); - - foreach ($tables as $table_name) - { - if (($pos = strpos($table_name, ' ')) !== false) - { - $table_name = substr($table_name, 0, $pos); - } - - $temp = memcache_get($this->memcache, 'sql_' . $table_name); - if ($temp === false) - { - $temp = array(); - } - $temp[md5($query)] = true; - memcache_set($this->memcache, 'sql_' . $table_name, $temp, 0, $ttl); - } - - // store them in the right place - $query_id = sizeof($this->sql_rowset); - $this->sql_rowset[$query_id] = array(); - $this->sql_row_pointer[$query_id] = 0; - - while ($row = phpbb::$db->sql_fetchrow($query_result)) - { - $this->sql_rowset[$query_id][] = $row; - } - phpbb::$db->sql_freeresult($query_result); - - memcache_set($this->memcache, 'sql_' . md5($query), $this->sql_rowset[$query_id], 0, $ttl); - - $query_result = $query_id; - } - - /** - * Ceck if a given sql query exist in cache - */ - function sql_exists($query_id) - { - return isset($this->sql_rowset[$query_id]); - } - - /** - * Fetch row from cache (database) - */ - function sql_fetchrow($query_id) - { - if ($this->sql_row_pointer[$query_id] < sizeof($this->sql_rowset[$query_id])) - { - return $this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]++]; - } - - return false; - } - - /** - * Fetch a field from the current row of a cached database result (database) - */ - function sql_fetchfield($query_id, $field) - { - if ($this->sql_row_pointer[$query_id] < sizeof($this->sql_rowset[$query_id])) - { - return (isset($this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]][$field])) ? $this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]][$field] : false; - } - - return false; - } - - /** - * Seek a specific row in an a cached database result (database) - */ - function sql_rowseek($rownum, $query_id) - { - if ($rownum >= sizeof($this->sql_rowset[$query_id])) - { - return false; - } - - $this->sql_row_pointer[$query_id] = $rownum; - return true; - } - - /** - * Free memory used for a cached database result (database) - */ - function sql_freeresult($query_id) - { - if (!isset($this->sql_rowset[$query_id])) - { - return false; - } - - unset($this->sql_rowset[$query_id]); - unset($this->sql_row_pointer[$query_id]); - - return true; - } - - /** - * Removes/unlinks file - */ - function remove_file($filename, $check = false) - { - if ($check && !@is_writable($this->cache_dir)) - { - // E_USER_ERROR - not using language entry - intended. - trigger_error('Unable to remove files within ' . $this->cache_dir . '. Please check directory permissions.', E_USER_ERROR); - } - - return @unlink($filename); - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/acm/acm_xcache.php b/phpBB/includes/acm/acm_xcache.php deleted file mode 100644 index e2bf21748a..0000000000 --- a/phpBB/includes/acm/acm_xcache.php +++ /dev/null @@ -1,336 +0,0 @@ -<?php -/** -* -* @package acm -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* ACM XCache Based Caching -* @package acm -*/ -class acm -{ - var $vars = array(); - var $is_modified = false; - - var $sql_rowset = array(); - var $sql_row_pointer = array(); - var $cache_dir = ''; - - /** - * Set cache path - */ - function acm() - { - $this->cache_dir = $phpbb_root_path . 'cache/'; - } - - /** - * Load global cache - */ - function load() - { - // grab the global cache - if (xcache_isset('global')) - { - $this->vars = xcache_get('global'); - return true; - } - - return false; - } - - /** - * Unload cache object - */ - function unload() - { - $this->save(); - unset($this->vars); - unset($this->sql_rowset); - unset($this->sql_row_pointer); - } - - /** - * Save modified objects - */ - function save() - { - if (!$this->is_modified) - { - return; - } - - xcache_set('global', $this->vars, 31536000); - - $this->is_modified = false; - } - - /** - * Tidy cache - */ - function tidy() - { - // cache has auto GC, no need to have any code here :) - - set_config('cache_last_gc', time(), true); - } - - /** - * Get saved cache object - */ - function get($var_name) - { - if ($var_name[0] == '_') - { - return (xcache_isset($var_name)) ? xcache_get($var_name) : false; - } - else - { - if (!sizeof($this->vars)) - { - $this->load(); - } - return (isset($this->vars[$var_name])) ? $this->vars[$var_name] : false; - } - } - - /** - * Put data into cache - */ - function put($var_name, $var, $ttl = 31536000) - { - if ($var_name[0] == '_') - { - xcache_set($var_name, $var, $ttl); - } - else - { - $this->vars[$var_name] = $var; - $this->is_modified = true; - } - } - - /** - * Purge cache data - */ - function purge() - { - // Purge all phpbb cache files - $dir = @opendir($this->cache_dir); - - if (!$dir) - { - return; - } - - while (($entry = readdir($dir)) !== false) - { - if (strpos($entry, 'sql_') !== 0 && strpos($entry, 'data_') !== 0 && strpos($entry, 'ctpl_') !== 0 && strpos($entry, 'tpl_') !== 0) - { - continue; - } - - @unlink($this->cache_dir . $entry); - } - closedir($dir); - - $n = xcache_count(XC_TYPE_VAR); - for ($i = 0; $i < $n; $i++) - { - xcache_clear_cache(XC_TYPE_VAR, $i); - } - - unset($this->vars); - unset($this->sql_rowset); - unset($this->sql_row_pointer); - - $this->is_modified = false; - } - - /** - * Destroy cache data - */ - function destroy($var_name, $table = '') - { - if ($var_name == 'sql' && !empty($table)) - { - if (!is_array($table)) - { - $table = array($table); - } - - foreach ($table as $table_name) - { - // gives us the md5s that we want - if (!xcache_isset('sql_' . $table_name)) - { - continue; - } - $temp = xcache_get('sql_' . $table_name); - - // delete each query ref - foreach ($temp as $md5_id => $void) - { - xcache_unset('sql_' . $md5_id); - } - - // delete the table ref - xcache_unset('sql_' . $table_name); - } - - return; - } - - if ($var_name[0] == '_') - { - xcache_unset($var_name); - } - else if (isset($this->vars[$var_name])) - { - $this->is_modified = true; - unset($this->vars[$var_name]); - - // We save here to let the following cache hits succeed - $this->save(); - } - } - - /** - * Load cached sql query - */ - function sql_load($query) - { - // Remove extra spaces and tabs - $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); - $query_id = sizeof($this->sql_rowset); - - if (!xcache_isset('sql_' . md5($query))) - { - return false; - } - - $this->sql_rowset[$query_id] = xcache_get('sql_' . md5($query)); - - $this->sql_row_pointer[$query_id] = 0; - - return $query_id; - } - - /** - * Save sql query - */ - function sql_save($query, &$query_result, $ttl) - { - // Remove extra spaces and tabs - $query = preg_replace('/[\n\r\s\t]+/', ' ', $query); - - // determine which tables this query belongs to - preg_match('/FROM \\(?(\\w+(?: \\w+)?(?:, ?\\w+(?: \\w+)?)*)\\)?/', $query, $regs); - $tables = array_map('trim', explode(',', $regs[1])); - - foreach ($tables as $table_name) - { - if (($pos = strpos($table_name, ' ')) !== false) - { - $table_name = substr($table_name, 0, $pos); - } - - if (xcache_isset('sql_' . $table_name)) - { - $temp = xcache_get('sql_' . $table_name); - } - else - { - $temp = array(); - } - $temp[md5($query)] = true; - xcache_set('sql_' . $table_name, $temp, $ttl); - } - - // store them in the right place - $query_id = sizeof($this->sql_rowset); - $this->sql_rowset[$query_id] = array(); - $this->sql_row_pointer[$query_id] = 0; - - while ($row = phpbb::$db->sql_fetchrow($query_result)) - { - $this->sql_rowset[$query_id][] = $row; - } - phpbb::$db->sql_freeresult($query_result); - - xcache_set('sql_' . md5($query), $this->sql_rowset[$query_id], $ttl); - - $query_result = $query_id; - } - - /** - * Ceck if a given sql query exist in cache - */ - function sql_exists($query_id) - { - return isset($this->sql_rowset[$query_id]); - } - - /** - * Fetch row from cache (database) - */ - function sql_fetchrow($query_id) - { - if ($this->sql_row_pointer[$query_id] < sizeof($this->sql_rowset[$query_id])) - { - return $this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]++]; - } - - return false; - } - - /** - * Fetch a field from the current row of a cached database result (database) - */ - function sql_fetchfield($query_id, $field) - { - if ($this->sql_row_pointer[$query_id] < sizeof($this->sql_rowset[$query_id])) - { - return (isset($this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]][$field])) ? $this->sql_rowset[$query_id][$this->sql_row_pointer[$query_id]][$field] : false; - } - - return false; - } - - /** - * Seek a specific row in an a cached database result (database) - */ - function sql_rowseek($rownum, $query_id) - { - if ($rownum >= sizeof($this->sql_rowset[$query_id])) - { - return false; - } - - $this->sql_row_pointer[$query_id] = $rownum; - return true; - } - - /** - * Free memory used for a cached database result (database) - */ - function sql_freeresult($query_id) - { - if (!isset($this->sql_rowset[$query_id])) - { - return false; - } - - unset($this->sql_rowset[$query_id]); - unset($this->sql_row_pointer[$query_id]); - - return true; - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/acm/bootstrap.php b/phpBB/includes/acm/bootstrap.php deleted file mode 100644 index ea671706e5..0000000000 --- a/phpBB/includes/acm/bootstrap.php +++ /dev/null @@ -1,487 +0,0 @@ -<?php -/** -* -* @package acm -* @version $Id: acm_file.php 9233 2008-12-27 12:18:04Z acydburn $ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Base cache class. -* -* A prefix of # for $var_name indicates global data. -* -* @method mixed get($var_name) Get cached data. -* @method mixed put($var_name, $data, $ttl = 31536000) Put data into cache. -* @method mixed destroy($var_name) Destroy cached data. -* @method mixed exists($var_name) Check if cached data exists. -* -* @package acm -*/ -class phpbb_acm -{ - /** - * @var array required phpBB objects - */ - public $phpbb_required = array(); - - /** - * @var array Optional phpBB objects - */ - public $phpbb_optional = array(); - - /** - * @var array Currently registered core acm types. - */ - public $cache_types = array('data' => NULL, 'sql' => NULL); - - /** - * Constructor - * @access public - */ - public function __construct() { } - - /** - * Magic method for calling type-specific functions. - * Functions directly supported are: get(), put(), exists(), destroy() - * - * The type is added to the methods name, for getting sql data just use get_sql() for example. - * - * see {@link phpbb_acm_abstract phpbb_acm_abstract} for more information - * - * @access public - */ - public function __call($method, $arguments) - { - $supported_internal_functions = array('get', 'put', 'exists', 'destroy'); - $internal_method = explode('_', $method, 2); - - // Get cache type and method - if (in_array($internal_method[0], $supported_internal_functions)) - { - $cache_type = (empty($internal_method[1])) ? 'data' : $internal_method[1]; - $method = $internal_method[0]; - } - else - { - $cache_type = $arguments[0]; - array_shift($arguments); - } - - // Check if the cache type is initialized and exist - if (!$this->type_exists($cache_type)) - { - return false; - } - - // $this->cache_types[$cache_type]->$method($arguments); - return call_user_func_array(array($this->cache_types[$cache_type], $method), $arguments); - } - - /** - * Tidy cache. This removes all expired cache data. - * @access public - */ - public function tidy() - { - foreach ($this->cache_types as $cache_type => $object) - { - if ($object === NULL) - { - continue; - } - - $this->cache_types[$cache_type]->tidy(); - } - } - - /** - * Purge cache. This removes all cache data, not only the expired one. - * @access public - */ - public function purge() - { - foreach ($this->cache_types as $cache_type => $object) - { - if ($object === NULL) - { - continue; - } - - $this->cache_types[$cache_type]->purge(); - } - } - - /** - * Load cache data. This is usually only used internally. - * @access public - */ - public function load() - { - foreach ($this->cache_types as $cache_type => $object) - { - if ($object === NULL) - { - continue; - } - - $this->cache_types[$cache_type]->load(); - } - } - - /** - * Unload everything from cache and make sure non-stored cache items are properly saved. - * @access public - */ - public function unload() - { - foreach ($this->cache_types as $cache_type => $object) - { - if ($object === NULL) - { - continue; - } - - $this->cache_types[$cache_type]->unload(); - } - } - - /** - * Register a custom cache type/class. - * - * @param string $cache_type The cache type to register/set - * @param string $cache_append String to append to the cached data as identifier (if the coder has different types to distinct from) - * @param string $cache_object The exact name of the cache class to load. - * The filename must be: <code>includes/acm/acm_{$cache_object}.php</code> - * The class definition must be: <code>class phpbb_acm_{$cache_object} extends phpbb_acm_abstract</code> - * Additionally it is possible to define classes for every cache type... - * for example: <code>phpbb_acm_{$cache_object}_{$cache_type} extends phpbb_acm_{$cache_object}</code> - * - * @return bool Returns true on success, else false. - * @access public - */ - public function register($cache_type, $cache_append = false, $cache_object = false) - { - $cache_object = ($cache_object === false) ? basename(phpbb::$base_config['acm_type']) : basename($cache_object); - - // We need to init every cache type... - if (!isset($this->cache_types[$cache_type])) - { - $this->cache_types[$cache_type] = NULL; - } - - // Unregister if already registered - if ($this->cache_types[$cache_type] !== NULL) - { - $this->cache_types[$cache_type] = NULL; - } - - if ($this->cache_types[$cache_type] === NULL) - { - $class_name = 'phpbb_acm_' . $cache_object; - - if (!class_exists($class_name)) - { - if (!file_exists(PHPBB_ROOT_PATH . 'includes/acm/acm_' . $cache_object . '.' . PHP_EXT)) - { - return false; - } - - require_once PHPBB_ROOT_PATH . 'includes/acm/acm_' . $cache_object . '.' . PHP_EXT; - } - - $class_name = (class_exists('phpbb_acm_' . $cache_object . '_' . $cache_type)) ? 'phpbb_acm_' . $cache_object . '_' . $cache_type : 'phpbb_acm_' . $cache_object; - - // Set cache prefix, for example ctpl_prosilver - $cache_prefix = ($cache_append === false) ? $cache_type : $cache_type . '_' . $cache_append; - - $this->cache_types[$cache_type] = new $class_name($cache_prefix); - - if (!$this->supported($cache_type)) - { - $this->cache_types[$cache_type] = NULL; - return false; - } - } - - return true; - } - - /** - * Check if a specified cache type is supported with the ACM class - * - * @param string $cache_type The cache type to check. - * - * @return bool True if the type is supported, else false. - * @access public - */ - public function supported($cache_type) - { - if (!$this->type_exists($cache_type)) - { - return false; - } - - return !empty($this->cache_types[$cache_type]->supported[$cache_type]) || $this->cache_types[$cache_type]->supported === true; - } - - /** - * Check if the cache type exists. Sometimes some types do not exist if the relevant files are not there or do not support the given cache type. - * - * @param string $cache_type The cache type to check. - * - * @return bool True if the type exist, else false. - * @access private - */ - private function type_exists($cache_type) - { - if (!isset($this->cache_types[$cache_type]) || $this->cache_types[$cache_type] === NULL) - { - $this->register($cache_type); - } - - return $this->cache_types[$cache_type] !== NULL; - } -} - - -/** -* The abstract class all ACM plugins must extend. -* @package acm -*/ -abstract class phpbb_acm_abstract -{ - /** - * @var string The current cache prefix - */ - public $cache_prefix = ''; - - /** - * @var array Cached global data - */ - protected $vars = array(); - - /** - * @var array Expire information for cached global data - */ - protected $var_expires = array(); - - /** - * @var bool Is true if global data is modified - */ - protected $is_modified = false; - - /** - * Get cached data - * - * @param string $var_name Variable name. Global variable name is prefixed with #. - * - * @return mixed Returns false if there is no data available, else returns the data - * @access public - */ - abstract public function get($var_name); - - /** - * Put data into cache - * - * @param string $var_name Variable name. Global variable name is prefixed with #. - * @param mixed $data Data to be put into cache. - * @param int $ttl Cache lifetime in seconds. - * - * @return mixed Returns $data - * @access public - */ - abstract public function put($var_name, $data, $ttl = 31536000); - - /** - * Destroy cached data. - * - * @param string $var_name Variable name. Global variable name is prefixed with #. - * - * @return mixed Returns false if the cached data does not exist - * @access public - */ - abstract public function destroy($var_name); - - /** - * Check if cached data exists. - * - * @param string $var_name Variable name. Global variable name is prefixed with #. - * - * @return bool True if it exists - * @access public - */ - abstract public function exists($var_name); - - /** - * Load cache data. This is usually only used internally. - * @access public - */ - abstract public function load(); - - /** - * Unload everything from cache and make sure non-stored cache items are properly saved. - * @access public - */ - abstract public function unload(); - - /** - * Tidy cache. This removes all expired cache data. - * @access public - */ - public function tidy() - { - $this->tidy_local(); - $this->tidy_global(); - - set_config('cache_last_gc', time(), true); - } - - /** - * Purge cache. This removes all cache data, not only the expired one. - * @access public - */ - public function purge() - { - $this->purge_local(); - $this->purge_global(); - } - - /** - * Tidy only local cache data - * @access protected - */ - abstract protected function tidy_local(); - - /** - * Purge only local cache data - * @access protected - */ - abstract protected function purge_local(); - - /** - * Get global cache data. See {@link get() get()}. - * @access protected - */ - protected function get_global($var_name) - { - // Check if we have all variables - if (!sizeof($this->vars)) - { - $this->load(); - } - - if (!isset($this->var_expires[$var_name])) - { - return false; - } - - // If expired... we remove this entry now... - if (time() > $this->var_expires[$var_name]) - { - $this->destroy('#' . $var_name); - return false; - } - - if (isset($this->vars[$var_name])) - { - return $this->vars[$var_name]; - } - - return false; - } - - /** - * Put data into global cache. See {@link put() put()}. - * @access protected - */ - protected function put_global($var_name, $data, $ttl = 31536000) - { - $this->vars[$var_name] = $data; - $this->var_expires[$var_name] = time() + $ttl; - $this->is_modified = true; - - return $data; - } - - /** - * Check if global data exists. See {@link exists() exists()}. - * @access protected - */ - protected function exists_global($var_name) - { - return !empty($this->vars[$var_name]) && time() <= $this->var_expires[$var_name]; - } - - /** - * Destroy global cache data. See {@link destroy() destroy()}. - * @access protected - */ - protected function destroy_global($var_name) - { - $this->is_modified = true; - - unset($this->vars[$var_name]); - unset($this->var_expires[$var_name]); - - // We save here to let the following cache hits succeed - $this->unload(); - } - - /** - * Tidy global cache data. See {@link tidy() tidy()}. - * @access protected - */ - protected function tidy_global() - { - // Now tidy global settings - if (!sizeof($this->vars)) - { - $this->load(); - } - - foreach ($this->var_expires as $var_name => $expires) - { - if (time() > $expires) - { - // We only unset, then save later - unset($this->vars[$var_name]); - unset($this->var_expires[$var_name]); - } - } - - $this->is_modified = true; - $this->unload(); - } - - /** - * Purge global cache data. See {@link purge() purge()}. - * @access protected - */ - protected function purge_global() - { - // Now purge global settings - unset($this->vars); - unset($this->var_expires); - - $this->vars = array(); - $this->var_expires = array(); - - $this->is_modified = true; - $this->unload(); - } -} - - - -?>
\ No newline at end of file diff --git a/phpBB/includes/auth/auth_apache.php b/phpBB/includes/auth/auth_apache.php deleted file mode 100644 index 2b9c068672..0000000000 --- a/phpBB/includes/auth/auth_apache.php +++ /dev/null @@ -1,250 +0,0 @@ -<?php -/** -* Apache auth plug-in for phpBB3 -* -* Authentication plug-ins is largely down to Sergey Kanareykin, our thanks to him. -* -* @package login -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Checks whether the user is identified to apache -* Only allow changing authentication to apache if the user is identified -* Called in acp_board while setting authentication plugins -* -* @return boolean|string false if the user is identified and else an error message -*/ -function init_apache() -{ - if (!isset($_SERVER['PHP_AUTH_USER']) || phpbb::$user->data['username'] !== $_SERVER['PHP_AUTH_USER']) - { - return phpbb::$user->lang['APACHE_SETUP_BEFORE_USE']; - } - return false; -} - -/** -* Login function -*/ -function login_apache(&$username, &$password) -{ - // do not allow empty password - if (!$password) - { - return array( - 'status' => LOGIN_ERROR_PASSWORD, - 'error_msg' => 'NO_PASSWORD_SUPPLIED', - 'user_row' => array('user_id' => ANONYMOUS), - ); - } - - if (!$username) - { - return array( - 'status' => LOGIN_ERROR_USERNAME, - 'error_msg' => 'LOGIN_ERROR_USERNAME', - 'user_row' => array('user_id' => ANONYMOUS), - ); - } - - if (!isset($_SERVER['PHP_AUTH_USER'])) - { - return array( - 'status' => LOGIN_ERROR_EXTERNAL_AUTH, - 'error_msg' => 'LOGIN_ERROR_EXTERNAL_AUTH_APACHE', - 'user_row' => array('user_id' => ANONYMOUS), - ); - } - - $php_auth_user = $_SERVER['PHP_AUTH_USER']; - $php_auth_pw = $_SERVER['PHP_AUTH_PW']; - - if (!empty($php_auth_user) && !empty($php_auth_pw)) - { - if ($php_auth_user !== $username) - { - return array( - 'status' => LOGIN_ERROR_USERNAME, - 'error_msg' => 'LOGIN_ERROR_USERNAME', - 'user_row' => array('user_id' => ANONYMOUS), - ); - } - - $sql = 'SELECT user_id, username, user_password, user_passchg, user_email, user_type - FROM ' . USERS_TABLE . " - WHERE username = '" . phpbb::$db->sql_escape($php_auth_user) . "'"; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ($row) - { - // User inactive... - if ($row['user_type'] == phpbb::USER_INACTIVE || $row['user_type'] == phpbb::USER_IGNORE) - { - return array( - 'status' => LOGIN_ERROR_ACTIVE, - 'error_msg' => 'ACTIVE_ERROR', - 'user_row' => $row, - ); - } - - // Successful login... - return array( - 'status' => LOGIN_SUCCESS, - 'error_msg' => false, - 'user_row' => $row, - ); - } - - // this is the user's first login so create an empty profile - return array( - 'status' => LOGIN_SUCCESS_CREATE_PROFILE, - 'error_msg' => false, - 'user_row' => user_row_apache($php_auth_user, $php_auth_pw), - ); - } - - // Not logged into apache - return array( - 'status' => LOGIN_ERROR_EXTERNAL_AUTH, - 'error_msg' => 'LOGIN_ERROR_EXTERNAL_AUTH_APACHE', - 'user_row' => array('user_id' => ANONYMOUS), - ); -} - -/** -* Autologin function -* -* @return array containing the user row or empty if no auto login should take place -*/ -function autologin_apache() -{ - if (!isset($_SERVER['PHP_AUTH_USER'])) - { - return array(); - } - - $php_auth_user = $_SERVER['PHP_AUTH_USER']; - $php_auth_pw = $_SERVER['PHP_AUTH_PW']; - - if (!empty($php_auth_user) && !empty($php_auth_pw)) - { - set_var($php_auth_user, $php_auth_user, 'string', true); - set_var($php_auth_pw, $php_auth_pw, 'string', true); - - $sql = 'SELECT * - FROM ' . USERS_TABLE . " - WHERE username = '" . phpbb::$db->sql_escape($php_auth_user) . "'"; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ($row) - { - return ($row['user_type'] == phpbb::USER_INACTIVE || $row['user_type'] == phpbb::USER_IGNORE) ? array() : $row; - } - - if (!function_exists('user_add')) - { - include(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); - } - - // create the user if he does not exist yet - user_add(user_row_apache($php_auth_user, $php_auth_pw)); - - $sql = 'SELECT * - FROM ' . USERS_TABLE . " - WHERE username_clean = '" . phpbb::$db->sql_escape(utf8_clean_string($php_auth_user)) . "'"; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ($row) - { - return $row; - } - } - - return array(); -} - -/** -* This function generates an array which can be passed to the user_add function in order to create a user -*/ -function user_row_apache($username, $password) -{ - // first retrieve default group id - $sql = 'SELECT group_id - FROM ' . GROUPS_TABLE . " - WHERE group_name_clean = '" . phpbb::$db->sql_escape('registered') . "' - AND group_type = " . GROUP_SPECIAL; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if (!$row) - { - trigger_error('NO_GROUP'); - } - - // generate user account data - return array( - 'username' => $username, - 'user_password' => phpbb_hash($password), - 'user_email' => '', - 'group_id' => (int) $row['group_id'], - 'user_type' => phpbb::USER_NORMAL, - 'user_ip' => phpbb::$user->ip, - ); -} - -/** -* The session validation function checks whether the user is still logged in -* -* @return boolean true if the given user is authenticated or false if the session should be closed -*/ -function validate_session_apache(&$user) -{ - // We only need to check authenticated users. For anonymous user as well as bots the session of course did not expire. - if ($user['user_id'] == ANONYMOUS) - { - return true; - } - - // Checking for a bot is a bit mroe complicated... but we are able to check this with the user type (anonymous has the same as bots) - if ($user['user_type'] == USER_IGNORE) - { - return true; - } - - if (!isset($_SERVER['PHP_AUTH_USER'])) - { - $php_auth_user = ''; - set_var($php_auth_user, $_SERVER['PHP_AUTH_USER'], 'string', true); - - return ($php_auth_user === $user['username']) ? true : false; - } - - // PHP_AUTH_USER is not set. A valid session is now determined by the user type (anonymous/bot or not) - if ($user['user_type'] == USER_IGNORE) - { - return true; - } - - return false; -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/auth/auth_ldap.php b/phpBB/includes/auth/auth_ldap.php deleted file mode 100644 index 6dd9abda03..0000000000 --- a/phpBB/includes/auth/auth_ldap.php +++ /dev/null @@ -1,335 +0,0 @@ -<?php -/** -* -* LDAP auth plug-in for phpBB3 -* -* Authentication plug-ins is largely down to Sergey Kanareykin, our thanks to him. -* -* @package login -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Connect to ldap server -* Only allow changing authentication to ldap if we can connect to the ldap server -* Called in acp_board while setting authentication plugins -*/ -function init_ldap() -{ - if (!@extension_loaded('ldap')) - { - return phpbb::$user->lang['LDAP_NO_LDAP_EXTENSION']; - } - - phpbb::$config['ldap_port'] = (int) phpbb::$config['ldap_port']; - if (phpbb::$config['ldap_port']) - { - $ldap = @ldap_connect(phpbb::$config['ldap_server'], phpbb::$config['ldap_port']); - } - else - { - $ldap = @ldap_connect(phpbb::$config['ldap_server']); - } - - if (!$ldap) - { - return phpbb::$user->lang['LDAP_NO_SERVER_CONNECTION']; - } - - @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3); - @ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0); - - if (phpbb::$config['ldap_user'] || phpbb::$config['ldap_password']) - { - if (!@ldap_bind($ldap, htmlspecialchars_decode(phpbb::$config['ldap_user']), htmlspecialchars_decode(phpbb::$config['ldap_password']))) - { - return phpbb::$user->lang['LDAP_INCORRECT_USER_PASSWORD']; - } - } - - // ldap_connect only checks whether the specified server is valid, so the connection might still fail - $search = @ldap_search( - $ldap, - phpbb::$config['ldap_base_dn'], - ldap_user_filter(phpbb::$user->data['username']), - (empty(phpbb::$config['ldap_email'])) ? array(phpbb::$config['ldap_uid']) : array(phpbb::$config['ldap_uid'], phpbb::$config['ldap_email']), - 0, - 1 - ); - - if ($search === false) - { - return phpbb::$user->lang['LDAP_NO_SERVER_CONNECTION']; - } - - $result = @ldap_get_entries($ldap, $search); - - @ldap_close($ldap); - - - if (!is_array($result) || sizeof($result) < 2) - { - return sprintf(phpbb::$user->lang['LDAP_NO_IDENTITY'], phpbb::$user->data['username']); - } - - if (!empty(phpbb::$config['ldap_email']) && !isset($result[0][phpbb::$config['ldap_email']])) - { - return phpbb::$user->lang['LDAP_NO_EMAIL']; - } - - return false; -} - -/** -* Login function -*/ -function login_ldap(&$username, &$password) -{ - // do not allow empty password - if (!$password) - { - return array( - 'status' => LOGIN_ERROR_PASSWORD, - 'error_msg' => 'NO_PASSWORD_SUPPLIED', - 'user_row' => array('user_id' => ANONYMOUS), - ); - } - - if (!$username) - { - return array( - 'status' => LOGIN_ERROR_USERNAME, - 'error_msg' => 'LOGIN_ERROR_USERNAME', - 'user_row' => array('user_id' => ANONYMOUS), - ); - } - - if (!@extension_loaded('ldap')) - { - return array( - 'status' => LOGIN_ERROR_EXTERNAL_AUTH, - 'error_msg' => 'LDAP_NO_LDAP_EXTENSION', - 'user_row' => array('user_id' => ANONYMOUS), - ); - } - - phpbb::$config['ldap_port'] = (int) phpbb::$config['ldap_port']; - if (phpbb::$config['ldap_port']) - { - $ldap = @ldap_connect(phpbb::$config['ldap_server'], phpbb::$config['ldap_port']); - } - else - { - $ldap = @ldap_connect(phpbb::$config['ldap_server']); - } - - if (!$ldap) - { - return array( - 'status' => LOGIN_ERROR_EXTERNAL_AUTH, - 'error_msg' => 'LDAP_NO_SERVER_CONNECTION', - 'user_row' => array('user_id' => ANONYMOUS), - ); - } - - @ldap_set_option($ldap, LDAP_OPT_PROTOCOL_VERSION, 3); - @ldap_set_option($ldap, LDAP_OPT_REFERRALS, 0); - - if (phpbb::$config['ldap_user'] || phpbb::$config['ldap_password']) - { - if (!@ldap_bind($ldap, phpbb::$config['ldap_user'], htmlspecialchars_decode(phpbb::$config['ldap_password']))) - { - return phpbb::$user->lang['LDAP_NO_SERVER_CONNECTION']; - } - } - - $search = @ldap_search( - $ldap, - phpbb::$config['ldap_base_dn'], - ldap_user_filter($username), - (empty(phpbb::$config['ldap_email'])) ? array(phpbb::$config['ldap_uid']) : array(phpbb::$config['ldap_uid'], phpbb::$config['ldap_email']), - 0, - 1 - ); - - $ldap_result = @ldap_get_entries($ldap, $search); - - if (is_array($ldap_result) && sizeof($ldap_result) > 1) - { - if (@ldap_bind($ldap, $ldap_result[0]['dn'], htmlspecialchars_decode($password))) - { - @ldap_close($ldap); - - $sql ='SELECT user_id, username, user_password, user_passchg, user_email, user_type - FROM ' . USERS_TABLE . " - WHERE username_clean = '" . phpbb::$db->sql_escape(utf8_clean_string($username)) . "'"; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ($row) - { - unset($ldap_result); - - // User inactive... - if ($row['user_type'] == phpbb::USER_INACTIVE || $row['user_type'] == phpbb::USER_IGNORE) - { - return array( - 'status' => LOGIN_ERROR_ACTIVE, - 'error_msg' => 'ACTIVE_ERROR', - 'user_row' => $row, - ); - } - - // Successful login... set user_login_attempts to zero... - return array( - 'status' => LOGIN_SUCCESS, - 'error_msg' => false, - 'user_row' => $row, - ); - } - else - { - // retrieve default group id - $sql = 'SELECT group_id - FROM ' . GROUPS_TABLE . " - WHERE group_name_clean = '" . phpbb::$db->sql_escape('registered') . "' - AND group_type = " . GROUP_SPECIAL; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if (!$row) - { - trigger_error('NO_GROUP'); - } - - // generate user account data - $ldap_user_row = array( - 'username' => $username, - 'user_password' => phpbb_hash($password), - 'user_email' => (!empty(phpbb::$config['ldap_email'])) ? $ldap_result[0][phpbb::$config['ldap_email']][0] : '', - 'group_id' => (int) $row['group_id'], - 'user_type' => phpbb::USER_NORMAL, - 'user_ip' => phpbb::$user->ip, - ); - - unset($ldap_result); - - // this is the user's first login so create an empty profile - return array( - 'status' => LOGIN_SUCCESS_CREATE_PROFILE, - 'error_msg' => false, - 'user_row' => $ldap_user_row, - ); - } - } - else - { - unset($ldap_result); - @ldap_close($ldap); - - // Give status about wrong password... - return array( - 'status' => LOGIN_ERROR_PASSWORD, - 'error_msg' => 'LOGIN_ERROR_PASSWORD', - 'user_row' => array('user_id' => ANONYMOUS), - ); - } - } - - @ldap_close($ldap); - - return array( - 'status' => LOGIN_ERROR_USERNAME, - 'error_msg' => 'LOGIN_ERROR_USERNAME', - 'user_row' => array('user_id' => ANONYMOUS), - ); -} - -/** -* Generates a filter string for ldap_search to find a user -* -* @param $username string Username identifying the searched user -* -* @return string A filter string for ldap_search -*/ -function ldap_user_filter($username) -{ - $filter = '(' . phpbb::$config['ldap_uid'] . '=' . ldap_escape(htmlspecialchars_decode($username)) . ')'; - if (phpbb::$config['ldap_user_filter']) - { - $filter = "(&$filter({phpbb::$config['ldap_user_filter']}))"; - } - return $filter; -} - -/** -* Escapes an LDAP AttributeValue -*/ -function ldap_escape($string) -{ - return str_replace(array('*', '\\', '(', ')'), array('\\*', '\\\\', '\\(', '\\)'), $string); -} - -/** -* This function is used to output any required fields in the authentication -* admin panel. It also defines any required configuration table fields. -*/ -function acp_ldap(&$new) -{ - $tpl = ' - - <dl> - <dt><label for="ldap_server">' . phpbb::$user->lang['LDAP_SERVER'] . ':</label><br /><span>' . phpbb::$user->lang['LDAP_SERVER_EXPLAIN'] . '</span></dt> - <dd><input type="text" id="ldap_server" size="40" name="config[ldap_server]" value="' . $new['ldap_server'] . '" /></dd> - </dl> - <dl> - <dt><label for="ldap_port">' . phpbb::$user->lang['LDAP_PORT'] . ':</label><br /><span>' . phpbb::$user->lang['LDAP_PORT_EXPLAIN'] . '</span></dt> - <dd><input type="text" id="ldap_port" size="40" name="config[ldap_port]" value="' . $new['ldap_port'] . '" /></dd> - </dl> - <dl> - <dt><label for="ldap_dn">' . phpbb::$user->lang['LDAP_DN'] . ':</label><br /><span>' . phpbb::$user->lang['LDAP_DN_EXPLAIN'] . '</span></dt> - <dd><input type="text" id="ldap_dn" size="40" name="config[ldap_base_dn]" value="' . $new['ldap_base_dn'] . '" /></dd> - </dl> - <dl> - <dt><label for="ldap_uid">' . phpbb::$user->lang['LDAP_UID'] . ':</label><br /><span>' . phpbb::$user->lang['LDAP_UID_EXPLAIN'] . '</span></dt> - <dd><input type="text" id="ldap_uid" size="40" name="config[ldap_uid]" value="' . $new['ldap_uid'] . '" /></dd> - </dl> - <dl> - <dt><label for="ldap_user_filter">' . phpbb::$user->lang['LDAP_USER_FILTER'] . ':</label><br /><span>' . phpbb::$user->lang['LDAP_USER_FILTER_EXPLAIN'] . '</span></dt> - <dd><input type="text" id="ldap_user_filter" size="40" name="config[ldap_user_filter]" value="' . $new['ldap_user_filter'] . '" /></dd> - </dl> - <dl> - <dt><label for="ldap_email">' . phpbb::$user->lang['LDAP_EMAIL'] . ':</label><br /><span>' . phpbb::$user->lang['LDAP_EMAIL_EXPLAIN'] . '</span></dt> - <dd><input type="text" id="ldap_email" size="40" name="config[ldap_email]" value="' . $new['ldap_email'] . '" /></dd> - </dl> - <dl> - <dt><label for="ldap_user">' . phpbb::$user->lang['LDAP_USER'] . ':</label><br /><span>' . phpbb::$user->lang['LDAP_USER_EXPLAIN'] . '</span></dt> - <dd><input type="text" id="ldap_user" size="40" name="config[ldap_user]" value="' . $new['ldap_user'] . '" /></dd> - </dl> - <dl> - <dt><label for="ldap_password">' . phpbb::$user->lang['LDAP_PASSWORD'] . ':</label><br /><span>' . phpbb::$user->lang['LDAP_PASSWORD_EXPLAIN'] . '</span></dt> - <dd><input type="password" id="ldap_password" size="40" name="config[ldap_password]" value="' . $new['ldap_password'] . '" /></dd> - </dl> - '; - - // These are fields required in the config table - return array( - 'tpl' => $tpl, - 'config' => array('ldap_server', 'ldap_port', 'ldap_base_dn', 'ldap_uid', 'ldap_user_filter', 'ldap_email', 'ldap_user', 'ldap_password') - ); -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/auth/db.php b/phpBB/includes/auth/db.php deleted file mode 100644 index 11b90e4df7..0000000000 --- a/phpBB/includes/auth/db.php +++ /dev/null @@ -1,158 +0,0 @@ -<?php -/** -* Database auth plug-in for phpBB3 -* -* Authentication plug-ins is largely down to Sergey Kanareykin, our thanks to him. -* -* This is for authentication via the integrated user table -* -* @package login -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -class phpbb_auth_db /* extends phpbb_auth */ -{ - /** - * Login function - */ - function login(&$username, &$password) - { - // do not allow empty password - if (!$password) - { - return array( - 'status' => LOGIN_ERROR_PASSWORD, - 'error_msg' => 'NO_PASSWORD_SUPPLIED', - 'user_row' => array('user_id' => ANONYMOUS), - ); - } - - if (!$username) - { - return array( - 'status' => LOGIN_ERROR_USERNAME, - 'error_msg' => 'LOGIN_ERROR_USERNAME', - 'user_row' => array('user_id' => ANONYMOUS), - ); - } - - $sql = 'SELECT user_id, username, user_password, user_passchg, user_pass_convert, user_email, user_type, user_login_attempts - FROM ' . USERS_TABLE . " - WHERE username_clean = '" . phpbb::$db->sql_escape(utf8_clean_string($username)) . "'"; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if (!$row) - { - return array( - 'status' => LOGIN_ERROR_USERNAME, - 'error_msg' => 'LOGIN_ERROR_USERNAME', - 'user_row' => array('user_id' => ANONYMOUS), - ); - } - - // If there are too much login attempts, we need to check for an confirm image - // Every auth module is able to define what to do by itself... - if (phpbb::$config['max_login_attempts'] && $row['user_login_attempts'] >= phpbb::$config['max_login_attempts']) - { - $confirm_id = request_var('confirm_id', ''); - $confirm_code = request_var('confirm_code', ''); - - // Visual Confirmation handling - if (!$confirm_id) - { - return array( - 'status' => LOGIN_ERROR_ATTEMPTS, - 'error_msg' => 'LOGIN_ERROR_ATTEMPTS', - 'user_row' => $row, - ); - } - else - { - $captcha = phpbb_captcha_factory::get_instance(phpbb::$config['captcha_plugin']); - $captcha->init(CONFIRM_LOGIN); - $vc_response = $captcha->validate(); - if ($vc_response) - { - return array( - 'status' => LOGIN_ERROR_ATTEMPTS, - 'error_msg' => 'LOGIN_ERROR_ATTEMPTS', - 'user_row' => $row, - ); - } - } - } - - // Check password ... - if (!$row['user_pass_convert'] && phpbb::$security->check_password($password, $row['user_password'])) - { - // Check for old password hash... - if (strlen($row['user_password']) == 32) - { - $hash = phpbb::$security->hash_password($password); - - // Update the password in the users table to the new format - $sql = 'UPDATE ' . USERS_TABLE . " - SET user_password = '" . phpbb::$db->sql_escape($hash) . "', - user_pass_convert = 0 - WHERE user_id = {$row['user_id']}"; - phpbb::$db->sql_query($sql); - - $row['user_password'] = $hash; - } - - if ($row['user_login_attempts'] != 0) - { - // Successful, reset login attempts (the user passed all stages) - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_login_attempts = 0 - WHERE user_id = ' . $row['user_id']; - phpbb::$db->sql_query($sql); - } - - // User inactive... - if ($row['user_type'] == phpbb::USER_INACTIVE || $row['user_type'] == phpbb::USER_IGNORE) - { - return array( - 'status' => LOGIN_ERROR_ACTIVE, - 'error_msg' => 'ACTIVE_ERROR', - 'user_row' => $row, - ); - } - - // Successful login... set user_login_attempts to zero... - return array( - 'status' => LOGIN_SUCCESS, - 'error_msg' => false, - 'user_row' => $row, - ); - } - - // Password incorrect - increase login attempts - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_login_attempts = user_login_attempts + 1 - WHERE user_id = ' . $row['user_id']; - phpbb::$db->sql_query($sql); - - // Give status about wrong password... - return array( - 'status' => LOGIN_ERROR_PASSWORD, - 'error_msg' => 'LOGIN_ERROR_PASSWORD', - 'user_row' => $row, - ); - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/bbcode.php b/phpBB/includes/bbcode.php deleted file mode 100644 index 22aa43431e..0000000000 --- a/phpBB/includes/bbcode.php +++ /dev/null @@ -1,583 +0,0 @@ -18.04.2009<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* BBCode class -* @package phpBB3 -*/ -class bbcode -{ - var $bbcode_uid = ''; - var $bbcode_bitfield = ''; - var $bbcode_cache = array(); - var $bbcode_template = array(); - - var $bbcodes = array(); - - var $template_bitfield; - var $template_filename = ''; - - /** - * Constructor - * Init bbcode cache entries if bitfield is specified - */ - function __construct($bitfield = '') - { - if ($bitfield) - { - $this->bbcode_bitfield = $bitfield; - $this->bbcode_cache_init(); - } - } - - /** - * Second pass bbcodes - */ - function bbcode_second_pass(&$message, $bbcode_uid = '', $bbcode_bitfield = false) - { - if ($bbcode_uid) - { - $this->bbcode_uid = $bbcode_uid; - } - - if ($bbcode_bitfield !== false) - { - $this->bbcode_bitfield = $bbcode_bitfield; - - // Init those added with a new bbcode_bitfield (already stored codes will not get parsed again) - $this->bbcode_cache_init(); - } - - if (!$this->bbcode_bitfield) - { - // Remove the uid from tags that have not been transformed into HTML - if ($this->bbcode_uid) - { - $message = str_replace(':' . $this->bbcode_uid, '', $message); - } - - return; - } - - $str = array('search' => array(), 'replace' => array()); - $preg = array('search' => array(), 'replace' => array()); - - $bitfield = new bitfield($this->bbcode_bitfield); - $bbcodes_set = $bitfield->get_all_set(); - - $undid_bbcode_specialchars = false; - foreach ($bbcodes_set as $bbcode_id) - { - if (!empty($this->bbcode_cache[$bbcode_id])) - { - foreach ($this->bbcode_cache[$bbcode_id] as $type => $array) - { - foreach ($array as $search => $replace) - { - ${$type}['search'][] = str_replace('$uid', $this->bbcode_uid, $search); - ${$type}['replace'][] = $replace; - } - - if (sizeof($str['search'])) - { - $message = str_replace($str['search'], $str['replace'], $message); - $str = array('search' => array(), 'replace' => array()); - } - - if (sizeof($preg['search'])) - { - // we need to turn the entities back into their original form to allow the - // search patterns to work properly - if (!$undid_bbcode_specialchars) - { - $message = str_replace(array(':', '.'), array(':', '.'), $message); - $undid_bbcode_specialchars = true; - } - - $message = preg_replace($preg['search'], $preg['replace'], $message); - $preg = array('search' => array(), 'replace' => array()); - } - } - } - } - - // Remove the uid from tags that have not been transformed into HTML - $message = str_replace(':' . $this->bbcode_uid, '', $message); - } - - /** - * Init bbcode cache - * - * requires: $this->bbcode_bitfield - * sets: $this->bbcode_cache with bbcode templates needed for bbcode_bitfield - */ - function bbcode_cache_init() - { - if (empty($this->template_filename)) - { - $this->template_bitfield = new bitfield(phpbb::$user->theme['bbcode_bitfield']); - $this->template_filename = PHPBB_ROOT_PATH . 'styles/' . phpbb::$user->theme['template_path'] . '/template/bbcode.html'; - - if (!@file_exists($this->template_filename)) - { - trigger_error('The file ' . $this->template_filename . ' is missing.', E_USER_ERROR); - } - } - - $bbcode_ids = $rowset = $sql = array(); - - $bitfield = new bitfield($this->bbcode_bitfield); - $bbcodes_set = $bitfield->get_all_set(); - - foreach ($bbcodes_set as $bbcode_id) - { - if (isset($this->bbcode_cache[$bbcode_id])) - { - // do not try to re-cache it if it's already in - continue; - } - $bbcode_ids[] = $bbcode_id; - - if ($bbcode_id > NUM_CORE_BBCODES) - { - $sql[] = $bbcode_id; - } - } - - if (sizeof($sql)) - { - $sql = 'SELECT * - FROM ' . BBCODES_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('bbcode_id', $sql); - $result = phpbb::$db->sql_query($sql, 3600); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - // To circumvent replacing newlines with <br /> for the generated html, - // we use carriage returns here. They are later changed back to newlines - $row['bbcode_tpl'] = str_replace("\n", "\r", $row['bbcode_tpl']); - $row['second_pass_replace'] = str_replace("\n", "\r", $row['second_pass_replace']); - - $rowset[$row['bbcode_id']] = $row; - } - phpbb::$db->sql_freeresult($result); - } - - foreach ($bbcode_ids as $bbcode_id) - { - switch ($bbcode_id) - { - case 0: - $this->bbcode_cache[$bbcode_id] = array( - 'str' => array( - '[/quote:$uid]' => $this->bbcode_tpl('quote_close', $bbcode_id) - ), - 'preg' => array( - '#\[quote(?:="(.*?)")?:$uid\]((?!\[quote(?:=".*?")?:$uid\]).)?#ise' => "\$this->bbcode_second_pass_quote('\$1', '\$2')" - ) - ); - break; - - case 1: - $this->bbcode_cache[$bbcode_id] = array( - 'str' => array( - '[b:$uid]' => $this->bbcode_tpl('b_open', $bbcode_id), - '[/b:$uid]' => $this->bbcode_tpl('b_close', $bbcode_id), - ) - ); - break; - - case 2: - $this->bbcode_cache[$bbcode_id] = array( - 'str' => array( - '[i:$uid]' => $this->bbcode_tpl('i_open', $bbcode_id), - '[/i:$uid]' => $this->bbcode_tpl('i_close', $bbcode_id), - ) - ); - break; - - case 3: - $this->bbcode_cache[$bbcode_id] = array( - 'preg' => array( - '#\[url:$uid\]((.*?))\[/url:$uid\]#s' => $this->bbcode_tpl('url', $bbcode_id), - '#\[url=([^\[]+?):$uid\](.*?)\[/url:$uid\]#s' => $this->bbcode_tpl('url', $bbcode_id), - ) - ); - break; - - case 4: - if (phpbb::$user->optionget('viewimg')) - { - $this->bbcode_cache[$bbcode_id] = array( - 'preg' => array( - '#\[img:$uid\](.*?)\[/img:$uid\]#s' => $this->bbcode_tpl('img', $bbcode_id), - ) - ); - } - else - { - $this->bbcode_cache[$bbcode_id] = array( - 'preg' => array( - '#\[img:$uid\](.*?)\[/img:$uid\]#s' => str_replace('$2', '[ img ]', $this->bbcode_tpl('url', $bbcode_id, true)), - ) - ); - } - break; - - case 5: - $this->bbcode_cache[$bbcode_id] = array( - 'preg' => array( - '#\[size=([\-\+]?\d+):$uid\](.*?)\[/size:$uid\]#s' => $this->bbcode_tpl('size', $bbcode_id), - ) - ); - break; - - case 6: - $this->bbcode_cache[$bbcode_id] = array( - 'preg' => array( - '!\[color=(#[0-9a-f]{6}|[a-z\-]+):$uid\](.*?)\[/color:$uid\]!is' => $this->bbcode_tpl('color', $bbcode_id), - ) - ); - break; - - case 7: - $this->bbcode_cache[$bbcode_id] = array( - 'str' => array( - '[u:$uid]' => $this->bbcode_tpl('u_open', $bbcode_id), - '[/u:$uid]' => $this->bbcode_tpl('u_close', $bbcode_id), - ) - ); - break; - - case 8: - $this->bbcode_cache[$bbcode_id] = array( - 'preg' => array( - '#\[code(?:=([a-z]+))?:$uid\](.*?)\[/code:$uid\]#ise' => "\$this->bbcode_second_pass_code('\$1', '\$2')", - ) - ); - break; - - case 9: - $this->bbcode_cache[$bbcode_id] = array( - 'preg' => array( - '#(\[\/?(list|\*):[mou]?:?$uid\])[\n]{1}#' => "\$1", - '#(\[list=([^\[]+):$uid\])[\n]{1}#' => "\$1", - '#\[list=([^\[]+):$uid\]#e' => "\$this->bbcode_list('\$1')", - ), - 'str' => array( - '[list:$uid]' => $this->bbcode_tpl('ulist_open_default', $bbcode_id), - '[/list:u:$uid]' => $this->bbcode_tpl('ulist_close', $bbcode_id), - '[/list:o:$uid]' => $this->bbcode_tpl('olist_close', $bbcode_id), - '[*:$uid]' => $this->bbcode_tpl('listitem', $bbcode_id), - '[/*:$uid]' => $this->bbcode_tpl('listitem_close', $bbcode_id), - '[/*:m:$uid]' => $this->bbcode_tpl('listitem_close', $bbcode_id) - ), - ); - break; - - case 10: - $this->bbcode_cache[$bbcode_id] = array( - 'preg' => array( - '#\[email:$uid\]((.*?))\[/email:$uid\]#is' => $this->bbcode_tpl('email', $bbcode_id), - '#\[email=([^\[]+):$uid\](.*?)\[/email:$uid\]#is' => $this->bbcode_tpl('email', $bbcode_id) - ) - ); - break; - - case 11: - if (phpbb::$user->optionget('viewflash')) - { - $this->bbcode_cache[$bbcode_id] = array( - 'preg' => array( - '#\[flash=([0-9]+),([0-9]+):$uid\](.*?)\[/flash:$uid\]#' => $this->bbcode_tpl('flash', $bbcode_id), - ) - ); - } - else - { - $this->bbcode_cache[$bbcode_id] = array( - 'preg' => array( - '#\[flash=([0-9]+),([0-9]+):$uid\](.*?)\[/flash:$uid\]#' => str_replace('$1', '$3', str_replace('$2', '[ flash ]', $this->bbcode_tpl('url', $bbcode_id, true))) - ) - ); - } - break; - - case 12: - $this->bbcode_cache[$bbcode_id] = array( - 'str' => array( - '[/attachment:$uid]' => $this->bbcode_tpl('inline_attachment_close', $bbcode_id) - ), - 'preg' => array( - '#\[attachment=([0-9]+):$uid\]#' => $this->bbcode_tpl('inline_attachment_open', $bbcode_id) - ) - ); - break; - - default: - if (isset($rowset[$bbcode_id])) - { - if ($this->template_bitfield->get($bbcode_id)) - { - // The bbcode requires a custom template to be loaded - if (!$bbcode_tpl = $this->bbcode_tpl($rowset[$bbcode_id]['bbcode_tag'], $bbcode_id)) - { - // For some reason, the required template seems not to be available, use the default template - $bbcode_tpl = (!empty($rowset[$bbcode_id]['second_pass_replace'])) ? $rowset[$bbcode_id]['second_pass_replace'] : $rowset[$bbcode_id]['bbcode_tpl']; - } - else - { - // In order to use templates with custom bbcodes we need - // to replace all {VARS} to corresponding backreferences - // Note that backreferences are numbered from bbcode_match - if (preg_match_all('/\{(URL|LOCAL_URL|EMAIL|TEXT|SIMPLETEXT|IDENTIFIER|COLOR|NUMBER)[0-9]*\}/', $rowset[$bbcode_id]['bbcode_match'], $m)) - { - foreach ($m[0] as $i => $tok) - { - $bbcode_tpl = str_replace($tok, '$' . ($i + 1), $bbcode_tpl); - } - } - } - } - else - { - // Default template - $bbcode_tpl = (!empty($rowset[$bbcode_id]['second_pass_replace'])) ? $rowset[$bbcode_id]['second_pass_replace'] : $rowset[$bbcode_id]['bbcode_tpl']; - } - - // Replace {L_*} lang strings - $bbcode_tpl = preg_replace('/{L_([A-Z_]+)}/e', "phpbb::\$user->lang('\$1')", $bbcode_tpl); - - if (!empty($rowset[$bbcode_id]['second_pass_replace'])) - { - // The custom BBCode requires second-pass pattern replacements - $this->bbcode_cache[$bbcode_id] = array( - 'preg' => array($rowset[$bbcode_id]['second_pass_match'] => $bbcode_tpl) - ); - } - else - { - $this->bbcode_cache[$bbcode_id] = array( - 'str' => array($rowset[$bbcode_id]['second_pass_match'] => $bbcode_tpl) - ); - } - } - else - { - $this->bbcode_cache[$bbcode_id] = false; - } - break; - } - } - } - - /** - * Return bbcode template - */ - function bbcode_tpl($tpl_name, $bbcode_id = -1, $skip_bitfield_check = false) - { - static $bbcode_hardtpl = array(); - if (empty($bbcode_hardtpl)) - { - $bbcode_hardtpl = array( - 'b_open' => '<span style="font-weight: bold">', - 'b_close' => '</span>', - 'i_open' => '<span style="font-style: italic">', - 'i_close' => '</span>', - 'u_open' => '<span style="text-decoration: underline">', - 'u_close' => '</span>', - 'img' => '<img src="$1" alt="' . phpbb::$user->lang['IMAGE'] . '" />', - 'size' => '<span style="font-size: $1%; line-height: normal">$2</span>', - 'color' => '<span style="color: $1">$2</span>', - 'email' => '<a href="mailto:$1">$2</a>' - ); - } - - if ($bbcode_id != -1 && !$skip_bitfield_check && !$this->template_bitfield->get($bbcode_id)) - { - return (isset($bbcode_hardtpl[$tpl_name])) ? $bbcode_hardtpl[$tpl_name] : false; - } - - if (empty($this->bbcode_template)) - { - if (($tpl = file_get_contents($this->template_filename)) === false) - { - trigger_error('Could not load bbcode template', E_USER_ERROR); - } - - // replace \ with \\ and then ' with \'. - $tpl = str_replace('\\', '\\\\', $tpl); - $tpl = str_replace("'", "\'", $tpl); - - // strip newlines and indent - $tpl = preg_replace("/\n[\n\r\s\t]*/", '', $tpl); - - // Turn template blocks into PHP assignment statements for the values of $bbcode_tpl.. - $this->bbcode_template = array(); - - $matches = preg_match_all('#<!-- BEGIN (.*?) -->(.*?)<!-- END (?:.*?) -->#', $tpl, $match); - - for ($i = 0; $i < $matches; $i++) - { - if (empty($match[1][$i])) - { - continue; - } - - $this->bbcode_template[$match[1][$i]] = $this->bbcode_tpl_replace($match[1][$i], $match[2][$i]); - } - } - - return (isset($this->bbcode_template[$tpl_name])) ? $this->bbcode_template[$tpl_name] : ((isset($bbcode_hardtpl[$tpl_name])) ? $bbcode_hardtpl[$tpl_name] : false); - } - - /** - * Return bbcode template replacement - */ - function bbcode_tpl_replace($tpl_name, $tpl) - { - static $replacements = array( - 'quote_username_open' => array('{USERNAME}' => '$1'), - 'color' => array('{COLOR}' => '$1', '{TEXT}' => '$2'), - 'size' => array('{SIZE}' => '$1', '{TEXT}' => '$2'), - 'img' => array('{URL}' => '$1'), - 'flash' => array('{WIDTH}' => '$1', '{HEIGHT}' => '$2', '{URL}' => '$3'), - 'url' => array('{URL}' => '$1', '{DESCRIPTION}' => '$2'), - 'email' => array('{EMAIL}' => '$1', '{DESCRIPTION}' => '$2') - ); - - $tpl = preg_replace('/{L_([A-Z_]+)}/e', "phpbb::\$user->lang('\$1')", $tpl); - - if (!empty($replacements[$tpl_name])) - { - $tpl = strtr($tpl, $replacements[$tpl_name]); - } - - return trim($tpl); - } - - /** - * Second parse list bbcode - */ - function bbcode_list($type) - { - if ($type == '') - { - $tpl = 'ulist_open_default'; - $type = 'default'; - } - else if ($type == 'i') - { - $tpl = 'olist_open'; - $type = 'lower-roman'; - } - else if ($type == 'I') - { - $tpl = 'olist_open'; - $type = 'upper-roman'; - } - else if (preg_match('#^(disc|circle|square)$#i', $type)) - { - $tpl = 'ulist_open'; - $type = strtolower($type); - } - else if (preg_match('#^[a-z]$#', $type)) - { - $tpl = 'olist_open'; - $type = 'lower-alpha'; - } - else if (preg_match('#[A-Z]#', $type)) - { - $tpl = 'olist_open'; - $type = 'upper-alpha'; - } - else if (is_numeric($type)) - { - $tpl = 'olist_open'; - $type = 'decimal'; - } - else - { - $tpl = 'olist_open'; - $type = 'decimal'; - } - - return str_replace('{LIST_TYPE}', $type, $this->bbcode_tpl($tpl)); - } - - /** - * Second parse quote tag - */ - function bbcode_second_pass_quote($username, $quote) - { - // when using the /e modifier, preg_replace slashes double-quotes but does not - // seem to slash anything else - $quote = str_replace('\"', '"', $quote); - $username = str_replace('\"', '"', $username); - - // remove newline at the beginning - if ($quote == "\n") - { - $quote = ''; - } - - $quote = (($username) ? str_replace('$1', $username, $this->bbcode_tpl('quote_username_open')) : $this->bbcode_tpl('quote_open')) . $quote; - - return $quote; - } - - /** - * Second parse code tag - */ - function bbcode_second_pass_code($type, $code) - { - // when using the /e modifier, preg_replace slashes double-quotes but does not - // seem to slash anything else - $code = str_replace('\"', '"', $code); - - switch ($type) - { - case 'php': - // Not the english way, but valid because of hardcoded syntax highlighting - if (strpos($code, '<span class="syntaxdefault"><br /></span>') === 0) - { - $code = substr($code, 41); - } - - // no break; - - default: - $code = str_replace("\t", ' ', $code); - $code = str_replace(' ', ' ', $code); - $code = str_replace(' ', ' ', $code); - - // remove newline at the beginning - if (!empty($code) && $code[0] == "\n") - { - $code = substr($code, 1); - } - break; - } - - $code = $this->bbcode_tpl('code_open') . $code . $this->bbcode_tpl('code_close'); - - return $code; - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/bbcode/bbcode_parser.php b/phpBB/includes/bbcode/bbcode_parser.php deleted file mode 100644 index 81151a2945..0000000000 --- a/phpBB/includes/bbcode/bbcode_parser.php +++ /dev/null @@ -1,241 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** - * The phpBB version of the BBCode parser - * - */ -class phpbb_bbcode_parser extends phpbb_bbcode_parser_base -{ - private $list_stack = array(); - protected $tags = array(); - - public function __construct() - { - $this->tags = array( - // The exact B BBcode from phpBB - 'b' => array( - 'replace' => '<span style="font-weight: bold">', - 'close' => '</span>', - 'attributes' => array(), - 'children' => array(true, 'quote' => true, 'code' => true, 'list' => true), - 'parents' => array(true), - ), - // The exact I BBcode from phpBB - 'i' => array( - 'replace' => '<span style="font-style: italic">', - 'close' => '</span>', - 'attributes' => array(), - 'children' => array(true, 'quote' => true, 'code' => true, 'list' => true), - 'parents' => array(true), - ), - // The exact U BBcode from phpBB - 'u' => array( - 'replace' => '<span style="text-decoration: underline">', - 'close' => '</span>', - 'attributes' => array(), - 'children' => array(true, 'quote' => true, 'code' => true, 'list' => true), - 'parents' => array(true), - ), - - // Quote tag attempt. - 'quote' => array( - 'replace' => '<div class="quotetitle">{_}</div><div class="quotecontent">', - 'close' => '</div>', - 'attributes' => array( - '_' => array( - 'replace' => '%s wrote:', - ), - ), - 'children' => array(true), - 'parents' => array(true), - ), - - // code tag (without the =php functionality) - 'code' => array( - 'replace' => '<div class="codetitle"><b>Code:</b></div><div class="codecontent">', - 'close' => '</div>', - 'attributes' => array(), - 'children' => array(false), - 'parents' => array(true), - ), - - // list tag - 'list' => array( - 'replace' => '', - 'replace_func' => array($this, 'list_open'), - 'close' => '', - 'close_func' => array($this, 'list_close'), - 'attributes' => array( - '_' => array( - 'replace' => '', - ), - ), - 'children' => array(false, 'li' => true), - 'parents' => array(true), - ), - - // The exact * tag from phpBB. "*" is not a valid tag name in this parser... introducing li from HTML! - 'li' => array( - 'replace' => '<li>', - 'close' => '</li>', - 'close_shadow' => true, - 'attributes' => array(), - 'children' => array(true, 'li' => true), - 'parents' => array(false, 'list' => true), - ), - - // Almost exact img tag from phpBB... - 'img' => array( - 'replace' => '<img alt="Image" src="', - 'close' => '" />', - 'attributes' => array( - '__' => array( - 'replace' => '%s', - ), - ), - 'children' => array(false), - 'parents' => array(true), - - ), - - 'url' => array( - 'replace' => '', - 'replace_func' => array($this, 'url_tag'), - 'close' => '</a>', - 'attributes' => array( - // The replace value is not important empty because the replace_func handles this. - '_' => array( - 'replace' => '', - ), - '__' => array( - 'replace' => '', - ), - ), - 'children' => array(false), - 'parents' => array(true), - - ), - - 'color' => array( - 'replace' => '<span style="color: {_}">', - 'close' => '</span>', - 'attributes' => array( - '_' => array( - 'replace' => '%s', - 'required' => true - ), - ), - 'children' => array(true, 'color' => true), - 'parents' => array(true), - ), - - 'size' => array( - 'replace' => '<span style="font-size: {_}px; line-height: normal">', - 'close' => '</span>', - 'attributes' => array( - '_' => array( - 'replace' => '%s', - 'required' => true - ), - ), - 'children' => array(true, 'size' => true), - 'parents' => array(true), - ), - - - // FLASH tag implementation attempt. - 'flash' => array( - 'replace' => '<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=7,0,19,0"{w}{h}> -<param name="movie" value="{m}" /> -<param name="quality" value="high" /> -<embed src="{m}" quality="high" pluginspage="http://www.macromedia.com/go/getflashplayer" type="application/x-shockwave-flash"{w}{h}> -</embed> -</object>', - 'close' => false, - 'attributes' => array( - 'm' => array( - 'replace' => '%s', - 'required' => true, - ), - 'w' => array( - 'replace' => ' width="%s"', - 'type_check' => 'ctype_digit', - ), - 'h' => array( - 'replace' => ' height="%s"', - 'type_check' => 'ctype_digit', - ), - ), - 'children' => array(false), - 'parents' => array(true), - ), - // The spoiler tag from area51.phpbb.com :p - 'spoiler' => array( - 'replace' => '<span class="quotetitle"><b>Spoiler:</b></span><span style="background-color:white;color:white;">', - 'close' => '</span>', - 'attributes' => array(), - 'children' => array(false), - 'parents' => array(true), - ), - // a noparse tag - 'noparse' => array( - 'replace' => '', - 'close' => '', - 'attributes' => array(), - 'children' => array(false), - 'parents' => array(true), - ), - ); - $this->smilies = array( - ':)' => '<img src="http://area51.phpbb.com/phpBB/images/smilies/icon_e_smile.gif" />', - ':(' => '<img src="http://area51.phpbb.com/phpBB/images/smilies/icon_e_sad.gif" />', - ); - -// $this->text_callback = 'strtoupper'; - parent::__construct(); - } - - - protected function url_tag(array $attributes = array(), array $definition = array()) - { - if (isset($attributes['_'])) - { - return '<a href="' . $attributes['_'] . '">'; - } - return '<a href="' . $attributes['__'] . '">'; - } - - protected function list_open(array $attributes = array(), array $definition = array()) - { - if (isset($attributes['_'])) - { - return '<ol style="list-style-type: ' . $attributes['_'] . '">'; - } - return '<ul>'; - } - - protected function list_close(array $attributes = array()) - { - if (isset($attributes['_'])) - { - return '</ol>'; - } - return '</ul>'; - } -} diff --git a/phpBB/includes/bbcode/bbcode_parser_base.php b/phpBB/includes/bbcode/bbcode_parser_base.php deleted file mode 100644 index af74f6c38e..0000000000 --- a/phpBB/includes/bbcode/bbcode_parser_base.php +++ /dev/null @@ -1,868 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - - -/** - * A stack based BBCode parser. - * - */ -abstract class phpbb_bbcode_parser_base -{ - /** - * Array holding the BBCode definitions. - * - * This is all the documentation you'll find! - * - * 'tagName' => array( // The tag name must start with a letter and can consist only of letters and numbers. - * 'replace' => 'The open tag is replaced with this. "{attribute}" - Will be replaced with an existing attribute.', - * // Optional - * 'replace_func' => 'function_name', // Open tag is replaced with the the value that this function returns. replace will not be used. The function will get the arguments given to the tag and the tag definition. It is your responsibility to validate the arguments. - * 'close' => 'The close tag is replaced by this. If set to bool(false) the tag won't need a closing tag.', - * // Optional - * 'close_shadow' => true, // If set, no closing tag will be needed, but the value close will be added as soon as the parent tag is closed or a tag which is not allowed in the tag is encountered. - * // Optional - * 'close_func' => 'function_name', // Close tag is replaced with the the value that this function returns. close will not be used. If close is set to bool this might not function as expected. - * 'attributes' => array( - * 'attributeName' => array( - * 'replace' => 'Attribute replacement. Use string defined in self::$attr_value_replace as a replacement for the attributes value', - * 'type_check' => 'function_name', // Optional. Function name to check if the value of the attribute is allowed. It must return bool or a corrected string. It must accept the attribute value string. - * 'required' => true, // Optional. The attribute must be set and not empty for the tag to be parsed. - * ), - * // ... - * ), - * 'children' => array( - * true, // true allows all tags to be a child of this tag except for the other tags in the array. false allows only the tags in the array. - * 'tag2' => true, - * // ... - * ), - * 'parents' => array(true), // Same as 'children'. - * // Optional - * 'content_func' => 'function_name', // Applies function to the contents of the tag and replaces it with the output. Used only when the tag does not allow children. It must return the replacement string and accept the input string. This is not like HTML... - * ), - * 'tag2' => array( - * // ... - * - * NOTE: Use "_" as the name of the attribute assigned to the tag itself. (eg. form the tag [tag="value"] "_" will hold "value") - * NOTE: Use "__" for the content of a tag without children. (eg. for [u]something[/u] "__" will hold "something") This is not like HTML... - * NOTE: The following special tags exist: "__url" (child), "__smiley" (child) and "__global" (parent). They are to be used in the child/parent allowed/disallowed lists. - * @var array - */ - protected $tags = array(); - - /** - * The smilies which are to be "parsed". - * - * Smilies are treated the same way as BBCodes (though BBcodes have precedence). - * Use "__smiley" to allow/disallow them in tags. Smileys can only be children. - * - * 'smiley' => 'replacement' - * - * @var array - */ - protected $smilies = array(); - - /** - * Callback to be applied to all text nodes (in second_pass). - * - * @var mixed - */ - protected $text_callback = null; - - /** - * Used by first_pass and second_pass - * - * @var array - */ - private $stack = array(); - - /** - * Regex to match BBCode tags. - * - * @var string - */ - private $tag_regex = '\[(/?)([a-z][a-z0-9]*)(?:=(\'[^\']*\'|"[^"]*"))?((?: [a-z]+(?:\s?=\s?(?:\'[^\']*\'|"[^"]*"))?)*)\]'; - - /** - * Regex for URL's - * - * @var string - */ - private $url_regex = '(?>([a-z+]{2,}://|www\.))(?:[a-z0-9]+(?:\.[a-z0-9]+)?@)?(?:(?:[a-z](?:[a-z0-9]|(?<!-)-)*[a-z0-9])(?:\.[a-z](?:[a-z0-9]|(?<!-)-)*[a-z0-9])+|(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?))(?:/[^\\/:?*"<>|\n]*[a-z0-9])*/?(?:\?[a-z0-9_.%]+(?:=[a-z0-9_.%:/+-]*)?(?:&[a-z0-9_.%]+(?:=[a-z0-9_.%:/+-]*)?)*)?(?:#[a-z0-9_%.]+)?'; - - /** - * Regex to match attribute&value pairs. - * - * @var string - */ - private $attribute_regex = '~([a-z]+)(?:\s?=\s?((?:\'[^\']*?\'|"[^"]*?")))?~i'; - - /** - * Delimiter's ASCII code. - * - * @var int - */ - private $delimiter = 0; - - /** - * This string will be replaced by the attribute value. - * - * @var string - */ - private $attr_value_replace = '%s'; - - /** - * First pass result. - * - * @var array - */ - private $parsed = array(); - private $parse_pos = 1; - - /** - * Parse flags - * - * @var int - */ - protected $flags; - - /** - * Types - */ - const TYPE_TAG = 1; - const TYPE_TAG_SIMPLE = 2; - const TYPE_CTAG = 3; - const TYPE_ABSTRACT_SMILEY = 4; - const TYPE_ABSTRACT_URL = 5; - - /** - * Feature flags - */ - const PARSE_BBCODE = 1; - const PARSE_URLS = 2; - const PARSE_SMILIES = 4; - - /** - * Tag Backreferences. - * - */ - const MATCH_CLOSING_TAG = 1; - const MATCH_TAG_NAME = 2; - const MATCH_SHORT_ARG = 3; - const MATCH_ARGS = 4; - - /** - * Argument backreferences - * - */ - const MATCH_ARG_NAME = 1; - const MATCH_ARG_VALUE = 2; - - /** - * Constructor. - * - */ - public function __construct() - { - $this->delimiter = chr($this->delimiter); - $this->flags = self::PARSE_BBCODE | self::PARSE_URLS | self::PARSE_SMILIES; - } - - /** - * Returns a string ready for storage and/or second_pass - * - * @param string $string - * @return string - */ - public function first_pass($string) - { - $this->stack = array(); - $this->parsed = array(); - $this->parse_pos = 1; - - // Remove the delimiter from the string. - $string = str_replace($this->delimiter, '', $string); - - $smilies = implode('|',array_map(array($this, 'regex_quote'), array_keys($this->smilies))); - - // Make a regex out of the following items: - $regex_parts = array( - $this->tag_regex, - $this->url_regex, - $smilies, - ); - - $regex = '~' . implode('|', $regex_parts) . '~i'; - - // Do most of the job here... - $string = preg_replace_callback($regex, array($this, 'first_pass_tag_check'), $string); - - // Close all remaining open tags. - if (sizeof($this->stack) > 0) - { - $string .= $this->close_tags($this->stack); - $this->stack = array(); - } - - // Make a serialized array out of it. - $string = explode($this->delimiter, $string); - - if (sizeof($string) > 1) - { - $parsed = array(); - - $this->parse_pos = 0; - - end($this->parsed); - reset($string); - foreach ($this->parsed as $key => $val) - { - $parsed[key($string) * 2] = current($string); - $parsed[$key] = $val; - next($string); - } - - $this->parsed = array(); - $this->parse_pos = 1; - } - else - { - $parsed = $string; - } - - return serialize($parsed); - } - - /** - * Opposite function to first_pass. - * Changes the output of first_pass back to BBCode. - * - * @param string $string - * @return string - * @todo make sure this works after the change of first_pass data storage. - */ - public function first_pass_decompile($string) - { - $string = unserialize($string); - for ($i = 1, $n = sizeof($string); $i < $n; $i += 2) - { - $string[$i] = $this->decompile_tag($tag); - } - return implode('', $string); - } - - /** - * Removes first_pass data. This removes all BBCode tags. To reverse the effect of first_pass use first_pass_decompile - * - * @param string $string - * @return string - */ - public function remove_first_pass_data($string) - { - $decompiled = array(); - $compiled = unserialize($string); - for ($i = 0, $n = sizeof($compiled); $i < $n; $n += 2) - { - $decompiled[] = $compiled[$i]; - } - return implode('', $decompiled); - } - - /** - * The function takes the result of first_pass and returnes the string fully parsed. - * - * @param string $string - * @return string - */ - public function second_pass($string) - { - $this->stack = array(); - - $string = unserialize($string); - - if (!is_null($this->text_callback)) - { - for ($i = 0, $n = sizeof($string); $i < $n; $i += 2) - { - $string[$i] = call_user_func($this->text_callback, $string[$i]); - } - } - - for ($i = 1, $n = sizeof($string); $i < $n; $i += 2) - { - - $tag_data = $string[$i]; - $type = &$tag_data[0]; - $tag = $tag_data[1]; - $tag_definition = &$this->tags[$tag]; - - if ($this->flags & self::PARSE_BBCODE && $type != self::TYPE_ABSTRACT_URL && $type != self::TYPE_ABSTRACT_SMILEY && $type != self::TYPE_CTAG) - { - // These apply to opening tags and tags without closing tags. - - // Is the tag still allowed as a child? - // This is still needed! - if (sizeof($this->stack) && isset($this->tags[$this->stack[0]['name']]['close_shadow']) && !is_bool($this->tags[$this->stack[0]['name']]['close']) && !$this->child_allowed($tag)) - { - // The previous string won't be edited anymore. - $string[$i - 1] .= $this->tags[$this->stack[0]['name']]['close']; - array_shift($this->stack); - } - - // Add tag to stack only if it needs a closing tag. - if ($tag_definition['close'] !== false || !isset($tag_definition['close_shadow'])) - { - array_unshift($this->stack, array('name' => $tag, 'attributes' => array())); - } - } - - switch ($type) - { - case self::TYPE_ABSTRACT_URL: - - if ($this->flags & self::PARSE_URLS && $this->child_allowed('__url')) - { - $string[$i] = '<a href="' . $tag_data[1] . '">' . $tag_data[1] . '</a>'; - } - else - { - $string[$i] = $tag_data[1]; - } - - break; - - case self::TYPE_ABSTRACT_SMILEY: - - if ($this->flags & self::PARSE_SMILIES && $this->child_allowed('__smiley')) - { - $string[$i] = $this->smilies[$tag_data[1]]; - } - else - { - $string[$i] = $tag_data[1]; - } - - break; - - case self::TYPE_CTAG: - - if (($this->flags & self::PARSE_BBCODE) == 0) - { - $string[$i] = $this->decompile_tag($string[$i]); - break; - } - - // It must be the last one as tag nesting was checked in the first pass. - // An exception to this rule was created with adding the new type of tag without closing tag. - if (isset($this->tags[$this->stack[0]['name']]['close_shadow'])) - { - if (!is_bool($this->tags[$this->stack[0]['name']]['close'])) - { - // the previous string won't be edited anymore. - $string[$i - 1] .= $this->tags[$this->stack[0]['name']]['close']; - } - else if (isset($tag_definition['close_func'])) - { - $string[$i - 1] .= call_user_func($tag_definition['close_func'], $this->stack[0]['attributes']); - } - array_shift($this->stack); - } - - if ($tag != $this->stack[0]['name']) - { - $string[$i] = $this->decompile_tag('/' . $tag); - } - else if (isset($tag_definition['close_shadow'])) - { - $string[$i] = ''; - } - else if ($tag_definition['close'] !== false || !isset($tag_definition['close_shadow'])) - { - if (isset($tag_definition['close_func'])) - { - $string[$i] = call_user_func($tag_definition['close_func'], $this->stack[0]['attributes']); - } - else - { - $string[$i] = $tag_definition['close']; - } - array_shift($this->stack); - } - else - { - $string[$i] = ''; - } - - break; - - case self::TYPE_TAG_SIMPLE: - - if (($this->flags & self::PARSE_BBCODE) == 0) - { - $string[$i] = $this->decompile_tag($string[$i]); - break; - } - - if ($tag_definition['children'][0] == false && sizeof($tag_definition['children']) == 1) - { - if (isset($tag_definition['attributes']['__'])) - { - $this->stack[0]['attributes'] = array('__' => $string[$i + 1]); - if (isset($tag_definition['replace_func'])) - { - $string[$i] = call_user_func($tag_definition['replace_func'], array('__' => $string[$i + 1]), $tag_definition); - } - else - { - $string[$i] = str_replace('{__}', $string[$i + 1], $tag_definition['replace']); - } - } - else if (isset($tag_definition['replace_func'])) - { - $string[$i] = call_user_func($tag_definition['replace_func'], array(), $tag_definition); - } - else - { - $string[$i] = $tag_definition['replace']; - } - - if (isset($this->tags[$tag]['content_func'])) - { - $string[$i + 1] = call_user_func($tag_definition['content_func'], $string[$i + 1]); - } - } - else - { - if (isset($tag_definition['replace_func'])) - { - $string[$i] = call_user_func($tag_definition['replace_func'], array(), $tag_definition); - } - else - { - $string[$i] = $tag_definition['replace']; - } - } - - if (sizeof($tag_definition['attributes']) > 0) - { - // The tag has defined attributes but doesn't use any. The attribute replacements must be removed. I don't want this regex here. - $string[$i] = preg_replace('/{[^}]*}/', '', $string[$i]); - } - - break; - - case self::TYPE_TAG: - - if (($this->flags & self::PARSE_BBCODE) == 0) - { - $string[$i] = $this->decompile_tag($string[$i]); - break; - } - - // These apply to tags with attributes. - if (!isset($tag_data[2])) - { - $tag_data[2] = array('__' => $string[$i + 1]); - } - $this->stack[0]['attributes'] = $tag_data[2]; - - // Handle the (opening) tag with a custom function - if (isset($tag_definition['replace_func'])) - { - - $string[$i] = call_user_func($tag_definition['replace_func'], $tag_data[2], $tag_definition); - - if (isset($tag_definition['content_func']) && $tag_definition['children'][0] === false && sizeof($tag_definition['children']) == 1) - { - $string[$i + 1] = call_user_func($tag_definition['content_func'], $string[$i + 1]); - } - break; - } - - // New code for the feature I've always wanted to implement :) - if (isset($tag_definition['attributes']['__']) && $tag_definition['children'][0] == false && sizeof($tag_definition['children']) == 1) - { - $attributes = array('{__}'); - $replacements = array($string[$i + 1]); - // End new code. - } - else - { - $attributes = array(); - $replacements = array(); - } - - foreach ($tag_definition['attributes'] as $attribute => $value) - { - $attributes[] = '{' . $attribute . '}'; - if (!isset($tag_data[2][$attribute])) - { - if (isset($value['required'])) - { - $string[$i] = $this->decompile_tag($tag_data); - break 2; - } - $replacements[] = ''; - continue; - } - - $replacements[] = str_replace($this->attr_value_replace, $tag_data[2][$attribute], $tag_definition['attributes'][$attribute]['replace']); - } - - - $string[$i] = str_replace($attributes, $replacements, $this->tags[$tag]['replace']); - - // It has to be twice... this should not be used if required attributes are missing. - if (isset($tag_definition['content_func']) && $tag_definition['children'][0] === false && sizeof($tag_definition['children']) == 1) - { - $string[$i + 1] = call_user_func($tag_definition['content_func'], $string[$i + 1]); - } - - break; - } - } - - return implode($string); - } - - /** - * Callback for preg_replace_callback in first_pass. - * - * @param array $matches - * @return string - */ - private function first_pass_tag_check($matches) - { - switch (sizeof($matches)) - { - // Smilies - case 1: - - $this->parsed[$this->parse_pos] = array(self::TYPE_ABSTRACT_SMILEY, $matches[0]); - $this->parse_pos += 2; - return $this->delimiter; - - break; - - // URL - case 6: - - $this->parsed[$this->parse_pos] = array(self::TYPE_ABSTRACT_URL, $matches[0]); - $this->parse_pos += 2; - return $this->delimiter; - - break; - - default: - - if (!isset($this->tags[$matches[self::MATCH_TAG_NAME]])) - { - // Tag with the given name not defined. - return $matches[0]; - } - - // If tag is an opening tag. - if (strlen($matches[self::MATCH_CLOSING_TAG]) == 0) - { - if (sizeof($this->stack)) - { - if ($this->tags[$this->stack[0]]['children'][0] == false && sizeof($this->tags[$this->stack[0]]['children']) == 1) - { - // Tag does not allow children. - return $matches[0]; - } - // Tag parent not allowed for this tag. Omit here. - else if (!$this->parent_allowed($matches[self::MATCH_TAG_NAME], $this->stack[0])) - { - if (isset($this->tags[$this->stack[0]]['close_shadow'])) - { - array_shift($this->stack); - } - else - { - return $matches[0]; - } - } - } - // Is tag allowed in global scope? - else if (!$this->parent_allowed($matches[self::MATCH_TAG_NAME], '__global')) - { - return $matches[0]; - } - - if ($this->tags[$matches[self::MATCH_TAG_NAME]]['close'] !== false || !isset($this->tags[$matches[self::MATCH_TAG_NAME]]['close_shadow'])) - { - // Do not add tags to stack that do not need closing tags. - array_unshift($this->stack, $matches[self::MATCH_TAG_NAME]); - } - - $tag_attributes = &$this->tags[$matches[self::MATCH_TAG_NAME]]['attributes']; - - if (strlen($matches[self::MATCH_SHORT_ARG]) != 0 && isset($tag_attributes['_'])) - { - // Add short attribute. - $attributes = array('_' => substr($matches[self::MATCH_SHORT_ARG], 1, -1)); - } - else if (strlen($matches[4]) == 0 || (sizeof($tag_attributes)) == 0) - { - // Check all attributes, which were not used, if they are required. - if ($this->has_required($matches[self::MATCH_TAG_NAME], array_keys($tag_attributes))) - { - // Not all required attributes were used. - return $matches[0]; - } - else - { - $this->parsed[$this->parse_pos] = array(self::TYPE_TAG_SIMPLE, $matches[self::MATCH_TAG_NAME]); - if (isset($attributes)) - { - $this->parsed[$this->parse_pos][] = $attributes; - } - $this->parse_pos += 2; - return $this->delimiter; - } - } - else - { - $attributes = array(); - } - - // Analyzer... - $matched_attrs = array(); - - preg_match_all($this->attribute_regex, $matches[self::MATCH_ARGS], $matched_attrs, PREG_SET_ORDER); - - foreach($matched_attrs as $i => $value) - { - $tag_attribs_matched = &$tag_attributes[$value[self::MATCH_ARG_NAME]]; - if (isset($attributes[$value[self::MATCH_ARG_NAME]])) - { - // This prevents adding the same attribute more than once. Childish betatesters are needed. - continue; - } - if (isset($tag_attribs_matched)) - { - // The attribute exists within the defined tag. Undefined tags are removed. - - $attr_value = substr($value[self::MATCH_ARG_VALUE], 1, -1); - - if (isset($tag_attribs_matched['type_check'])) - { - // A type check is needed for this attribute. - - $type_check = $tag_attribs_matched['type_check']($attr_value); - - if (!is_bool($type_check)) - { - // The type check function decided to fix the input instead of returning false. - $attr_value = $type_check; - } - else if ($type_check === false) - { - // Type check has failed. - continue; - } - } - if (isset($tag_attribs_matched['required']) && strlen($attr_value) == 0) - { - // A required attribute is empty. This is done after the type check as the type check may return an empty value. - return $matches[0]; - } - $attributes[$value[self::MATCH_ARG_NAME]] = $attr_value; - } - } - - // Check all attributes, which were not used, if they are required. - if ($this->has_required($matches[self::MATCH_TAG_NAME], array_values(array_diff(array_keys($tag_attributes), array_keys($attributes))))) - { - // Not all required attributes were used. - return $matches[0]; - } - - if (sizeof($attributes)) - { - $this->parsed[$this->parse_pos] = array(self::TYPE_TAG, $matches[self::MATCH_TAG_NAME], $attributes); - $this->parse_pos += 2; - return $this->delimiter; - } - - $this->parsed[$this->parse_pos] = array(self::TYPE_TAG_SIMPLE, $matches[self::MATCH_TAG_NAME]); - $this->parse_pos += 2; - return $this->delimiter; - } - // If tag is a closing tag. - - - $valid = array_search($matches[self::MATCH_TAG_NAME], $this->stack); - - if ($valid === false) - { - // Closing tag without open tag. - return $matches[0]; - } - else if ($valid != 0) - { - if ($this->tags[$this->stack[0]]['children'][0] == false && sizeof($this->tags[$this->stack[0]]['children']) == 1) - { - // Tag does not allow children. - // Do not handle other closing tags here as they are invalid in tags which do not allow children. - return $matches[0]; - } - // Now we have to close all tags that were opened before this closing tag. - // We know that this tag does not close the last opened tag. - $to_close = array_splice($this->stack, 0, $valid + 1); - return $this->close_tags($to_close); - } - else - { - // A unset() was elicting many notices here. - array_shift($this->stack); - $this->parsed[$this->parse_pos] = array(self::TYPE_CTAG, $matches[self::MATCH_TAG_NAME]); - $this->parse_pos += 2; - return $this->delimiter; - } - - break; - } - } - - /** - * Returns closing tags for all tags in the $tags array (in reverse order). - * - * @param array $tags - * @return string - */ - private function close_tags($tags) - { - $ret = ''; - foreach($tags as $tag) - { - // @todo: Is this needed? - if (!isset($this->tags[$tag]['close_shadow'])) - { - $this->parsed[$this->parse_pos] = array(self::TYPE_CTAG, $tag); - $this->parse_pos += 2; - $ret .= $this->delimiter; - } - } - return $ret; - } - - /** - * Returns the tag to the form it had before the first_pass - * - * @param array $tag - * @return string - */ - private function decompile_tag(array $tag) - { - $ret = '[' . (($tag[0]) ? '' : '/'); - $ret .= $tag[1]; - - if(isset($tag[2])) - { - if (isset($tag[2]['_'])) - { - $ret .= '="' . $tag[2]['_'] . '"'; - unset($tag[2]['_']); - } - - foreach ($tag[2] as $attribute => $value) - { - $ret .= ' ' . $attribute . '="' . $value . '"'; - } - } - $ret .= ']'; - - return $ret; - } - - /** - * Checks if $tag can be a child of the tag in stack index $index - * - * @param string $tag - * @param int $index = 0 - * @return bool - */ - private function child_allowed($tag, $index = 0) - { - if (!isset($this->stack[$index])) - { - return true; - } - // I assume this trick is usefull starting form two. - $children = &$this->tags[$this->stack[$index]['name']]['children']; - if (isset($children[$tag]) xor $children[0]) - { - return true; - } - else - { - return false; - } - } - - /** - * Checks if the $tag can be a child of $parent - * - * @param string $tag - * @param string $parent - * @return bool - */ - private function parent_allowed($tag, $parent) - { - $parents = &$this->tags[$tag]['parents']; - if (isset($parents[$parent]) xor $parents[0]) - { - return true; - } - else - { - return false; - } - } - - /** - * Checks if any of $tag's attributes in $attributes are required. - * - * @param string $tag - * @param string $attributes - * @return bool - */ - private function has_required($tag, $attributes) - { - for ($i = 0, $n = sizeof($attributes); $i < $n; ++$i) - { - if (isset($this->tags[$tag]['attributes'][$attributes[$i]]['required'])) - { - return true; - } - } - - return false; - } - - private function regex_quote($var) - { - return preg_quote($var, '~'); - } - - public function set_flags($flags) - { - $this->flags = (int) $flags; - } -} diff --git a/phpBB/includes/captcha/captcha_factory.php b/phpBB/includes/captcha/captcha_factory.php deleted file mode 100644 index 0f16e137ec..0000000000 --- a/phpBB/includes/captcha/captcha_factory.php +++ /dev/null @@ -1,95 +0,0 @@ -<?php -/** -* -* @package VC -* @version $Id: $ -* @copyright (c) 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -if (!interface_exists('phpbb_captcha_plugin')) -{ - include(PHPBB_ROOT_PATH . 'includes/captcha/captcha_plugin.' . PHP_EXT); -} - -/** -* A small class until we get the autoloader done -*/ -class phpbb_captcha_factory -{ - /** - * return an instance of class $name in file $name_plugin.php - */ - public static function get_instance($name) - { - $name = basename($name); - if (!class_exists($name)) - { - include(PHPBB_ROOT_PATH . "includes/captcha/plugins/{$name}_plugin." . PHP_EXT); - } - return call_user_func(array($name, 'get_instance')); - } - - /** - * Call the garbage collector - */ - public static function garbage_collect($name) - { - $name = basename($name); - if (!class_exists($name)) - { - include(PHPBB_ROOT_PATH . "includes/captcha/plugins/{$name}_plugin." . PHP_EXT); - } - call_user_func(array($name, 'garbage_collect'), 0); - } - - /** - * return a list of all discovered CAPTCHA plugins - */ - public static function get_captcha_types() - { - $captchas = array( - 'available' => array(), - 'unavailable' => array(), - ); - - $dp = @opendir(PHPBB_ROOT_PATH . 'includes/captcha/plugins'); - - if ($dp) - { - while (($file = readdir($dp)) !== false) - { - if ((preg_match('#_plugin\.' . PHP_EXT . '$#', $file))) - { - $name = preg_replace('#^(.*?)_plugin\.' . PHP_EXT . '$#', '\1', $file); - if (!class_exists($name)) - { - include(PHPBB_ROOT_PATH . "includes/captcha/plugins/$file"); - } - if (call_user_func(array($name, 'is_available'))) - { - $captchas['available'][$name] = call_user_func(array($name, 'get_name')); - } - else - { - $captchas['unavailable'][$name] = call_user_func(array($name, 'get_name')); - } - } - } - closedir($dp); - } - - return $captchas; - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/captcha/captcha_gd.php b/phpBB/includes/captcha/captcha_gd.php deleted file mode 100644 index 9db4bea46f..0000000000 --- a/phpBB/includes/captcha/captcha_gd.php +++ /dev/null @@ -1,2636 +0,0 @@ -<?php -/** -* -* @package VC -* @version $Id$ -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Original Author - Xore (Robert Hetzler) -* With contributions from Neothermic -* -* @package VC -*/ -class captcha -{ - const width = 360; - const height = 96; - - /** - * Create the image containing $code with a seed of $seed - */ - public static function execute($code, $seed) - { - srand($seed); - mt_srand($seed); - - // Create image - $img = imagecreatetruecolor(self::width, self::height); - - // Generate colours - $colour = new colour_manager($img, array( - 'random' => true, - 'min_value' => 60, - ), 'hsv'); - - $scheme = $colour->colour_scheme('background', false); - $scheme = $colour->mono_range($scheme, 10, false); - shuffle($scheme); - - $bg_colours = array_splice($scheme, mt_rand(6, 12)); - - // Generate code characters - $characters = $sizes = $bounding_boxes = $noise = array(); - $width_avail = self::width - 15; - $code_len = strlen($code); - - $captcha_bitmaps = self::captcha_bitmaps(); - for ($i = 0; $i < $code_len; ++$i) - { - $characters[$i] = new char_cube3d($captcha_bitmaps, $code[$i]); - - list($min, $max) = char_cube3d::range(); - $sizes[$i] = mt_rand($min, $max); - - $box = $characters[$i]->dimensions($sizes[$i]); - $width_avail -= ($box[2] - $box[0]); - $bounding_boxes[$i] = $box; - } - - - // Redistribute leftover x-space - $offset = array(); - for ($i = 0; $i < $code_len; ++$i) - { - $denom = ($code_len - $i); - $denom = max(1.3, $denom); - $offset[$i] = mt_rand(0, (1.5 * $width_avail) / $denom); - $width_avail -= $offset[$i]; - } - - if (phpbb::$config['captcha_gd_x_grid']) - { - $grid = (int) phpbb::$config['captcha_gd_x_grid']; - for ($y = 0; $y < self::height; $y += mt_rand($grid - 2, $grid + 2)) - { - $current_colour = $scheme[array_rand($scheme)]; - imageline($img, mt_rand(0,4), mt_rand($y - 3, $y), mt_rand(self::width - 5, self::width), mt_rand($y - 3, $y), $current_colour); - } - } - - if (phpbb::$config['captcha_gd_y_grid']) - { - $grid = (int) phpbb::$config['captcha_gd_y_grid']; - for ($x = 0; $x < self::width; $x += mt_rand($grid - 2, $grid + 2)) - { - $current_colour = $scheme[array_rand($scheme)]; - imagedashedline($img, mt_rand($x -3, $x + 3), mt_rand(0, 4), mt_rand($x -3, $x + 3), mt_rand(self::height - 5, self::height), $current_colour); - } - } - - if (phpbb::$config['captcha_gd_wave'] && (phpbb::$config['captcha_gd_y_grid'] || phpbb::$config['captcha_gd_y_grid'])) - { - self::wave($img); - } - - if (phpbb::$config['captcha_gd_3d_noise']) - { - $xoffset = rand(0,9); - $noise_bitmaps = self::captcha_noise_bg_bitmaps(); - for ($i = 0; $i < $code_len; ++$i) - { - $noise[$i] = new char_cube3d($noise_bitmaps, mt_rand(1, count($noise_bitmaps['data']))); - - list($min, $max) = $noise[$i]->range(); - //$box = $noise[$i]->dimensions($sizes[$i]); - } - $xoffset = 0; - for ($i = 0; $i < $code_len; ++$i) - { - $dimm = $bounding_boxes[$i]; - $xoffset += ($offset[$i] - $dimm[0]); - $yoffset = mt_rand(-$dimm[1], self::height - $dimm[3]); - - $noise[$i]->drawchar($sizes[$i], $xoffset, $yoffset, $img, $colour->get_resource('background'), $scheme); - $xoffset += $dimm[2]; - } - } - $xoffset = 5; - for ($i = 0; $i < $code_len; ++$i) - { - $dimm = $bounding_boxes[$i]; - $xoffset += ($offset[$i] - $dimm[0]); - $yoffset = mt_rand(-$dimm[1], self::height - $dimm[3]); - - $characters[$i]->drawchar($sizes[$i], $xoffset, $yoffset, $img, $colour->get_resource('background'), $scheme); - $xoffset += $dimm[2]; - } - - if (phpbb::$config['captcha_gd_wave']) - { - self::wave($img); - } - - if (phpbb::$config['captcha_gd_foreground_noise']) - { - self::noise_line($img, 0, 0, self::width, self::height, $colour->get_resource('background'), $scheme, $bg_colours); - } - // Send image - header('Content-Type: image/png'); - header('Cache-control: no-cache, no-store'); - imagepng($img); - imagedestroy($img); - } - - /** - * Sinus - */ - private static function wave($img) - { - $period_x = mt_rand(12,18); - $period_y = mt_rand(7,14); - $amp_x = mt_rand(5,10); - $amp_y = mt_rand(2,4); - $socket = mt_rand(0,100); - - $dampen_x = mt_rand(self::width/5, self::width/2); - $dampen_y = mt_rand(self::height/5, self::height/2); - $direction_x = (mt_rand (0, 1)); - $direction_y = (mt_rand (0, 1)); - - for ($i = 0; $i < self::width; $i++) - { - $dir = ($direction_x) ? $i : (self::width - $i); - imagecopy($img, $img, $i-1, sin($socket+ $i/($period_x + $dir/$dampen_x)) * $amp_x, $i, 0, 1, self::height); - } - $socket = mt_rand(0,100); - for ($i = 0; $i < self::height; $i++) - { - $dir = ($direction_y) ? $i : (self::height - $i); - imagecopy($img, $img ,sin($socket + $i/($period_y + ($dir)/$dampen_y)) * $amp_y, $i-1, 0, $i, self::width, 1); - } - return $img; - } - - /** - * Noise line - */ - private static function noise_line($img, $min_x, $min_y, $max_x, $max_y, $bg, $font, $non_font) - { - imagesetthickness($img, 2); - - $x1 = $min_x; - $x2 = $max_x; - $y1 = $min_y; - $y2 = $min_y; - - do - { - $line = array_merge( - array_fill(0, mt_rand(30, 60), $non_font[array_rand($non_font)]), - array_fill(0, mt_rand(30, 60), $bg) - ); - - imagesetstyle($img, $line); - imageline($img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED); - - $y1 += mt_rand(12, 35); - $y2 += mt_rand(12, 35); - } - while ($y1 < $max_y && $y2 < $max_y); - - $x1 = $min_x; - $x2 = $min_x; - $y1 = $min_y; - $y2 = $max_y; - - do - { - $line = array_merge( - array_fill(0, mt_rand(30, 60), $non_font[array_rand($non_font)]), - array_fill(0, mt_rand(30, 60), $bg) - ); - - imagesetstyle($img, $line); - imageline($img, $x1, $y1, $x2, $y2, IMG_COLOR_STYLED); - - $x1 += mt_rand(20, 35); - $x2 += mt_rand(20, 35); - } - while ($x1 < $max_x && $x2 < $max_x); - imagesetthickness($img, 1); - } - - - function captcha_noise_bg_bitmaps() - { - return array( - 'width' => 15, - 'height' => 5, - 'data' => array( - - 1 => array( - array(1,0,0,0,1,0,0,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,1,0,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,1,0,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0,0,0,1,0,0,0), - ), - 2 => array( - array(1,1,mt_rand(0,1),1,0,1,1,1,1,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,1,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0,1,1,0,1,1,1), - ), - 3 => array( - array(1,0,0,0,0,0,0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0,0,0,0,0,1,0), - array(0,0,0,0,1,0,0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,0,0,0,0,0,0,1), - ), - 4 => array( - array(1,0,1,0,1,0,0,1,1,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,1,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(1,0,1,0,0,0,0,0,0,0,0,0,0,0,0), - ), - 5 => array( - array(1,1,1,1,0,0,0,1,1,1,0,0,1,0,1), - array(0,0,0,0,0,0,0,1,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(1,0,1,0,0,0,0,0,0,0,0,0,0,0,0), - ), - 6 => array( - array(mt_rand(0,1),mt_rand(0,1),mt_rand(0,1),mt_rand(0,1),mt_rand(0,1),0,mt_rand(0,1),mt_rand(0,1),mt_rand(0,1),mt_rand(0,1),mt_rand(0,1),0,mt_rand(0,1),mt_rand(0,1),mt_rand(0,1)), - array(0,0,0,0,0,0,0,mt_rand(0,1),0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(mt_rand(0,1),0,mt_rand(0,1),0,0,0,0,0,0,0,0,0,0,0,0), - ), - 7 => array( - array(0,0,0,0,0,0,0,0,0,0,1,1,0,1,1), - array(0,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - array(0,0,1,1,0,0,0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,1,0,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0,0,0,0,0,0,0), - ), - )); - } - - /** - * Return bitmaps - */ - private static function captcha_bitmaps() - { - $chars = array( - 'A' => array( - array( - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,1,1,1,1,1,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,1,1,0,1,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,1,1,1,1,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,0,0,0,1,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,1,1,1,1,1,0,0), - array(0,1,1,0,0,0,1,1,0), - array(1,1,0,0,0,0,0,1,1), - array(1,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,1), - array(0,0,0,0,0,1,1,1,1), - array(0,0,0,1,1,1,0,0,1), - array(0,1,1,1,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,1,0,0,0,0,1,1,1), - array(0,1,1,1,1,1,1,0,1), - ), - ), - 'B' => array( - array( - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - ), - array( - array(1,1,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - ), - array( - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,1,1,1,1,0,0), - ), - ), - 'C' => array( - array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - array( - array(0,0,1,1,1,1,1,0,1), - array(0,1,0,0,0,0,0,1,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,1), - array(0,0,1,1,1,1,1,0,1), - ), - ), - 'D' => array( - array( - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - ), - array( - array(1,1,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,1,1,1,1,1,0,1), - array(0,1,1,0,0,0,1,1,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,1,0,0,0,1,1,1), - array(0,0,1,1,1,1,1,0,1), - ), - ), - 'E' => array( - array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,1,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,1,1), - ), - array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,1), - array(1,1,1,1,1,1,1,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,1,1,1,1,1,0,0), - array(0,1,1,0,0,0,1,1,0), - array(1,1,0,0,0,0,0,1,1), - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,1), - array(1,1,0,0,0,0,0,1,1), - array(0,1,1,1,1,1,1,1,0), - ), - ), - 'F' => array( - array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - ), - array( - array(0,1,1,1,1,1,1,1,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(1,1,1,0,0,0,0,0,0), - ), - array( - array(0,0,0,1,1,0,0,0,0), - array(0,0,1,1,0,0,0,0,0), - array(0,1,1,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(1,1,1,1,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - ), - ), - 'G' => array( - array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,1,1,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - array( - array(0,0,1,1,1,1,1,0,1), - array(0,1,0,0,0,0,0,1,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,1,1,1,1,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,1), - array(0,0,1,1,1,1,1,0,1), - ), - array( - array(0,0,1,1,1,1,1,0,1), - array(0,1,1,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,1,1,0,0,0,0,0,1), - array(0,0,1,1,1,1,1,1,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,1), - array(1,1,1,1,1,1,1,1,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - ), - 'H' => array( - array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - ), - array( - array(1,1,1,0,0,0,1,1,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,1,1,1,1,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,0,0,0,1,1,1), - ), - array( - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,1,1,1,0,0,0), - array(1,1,1,1,0,1,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - ), - ), - 'I' => array( - array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(1,1,1,1,1,1,1,1,1), - ), - array( - array(0,0,0,1,1,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,1,1,0,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,1,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,1,1,0,0,0), - ), - ), - 'J' => array( - array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(0,1,0,0,1,0,0,0,0), - array(0,0,1,1,0,0,0,0,0), - ), - array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,1,0,0,1,0,0,0,0), - array(1,0,1,1,0,0,0,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(0,1,0,0,1,0,0,0,0), - array(0,0,1,1,0,0,0,0,0), - ), - ), - 'K' => array( - array( // New 'K', supplied by NeoThermic - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,1,0,0,0,0), - array(1,0,0,1,0,0,0,0,0), - array(1,0,1,0,0,0,0,0,0), - array(1,1,0,0,0,0,0,0,0), - array(1,0,1,0,0,0,0,0,0), - array(1,0,0,1,0,0,0,0,0), - array(1,0,0,0,1,0,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - ), - array( - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,1,0,0), - array(0,1,0,0,0,1,0,0,0), - array(0,1,0,0,1,0,0,0,0), - array(0,1,0,1,0,0,0,0,0), - array(0,1,1,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,1,0,0,0,0,0,0), - array(0,1,0,1,0,0,0,0,0), - array(0,1,0,0,1,0,0,0,0), - array(0,1,0,0,0,1,0,0,0), - array(0,1,0,0,0,0,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,0,0,0,1,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,1,0,0,0), - array(0,1,0,0,1,0,0,0,0), - array(0,1,0,1,0,0,0,0,0), - array(0,1,1,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,1,0,0,0,0,0,0), - array(0,1,0,1,0,0,0,0,0), - array(0,1,0,0,1,0,0,0,0), - array(0,1,0,0,0,1,0,0,0), - array(0,1,0,0,0,0,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - ), - ), - 'L' => array( - array( - array(0,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,1), - array(1,1,1,1,1,1,1,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,1,0,0,0,0,0,0), - array(0,0,1,1,1,0,0,0,0), - ), - ), - 'M' => array( - array( - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,0,0,0,1,1,0), - array(0,1,1,0,0,0,1,1,0), - array(0,1,1,0,0,0,1,1,0), - array(0,1,0,1,0,1,0,1,0), - array(0,1,0,1,0,1,0,1,0), - array(0,1,0,1,0,1,0,1,0), - array(0,1,0,0,1,0,0,1,0), - array(0,1,0,0,1,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,0,0,0,1,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,1,1,1,0,1,1,1,0), - array(1,1,0,1,1,1,0,1,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - ), - ), - 'N' => array( - array( - array(1,1,0,0,0,0,0,0,1), - array(1,1,0,0,0,0,0,0,1), - array(1,0,1,0,0,0,0,0,1), - array(1,0,1,0,0,0,0,0,1), - array(1,0,0,1,0,0,0,0,1), - array(1,0,0,1,0,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,0,1,0,0,1), - array(1,0,0,0,0,1,0,0,1), - array(1,0,0,0,0,0,1,0,1), - array(1,0,0,0,0,0,1,0,1), - array(1,0,0,0,0,0,0,1,1), - array(1,0,0,0,0,0,0,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,0,0,0,0,1,0), - array(0,1,1,0,0,0,0,1,0), - array(0,1,1,0,0,0,0,1,0), - array(0,1,0,1,0,0,0,1,0), - array(0,1,0,1,0,0,0,1,0), - array(0,1,0,1,0,0,0,1,0), - array(0,1,0,0,1,0,0,1,0), - array(0,1,0,0,1,1,0,1,0), - array(0,1,0,0,0,1,0,1,0), - array(0,1,0,0,0,1,1,1,0), - array(0,1,0,0,0,0,1,1,0), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,0,0,0,1,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(1,0,1,1,1,1,0,0,0), - array(1,1,1,0,0,1,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - ), - ), - 'O' => array( - array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,1,1,1,1,1,0,0,0), - array(1,1,1,0,0,1,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,1,0,0,0,1,1,0,0), - array(0,1,1,1,1,1,0,0,0), - ), - ), - 'P' => array( - array( - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - ), - array( - array(1,1,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(1,1,1,0,0,0,0,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,1,1,0,0,0,0,0), - array(1,1,0,1,1,0,0,0,0), - array(1,0,0,0,1,0,0,0,0), - array(1,0,0,0,1,0,0,0,0), - array(1,0,0,1,1,0,0,0,0), - array(1,1,1,1,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - ), - ), - 'Q' => array( - array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,1,0,0,1), - array(1,0,0,0,0,0,1,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,1), - ), - array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,1,0,0,1,1,0,1,1), - array(0,1,1,1,1,1,1,1,0), - array(0,0,0,0,0,0,1,1,0), - array(0,0,0,0,0,0,0,1,1), - array(0,0,0,0,0,0,0,0,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,1,1,1,1), - array(0,0,0,0,1,1,0,0,1), - array(0,0,0,0,1,0,0,0,1), - array(0,0,0,0,1,0,0,0,1), - array(0,0,0,0,1,1,0,1,1), - array(0,0,0,0,0,1,1,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - ), - ), - 'R' => array( - array( - array(1,1,1,1,1,1,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - array(1,1,1,0,0,0,0,0,0), - array(1,0,0,1,0,0,0,0,0), - array(1,0,0,0,1,0,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,0,1,0,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - ), - array( - array(1,1,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,0,0), - array(0,1,1,0,0,0,0,0,0), - array(0,1,1,1,0,0,0,0,0), - array(0,1,0,1,1,0,0,0,0), - array(0,1,0,0,1,1,0,0,0), - array(0,1,0,0,0,1,1,0,0), - array(0,1,0,0,0,0,1,1,0), - array(1,1,1,0,0,0,1,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,0,0,0,0), - array(1,1,0,0,1,1,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - ), - ), - 'S' => array( - array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,0,1,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - array( - array(0,0,1,1,1,1,1,0,1), - array(0,1,0,0,0,0,0,1,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,0,1,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,1,0,0,0,0,0,1,0), - array(1,0,1,1,1,1,1,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,1,1,1,1,0,0,0,0), - array(1,0,0,0,0,1,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,0,0,0,0,0,0,0), - array(0,1,1,1,1,0,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(1,0,0,0,1,1,0,0,0), - array(0,1,1,1,1,0,0,0,0), - ), - ), - 'T' => array( - array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - ), - array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,1,0,0,0,1), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,1,1,0,0,0), - ), - array( - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,1,1,1,1,1,1,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,1,0,0,0), - array(0,0,0,0,0,1,1,1,0), - ), - ), - 'U' => array( - array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - array( - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,0,0,0,1,1,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,0,0,0,1,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,1,0,0,0,0,0,1), - array(0,0,1,0,0,0,0,0,1), - array(0,0,1,0,0,0,0,0,1), - array(0,0,1,0,0,0,0,0,1), - array(0,0,1,0,0,0,0,0,1), - array(0,0,1,0,0,0,0,1,1), - array(0,0,1,1,0,0,1,1,1), - array(0,0,0,1,1,1,1,0,1), - ), - ), - 'V' => array( - array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(1,1,1,0,0,0,1,1,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - ), - ), - 'W' => array( - array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,0,1,0,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,0,1,0,1,0,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,0,1,0,0,0,1,0,1), - array(1,1,0,0,0,0,0,1,1), - array(1,1,0,0,0,0,0,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(1,1,1,0,0,0,1,1,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,1,0,0,1,0), - array(0,1,0,0,1,0,0,1,0), - array(0,1,0,1,1,1,0,1,0), - array(0,1,0,1,0,1,0,1,0), - array(0,1,1,1,0,1,1,1,0), - array(0,1,1,0,0,0,1,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,1,0,0,1,0), - array(0,1,0,0,1,0,0,1,0), - array(0,1,0,1,1,1,0,1,0), - array(0,1,0,1,0,1,0,1,0), - array(0,1,1,1,0,1,1,1,0), - array(0,1,1,0,0,0,1,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,0), - ), - ), - 'X' => array( - array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,1,0,0,0,0,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(1,1,1,0,0,0,1,1,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,1,0,0,0,0,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,1,1,0,0,0,1,1,1), - array(0,0,0,0,0,0,0,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,1,0), - array(0,1,1,0,0,0,1,1,0), - array(0,0,1,1,0,1,1,0,0), - array(0,0,0,1,1,1,0,0,0), - array(0,0,0,1,1,1,0,0,0), - array(0,0,1,1,0,1,1,0,0), - array(0,1,1,0,0,0,1,1,0), - array(0,0,0,0,0,0,0,0,0), - ), - ), - 'Y' => array( - array( - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(1,1,1,0,0,0,1,1,1), - array(0,1,0,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,0,0,1,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,1,1,0,0,0), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,1,0,0,0,0,1), - array(0,0,0,1,1,0,0,0,1), - array(0,0,0,0,1,0,0,1,1), - array(0,0,0,0,1,1,0,1,0), - array(0,0,0,0,0,1,1,1,0), - array(0,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,1,1,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,1,1,0,0,0), - array(0,0,1,1,1,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - ), - ), - 'Z' => array( - array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,1,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,1), - array(1,1,1,1,1,1,1,1,1), - ), - array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,1,1,1,1,1,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,1,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,1,1), - ), - array( - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,0,0,0,0,0,0,0,0), - array(0,1,1,1,1,1,1,1,0), - array(0,0,0,0,0,1,1,0,0), - array(0,0,0,0,1,1,0,0,0), - array(0,0,0,1,1,0,0,0,0), - array(0,0,1,1,0,0,0,0,0), - array(0,0,1,0,0,0,0,0,0), - array(0,1,1,1,1,1,1,1,0), - ), - ), - ); - return array( - 'width' => 9, - 'height' => 15, - 'data' => array( - - 'A' => $chars['A'][mt_rand(0, min(count($chars['A']), phpbb::$config['captcha_gd_fonts']) -1)], - 'B' => $chars['B'][mt_rand(0, min(count($chars['B']), phpbb::$config['captcha_gd_fonts']) -1)], - 'C' => $chars['C'][mt_rand(0, min(count($chars['C']), phpbb::$config['captcha_gd_fonts']) -1)], - 'D' => $chars['D'][mt_rand(0, min(count($chars['D']), phpbb::$config['captcha_gd_fonts']) -1)], - 'E' => $chars['E'][mt_rand(0, min(count($chars['E']), phpbb::$config['captcha_gd_fonts']) -1)], - 'F' => $chars['F'][mt_rand(0, min(count($chars['F']), phpbb::$config['captcha_gd_fonts']) -1)], - 'G' => $chars['G'][mt_rand(0, min(count($chars['G']), phpbb::$config['captcha_gd_fonts']) -1)], - 'H' => $chars['H'][mt_rand(0, min(count($chars['H']), phpbb::$config['captcha_gd_fonts']) -1)], - 'I' => $chars['I'][mt_rand(0, min(count($chars['I']), phpbb::$config['captcha_gd_fonts']) -1)], - 'J' => $chars['J'][mt_rand(0, min(count($chars['J']), phpbb::$config['captcha_gd_fonts']) -1)], - 'K' => $chars['K'][mt_rand(0, min(count($chars['K']), phpbb::$config['captcha_gd_fonts']) -1)], - 'L' => $chars['L'][mt_rand(0, min(count($chars['L']), phpbb::$config['captcha_gd_fonts']) -1)], - 'M' => $chars['M'][mt_rand(0, min(count($chars['M']), phpbb::$config['captcha_gd_fonts']) -1)], - 'N' => $chars['N'][mt_rand(0, min(count($chars['N']), phpbb::$config['captcha_gd_fonts']) -1)], - 'O' => $chars['O'][mt_rand(0, min(count($chars['O']), phpbb::$config['captcha_gd_fonts']) -1)], - 'P' => $chars['P'][mt_rand(0, min(count($chars['P']), phpbb::$config['captcha_gd_fonts']) -1)], - 'Q' => $chars['Q'][mt_rand(0, min(count($chars['Q']), phpbb::$config['captcha_gd_fonts']) -1)], - 'R' => $chars['R'][mt_rand(0, min(count($chars['R']), phpbb::$config['captcha_gd_fonts']) -1)], - 'S' => $chars['S'][mt_rand(0, min(count($chars['S']), phpbb::$config['captcha_gd_fonts']) -1)], - 'T' => $chars['T'][mt_rand(0, min(count($chars['T']), phpbb::$config['captcha_gd_fonts']) -1)], - 'U' => $chars['U'][mt_rand(0, min(count($chars['U']), phpbb::$config['captcha_gd_fonts']) -1)], - 'V' => $chars['V'][mt_rand(0, min(count($chars['V']), phpbb::$config['captcha_gd_fonts']) -1)], - 'W' => $chars['W'][mt_rand(0, min(count($chars['W']), phpbb::$config['captcha_gd_fonts']) -1)], - 'X' => $chars['X'][mt_rand(0, min(count($chars['X']), phpbb::$config['captcha_gd_fonts']) -1)], - 'Y' => $chars['Y'][mt_rand(0, min(count($chars['Y']), phpbb::$config['captcha_gd_fonts']) -1)], - 'Z' => $chars['Z'][mt_rand(0, min(count($chars['Z']), phpbb::$config['captcha_gd_fonts']) -1)], - - '1' => array( - array(0,0,0,1,1,0,0,0,0), - array(0,0,1,0,1,0,0,0,0), - array(0,1,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,1,1,1,1,1,1,1,0), - ), - '2' => array( // New '2' supplied by Anon - array(0,0,0,1,1,1,0,0,0), - array(0,0,1,0,0,0,1,0,0), - array(0,1,0,0,0,0,1,1,0), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,1,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,0,0,0,0), - ), - '3' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,1,1,0,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - '4' => array( - array(0,0,0,0,0,0,1,1,0), - array(0,0,0,0,0,1,0,1,0), - array(0,0,0,0,1,0,0,1,0), - array(0,0,0,1,0,0,0,1,0), - array(0,0,1,0,0,0,0,1,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,1,0), - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - ), - '5' => array( - array(1,1,1,1,1,1,1,1,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,0,1,1,1,1,1,0,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - '6' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,1,1,1,1,0,0), - array(1,0,1,0,0,0,0,1,0), - array(1,1,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - '7' => array( - array(1,1,1,1,1,1,1,1,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,0,1,0), - array(0,0,0,0,0,0,1,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,0,1,0,0,0), - array(0,0,0,0,1,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,0,1,0,0,0,0,0), - array(0,0,1,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(0,1,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - array(1,0,0,0,0,0,0,0,0), - ), - '8' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - '9' => array( - array(0,0,1,1,1,1,1,0,0), - array(0,1,0,0,0,0,0,1,0), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,1,1), - array(0,1,0,0,0,0,1,0,1), - array(0,0,1,1,1,1,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(0,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(1,0,0,0,0,0,0,0,1), - array(0,1,0,0,0,0,0,1,0), - array(0,0,1,1,1,1,1,0,0), - ), - ) - ); - } -} - -/** -* @package VC -*/ -class char_cube3d -{ - private $bitmap; - private $bitmap_width; - private $bitmap_height; - - private $basis_matrix = array(array(1, 0, 0), array(0, 1, 0), array(0, 0, 1)); - private $abs_x = array(1, 0); - private $abs_y = array(0, 1); - private $x = 0; - private $y = 1; - private $z = 2; - private $letter = ''; - - /** - */ - function __construct(&$bitmaps, $letter) - { - $this->bitmap = $bitmaps['data'][$letter]; - $this->bitmap_width = $bitmaps['width']; - $this->bitmap_height = $bitmaps['height']; - - $this->basis_matrix[0][0] = mt_rand(-600, 600); - $this->basis_matrix[0][1] = mt_rand(-600, 600); - $this->basis_matrix[0][2] = (mt_rand(0, 1) * 2000) - 1000; - $this->basis_matrix[1][0] = mt_rand(-1000, 1000); - $this->basis_matrix[1][1] = mt_rand(-1000, 1000); - $this->basis_matrix[1][2] = mt_rand(-1000, 1000); - - $this->normalize($this->basis_matrix[0]); - $this->normalize($this->basis_matrix[1]); - $this->basis_matrix[2] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[1]); - $this->normalize($this->basis_matrix[2]); - - // $this->basis_matrix[1] might not be (probably isn't) orthogonal to $basis_matrix[0] - $this->basis_matrix[1] = $this->cross_product($this->basis_matrix[0], $this->basis_matrix[2]); - $this->normalize($this->basis_matrix[1]); - - // Make sure our cube is facing into the canvas (assuming +z == in) - for ($i = 0; $i < 3; ++$i) - { - if ($this->basis_matrix[$i][2] < 0) - { - $this->basis_matrix[$i][0] *= -1; - $this->basis_matrix[$i][1] *= -1; - $this->basis_matrix[$i][2] *= -1; - } - } - - // Force our "z" basis vector to be the one with greatest absolute z value - $this->x = 0; - $this->y = 1; - $this->z = 2; - - // Swap "y" with "z" - if ($this->basis_matrix[1][2] > $this->basis_matrix[2][2]) - { - $this->z = 1; - $this->y = 2; - } - - // Swap "x" with "z" - if ($this->basis_matrix[0][2] > $this->basis_matrix[$this->z][2]) - { - $this->x = $this->z; - $this->z = 0; - } - - // Still need to determine which of $x,$y are which. - // wrong orientation if y's y-component is less than it's x-component - // likewise if x's x-component is less than it's y-component - // if they disagree, go with the one with the greater weight difference. - // rotate if positive - $weight = (abs($this->basis_matrix[$this->x][1]) - abs($this->basis_matrix[$this->x][0])) + (abs($this->basis_matrix[$this->y][0]) - abs($this->basis_matrix[$this->y][1])); - - // Swap "x" with "y" - if ($weight > 0) - { - list($this->x, $this->y) = array($this->y, $this->x); - } - - $this->abs_x = array($this->basis_matrix[$this->x][0], $this->basis_matrix[$this->x][1]); - $this->abs_y = array($this->basis_matrix[$this->y][0], $this->basis_matrix[$this->y][1]); - - if ($this->abs_x[0] < 0) - { - $this->abs_x[0] *= -1; - $this->abs_x[1] *= -1; - } - - if ($this->abs_y[1] > 0) - { - $this->abs_y[0] *= -1; - $this->abs_y[1] *= -1; - } - - $this->letter = $letter; - } - - /** - * Draw a character - */ - public function drawchar($scale, $xoff, $yoff, $img, $background, $colours) - { - $width = $this->bitmap_width; - $height = $this->bitmap_height; - $bitmap = $this->bitmap; - - $colour1 = $colours[array_rand($colours)]; - $colour2 = $colours[array_rand($colours)]; - - $swapx = ($this->basis_matrix[$this->x][0] > 0); - $swapy = ($this->basis_matrix[$this->y][1] < 0); - - for ($y = 0; $y < $height; ++$y) - { - for ($x = 0; $x < $width; ++$x) - { - $xp = ($swapx) ? ($width - $x - 1) : $x; - $yp = ($swapy) ? ($height - $y - 1) : $y; - - if ($bitmap[$height - $yp - 1][$xp]) - { - $dx = $this->scale($this->abs_x, ($xp - ($swapx ? ($width / 2) : ($width / 2) - 1)) * $scale); - $dy = $this->scale($this->abs_y, ($yp - ($swapy ? ($height / 2) : ($height / 2) - 1)) * $scale); - $xo = $xoff + $dx[0] + $dy[0]; - $yo = $yoff + $dx[1] + $dy[1]; - - $origin = array(0, 0, 0); - $xvec = $this->scale($this->basis_matrix[$this->x], $scale); - $yvec = $this->scale($this->basis_matrix[$this->y], $scale); - $face_corner = self::sum2($xvec, $yvec); - - $zvec = $this->scale($this->basis_matrix[$this->z], $scale); - $x_corner = self::sum2($xvec, $zvec); - $y_corner = self::sum2($yvec, $zvec); - - imagefilledpolygon($img, self::gen_poly($xo, $yo, $origin, $xvec, $x_corner,$zvec), 4, $colour1); - imagefilledpolygon($img, self::gen_poly($xo, $yo, $origin, $yvec, $y_corner,$zvec), 4, $colour2); - - $face = self::gen_poly($xo, $yo, $origin, $xvec, $face_corner, $yvec); - - imagefilledpolygon($img, $face, 4, $background); - imagepolygon($img, $face, 4, $colour1); - } - } - } - } - - /* - * return a roughly acceptable range of sizes for rendering with this texttype - */ - public static function range() - { - return array(3, 4); - } - - /** - * Vector length - */ - private static function vectorlen($vector) - { - return sqrt(pow($vector[0], 2) + pow($vector[1], 2) + pow($vector[2], 2)); - } - - /** - * Normalize - */ - private static function normalize(&$vector, $length = 1) - { - $length = (( $length < 1) ? 1 : $length); - $length /= self::vectorlen($vector); - $vector[0] *= $length; - $vector[1] *= $length; - $vector[2] *= $length; - } - - /** - */ - private static function cross_product($vector1, $vector2) - { - $retval = array(0, 0, 0); - $retval[0] = (($vector1[1] * $vector2[2]) - ($vector1[2] * $vector2[1])); - $retval[1] = -(($vector1[0] * $vector2[2]) - ($vector1[2] * $vector2[0])); - $retval[2] = (($vector1[0] * $vector2[1]) - ($vector1[1] * $vector2[0])); - - return $retval; - } - - /** - */ - private static function sum($vector1, $vector2) - { - return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1], $vector1[2] + $vector2[2]); - } - - /** - */ - private static function sum2($vector1, $vector2) - { - return array($vector1[0] + $vector2[0], $vector1[1] + $vector2[1]); - } - - /** - */ - private static function scale($vector, $length) - { - if (sizeof($vector) == 2) - { - return array($vector[0] * $length, $vector[1] * $length); - } - - return array($vector[0] * $length, $vector[1] * $length, $vector[2] * $length); - } - - /** - */ - private static function gen_poly($xoff, $yoff, &$vec1, &$vec2, &$vec3, &$vec4) - { - $poly = array(); - $poly[0] = $xoff + $vec1[0]; - $poly[1] = $yoff + $vec1[1]; - $poly[2] = $xoff + $vec2[0]; - $poly[3] = $yoff + $vec2[1]; - $poly[4] = $xoff + $vec3[0]; - $poly[5] = $yoff + $vec3[1]; - $poly[6] = $xoff + $vec4[0]; - $poly[7] = $yoff + $vec4[1]; - - return $poly; - } - - /** - * dimensions - */ - public function dimensions($size) - { - $xn = $this->scale($this->basis_matrix[$this->x], -($this->bitmap_width / 2) * $size); - $xp = $this->scale($this->basis_matrix[$this->x], ($this->bitmap_width / 2) * $size); - $yn = $this->scale($this->basis_matrix[$this->y], -($this->bitmap_height / 2) * $size); - $yp = $this->scale($this->basis_matrix[$this->y], ($this->bitmap_height / 2) * $size); - - $p = array(); - $p[0] = self::sum2($xn, $yn); - $p[1] = self::sum2($xp, $yn); - $p[2] = self::sum2($xp, $yp); - $p[3] = self::sum2($xn, $yp); - - $min_x = $max_x = $p[0][0]; - $min_y = $max_y = $p[0][1]; - - for ($i = 1; $i < 4; ++$i) - { - $min_x = ($min_x > $p[$i][0]) ? $p[$i][0] : $min_x; - $min_y = ($min_y > $p[$i][1]) ? $p[$i][1] : $min_y; - $max_x = ($max_x < $p[$i][0]) ? $p[$i][0] : $max_x; - $max_y = ($max_y < $p[$i][1]) ? $p[$i][1] : $max_y; - } - - return array($min_x, $min_y, $max_x, $max_y); - } -} - -/** -* @package VC -*/ -class colour_manager -{ - private $img; - private $mode; - private $colours; - private $named_colours; - - /** - * Create the colour manager, link it to the image resource - */ - function __construct($img, $background = false, $mode = 'ahsv') - { - $this->img = $img; - $this->mode = $mode; - $this->colours = array(); - $this->named_colours = array(); - - if ($background !== false) - { - $bg = $this->allocate_named('background', $background); - imagefill($this->img, 0, 0, $bg); - } - } - - /** - * Lookup a named colour resource - */ - public function get_resource($named_colour) - { - if (isset($this->named_colours[$named_colour])) - { - return $this->named_colours[$named_colour]; - } - - if (isset($this->named_rgb[$named_colour])) - { - return $this->allocate_named($named_colour, $this->named_rgb[$named_colour], 'rgb'); - } - - return false; - } - - /** - * Assign a name to a colour resource - */ - private function name_colour($name, $resource) - { - $this->named_colours[$name] = $resource; - } - - /** - * names and allocates a colour resource - */ - private function allocate_named($name, $colour, $mode = false) - { - $resource = $this->allocate($colour, $mode); - - if ($resource !== false) - { - $this->name_colour($name, $resource); - } - return $resource; - } - - /** - * allocates a specified colour into the image - */ - private function allocate($colour, $mode = false) - { - if ($mode === false) - { - $mode = $this->mode; - } - - if (!is_array($colour)) - { - if (isset($this->named_rgb[$colour])) - { - return $this->allocate_named($colour, $this->named_rgb[$colour], 'rgb'); - } - - if (!is_int($colour)) - { - return false; - } - - $mode = 'rgb'; - $colour = array(255 & ($colour >> 16), 255 & ($colour >> 8), 255 & $colour); - } - - if (isset($colour['mode'])) - { - $mode = $colour['mode']; - unset($colour['mode']); - } - - if (isset($colour['random'])) - { - unset($colour['random']); - // everything else is params - return $this->random_colour($colour, $mode); - } - - $rgb = colour_manager::model_convert($colour, $mode, 'rgb'); - $store = ($this->mode == 'rgb') ? $rgb : colour_manager::model_convert($colour, $mode, $this->mode); - $resource = imagecolorallocate($this->img, $rgb[0], $rgb[1], $rgb[2]); - $this->colours[$resource] = $store; - - return $resource; - } - - /** - * randomly generates a colour, with optional params - */ - private function random_colour($params = array(), $mode = false) - { - if ($mode === false) - { - $mode = $this->mode; - } - - switch ($mode) - { - case 'rgb': - // @TODO random rgb generation. do we intend to do this, or is it just too tedious? - break; - - case 'ahsv': - case 'hsv': - default: - - $default_params = array( - 'hue_bias' => false, // degree / 'r'/'g'/'b'/'c'/'m'/'y' /'o' - 'hue_range' => false, // if hue bias, then difference range +/- from bias - 'min_saturation' => 30, // 0 - 100 - 'max_saturation' => 80, // 0 - 100 - 'min_value' => 30, // 0 - 100 - 'max_value' => 80, // 0 - 100 - ); - - $alt = ($mode == 'ahsv') ? true : false; - $params = array_merge($default_params, $params); - - $min_hue = 0; - $max_hue = 359; - $min_saturation = max(0, $params['min_saturation']); - $max_saturation = min(100, $params['max_saturation']); - $min_value = max(0, $params['min_value']); - $max_value = min(100, $params['max_value']); - - if ($params['hue_bias'] !== false) - { - if (is_numeric($params['hue_bias'])) - { - $h = intval($params['hue_bias']) % 360; - } - else - { - switch ($params['hue_bias']) - { - case 'o': - $h = $alt ? 60 : 30; - break; - - case 'y': - $h = $alt ? 120 : 60; - break; - - case 'g': - $h = $alt ? 180 : 120; - break; - - case 'c': - $h = $alt ? 210 : 180; - break; - - case 'b': - $h = 240; - break; - - case 'm': - $h = 300; - break; - - case 'r': - default: - $h = 0; - break; - } - } - - $min_hue = $h + 360; - $max_hue = $h + 360; - - if ($params['hue_range']) - { - $min_hue -= min(180, $params['hue_range']); - $max_hue += min(180, $params['hue_range']); - } - } - - $h = mt_rand($min_hue, $max_hue); - $s = mt_rand($min_saturation, $max_saturation); - $v = mt_rand($min_value, $max_value); - - return $this->allocate(array($h, $s, $v), $mode); - - break; - } - } - - /** - */ - public function colour_scheme($resource, $include_original = true) - { - $mode = 'hsv'; - - if (($pre = $this->get_resource($resource)) !== false) - { - $resource = $pre; - } - - $colour = colour_manager::model_convert($this->colours[$resource], $this->mode, $mode); - $results = ($include_original) ? array($resource) : array(); - $colour2 = $colour3 = $colour4 = $colour; - $colour2[0] += 150; - $colour3[0] += 180; - $colour4[0] += 210; - - - $results[] = $this->allocate($colour2, $mode); - $results[] = $this->allocate($colour3, $mode); - $results[] = $this->allocate($colour4, $mode); - - return $results; - } - - /** - */ - public function mono_range($resource, $count = 5, $include_original = true) - { - if (is_array($resource)) - { - $results = array(); - for ($i = 0, $size = sizeof($resource); $i < $size; ++$i) - { - $results = array_merge($results, $this->mono_range($resource[$i], $count, $include_original)); - } - return $results; - } - - $mode = (in_array($this->mode, array('hsv', 'ahsv'), true) ? $this->mode : 'ahsv'); - if (($pre = $this->get_resource($resource)) !== false) - { - $resource = $pre; - } - - $colour = colour_manager::model_convert($this->colours[$resource], $this->mode, $mode); - - $results = array(); - if ($include_original) - { - $results[] = $resource; - $count--; - } - - // This is a hard problem. I chicken out and try to maintain readability at the cost of less randomness. - - while ($count > 0) - { - $colour[1] = ($colour[1] + mt_rand(40,60)) % 99; - $colour[2] = ($colour[2] + mt_rand(40,60)); - $results[] = $this->allocate($colour, $mode); - $count--; - } - return $results; - } - - /** - * Convert from one colour model to another - */ - private static function model_convert($colour, $from_model, $to_model) - { - if ($from_model == $to_model) - { - return $colour; - } - - switch ($to_model) - { - case 'hsv': - - switch ($from_model) - { - case 'ahsv': - return colour_manager::ah2h($colour); - break; - - case 'rgb': - return colour_manager::rgb2hsv($colour); - break; - } - break; - - case 'ahsv': - - switch ($from_model) - { - case 'hsv': - return colour_manager::h2ah($colour); - break; - - case 'rgb': - return colour_manager::h2ah(colour_manager::rgb2hsv($colour)); - break; - } - break; - - case 'rgb': - switch ($from_model) - { - case 'hsv': - return colour_manager::hsv2rgb($colour); - break; - - case 'ahsv': - return colour_manager::hsv2rgb(colour_manager::ah2h($colour)); - break; - } - break; - } - return false; - } - - /** - * Slightly altered from wikipedia's algorithm - */ - private static function hsv2rgb($hsv) - { - colour_manager::normalize_hue($hsv[0]); - - $h = $hsv[0]; - $s = min(1, max(0, $hsv[1] / 100)); - $v = min(1, max(0, $hsv[2] / 100)); - - // calculate hue sector - $hi = floor($hsv[0] / 60); - - // calculate opposite colour - $p = $v * (1 - $s); - - // calculate distance between hex vertices - $f = ($h / 60) - $hi; - - // coming in or going out? - if (!($hi & 1)) - { - $f = 1 - $f; - } - - // calculate adjacent colour - $q = $v * (1 - ($f * $s)); - - switch ($hi) - { - case 0: - $rgb = array($v, $q, $p); - break; - - case 1: - $rgb = array($q, $v, $p); - break; - - case 2: - $rgb = array($p, $v, $q); - break; - - case 3: - $rgb = array($p, $q, $v); - break; - - case 4: - $rgb = array($q, $p, $v); - break; - - case 5: - $rgb = array($v, $p, $q); - break; - - default: - return array(0, 0, 0); - break; - } - - return array(255 * $rgb[0], 255 * $rgb[1], 255 * $rgb[2]); - } - - /** - * (more than) Slightly altered from wikipedia's algorithm - */ - private static function rgb2hsv($rgb) - { - $r = min(255, max(0, $rgb[0])); - $g = min(255, max(0, $rgb[1])); - $b = min(255, max(0, $rgb[2])); - $max = max($r, $g, $b); - $min = min($r, $g, $b); - - $v = $max / 255; - $s = (!$max) ? 0 : 1 - ($min / $max); - - // if max - min is 0, we want hue to be 0 anyway. - $h = $max - $min; - - if ($h) - { - switch ($max) - { - case $g: - $h = 120 + (60 * ($b - $r) / $h); - break; - - case $b: - $h = 240 + (60 * ($r - $g) / $h); - break; - - case $r: - $h = 360 + (60 * ($g - $b) / $h); - break; - } - } - colour_manager::normalize_hue($h); - - return array($h, $s * 100, $v * 100); - } - - /** - */ - private static function normalize_hue(&$hue) - { - $hue %= 360; - - if ($hue < 0) - { - $hue += 360; - } - } - - /** - * Alternate hue to hue - */ - private static function ah2h($ahue) - { - if (is_array($ahue)) - { - $ahue[0] = colour_manager::ah2h($ahue[0]); - return $ahue; - } - colour_manager::normalize_hue($ahue); - - // blue through red is already ok - if ($ahue >= 240) - { - return $ahue; - } - - // ahue green is at 180 - if ($ahue >= 180) - { - // return (240 - (2 * (240 - $ahue))); - return (2 * $ahue) - 240; // equivalent - } - - // ahue yellow is at 120 (RYB rather than RGB) - if ($ahue >= 120) - { - return $ahue - 60; - } - - return $ahue / 2; - } - - /** - * hue to Alternate hue - */ - private static function h2ah($hue) - { - if (is_array($hue)) - { - $hue[0] = colour_manager::h2ah($hue[0]); - return $hue; - } - colour_manager::normalize_hue($hue); - - // blue through red is already ok - if ($hue >= 240) - { - return $hue; - } - else if ($hue <= 60) - { - return $hue * 2; - } - else if ($hue <= 120) - { - return $hue + 60; - } - else - { - return ($hue + 240) / 2; - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/captcha/captcha_gd_wave.php b/phpBB/includes/captcha/captcha_gd_wave.php deleted file mode 100644 index 8c1d9d5507..0000000000 --- a/phpBB/includes/captcha/captcha_gd_wave.php +++ /dev/null @@ -1,842 +0,0 @@ -<?php
-/**
-*
-* @package VC
-* @version $Id: captcha_gd.php,v 1.19 2007/01/26 16:07:43 acydburn Exp $
-* @copyright (c) 2006 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
-*
-*/
- - -/** -Wave3D CAPTCHA by Robert Hetzler -*/
-class captcha
-{
- const WIDTH = 360;
- const HEIGHT = 96;
-
- static function execute($code, $seed)
- {
- global $starttime;
-
- // seed the random generator
- mt_srand($seed);
-
- // set height and width
- $img_x = self::WIDTH;
- $img_y = self::HEIGHT;
-
- // Generate image
- $img = imagecreatetruecolor($img_x, $img_y);
- $x_grid = mt_rand(6, 10);
- $y_grid = mt_rand(6, 10);
-
- // Ok, so lets cut to the chase. We could accurately represent this in 3d and
- // do all the appropriate linear transforms. my questions is... why bother?
- // The computational overhead is unnecessary when you consider the simple fact:
- // we're not here to accurately represent a model, but to just show off some random-ish
- // polygons
-
- // Conceive of 3 spaces.
- // 1) planar-space (discrete "pixel" grid)
- // 2) 3-space. (planar-space with z/height aspect)
- // 3) image space (pixels on the screen)
- // resolution of the planar-space we're embedding the text code in
- $plane_x = 100;
- $plane_y = 30;
-
- $subdivision_factor = 3;
- // $box is the 4 points in img_space that correspond to the corners of the plane in 3-space
- $box = array(
- 'upper_left' => array(
- 'x' => mt_rand(5, 15),
- 'y' => mt_rand(10, 15)
- ),
- 'upper_right' => array(
- 'x' => mt_rand($img_x - 35, $img_x - 19),
- 'y' => mt_rand(10, 17)
- ),
- 'lower_left' => array(
- 'x' => mt_rand($img_x - 5, $img_x - 45),
- 'y' => mt_rand($img_y - 0, $img_y - 15)
- ),
- );
- $box['lower_right'] = array(
- 'x' => $box['lower_left']['x'] + $box['upper_left']['x'] - $box['upper_right']['x'],
- 'y' => $box['lower_left']['y'] + $box['upper_left']['y'] - $box['upper_right']['y'],
- );
-
-
- // TODO
- $background = imagecolorallocate($img, mt_rand(155, 255), mt_rand(155, 255), mt_rand(155, 255));
- imagefill($img, 0, 0, $background);
- $black = imagecolorallocate($img, 0, 0, 0);
-
- $random = array();
- $fontcolors = array();
-
- for ($i = 0; $i < 15; ++$i)
- {
- $random[$i] = imagecolorallocate($img, mt_rand(120, 255), mt_rand(120, 255), mt_rand(120, 255));
- }
-
- $fontcolors[0] = imagecolorallocate($img, mt_rand(0, 120), mt_rand(0, 120), mt_rand(0, 120));
-
- $colors = array();
-
- $minr = mt_rand(20, 30);
- $ming = mt_rand(20, 30);
- $minb = mt_rand(20, 30);
-
- $maxr = mt_rand(150, 230);
- $maxg = mt_rand(150, 230);
- $maxb = mt_rand(150, 230);
-
- for ($i = -30; $i <= 30; ++$i)
- {
- $coeff1 = ($i + 12) / 45;
- $coeff2 = 1 - $coeff1;
- $colors[$i] = imagecolorallocate($img, ($coeff2 * $maxr) + ($coeff1 * $minr), ($coeff2 * $maxg) + ($coeff1 * $ming), ($coeff2 * $maxb) + ($coeff1 * $minb));
- }
-
- // $img_buffer is the last row of 3-space positions (converted to img-space), cached
- // (using this means we don't need to recalculate all 4 positions for each new polygon,
- // merely the newest point that we're adding, which is then cached.
- $img_buffer = array(array(), array());
-
- // In image-space, the x- and y-offset necessary to move one unit in the x-direction in planar-space
- $dxx = ($box['upper_right']['x'] - $box['upper_left']['x']) / ($subdivision_factor * $plane_x);
- $dxy = ($box['upper_right']['y'] - $box['upper_left']['y']) / ($subdivision_factor * $plane_x);
-
- // In image-space, the x- and y-offset necessary to move one unit in the y-direction in planar-space
- $dyx = ($box['lower_right']['x'] - $box['upper_left']['x']) / ($subdivision_factor * $plane_y);
- $dyy = ($box['lower_right']['y'] - $box['upper_left']['y']) / ($subdivision_factor * $plane_y);
-
- // Initial captcha-letter offset in planar-space
- $plane_offset_x = mt_rand(3, 8);
- $plane_offset_y = mt_rand( 12, 15);
-
- // character map
- $map = self::captcha_bitmaps();
-
- // matrix
- $plane = array();
-
- // for each character, we'll silkscreen it into our boolean pixel plane
- for ($c = 0, $code_num = strlen($code); $c < $code_num; ++$c)
- {
- $letter = $code[$c];
-
- for ($x = $map['width'] - 1; $x >= 0; --$x)
- {
- for ($y = $map['height'] - 1; $y >= 0; --$y)
- {
- if ($map['data'][$letter][$y][$x])
- {
- $plane[$y + $plane_offset_y + (($c & 1) ? 1 : -1)][$x + $plane_offset_x] = true;
- }
- }
- }
- $plane_offset_x += 11;
- }
-
- // calculate our first buffer, we can't actually draw polys with these yet
- // img_pos_prev == screen x,y location to our immediate left.
- // img_pos_cur == current screen x,y location
- // we calculate screen position of our
- // current cell based on the difference from the previous cell
- // rather than recalculating from absolute coordinates
- // What we cache into the $img_buffer contains the raised text coordinates.
- $img_pos_prev = $img_buffer[0][0] = array($box['upper_left']['x'], $box['upper_left']['y']);
- $cur_height = $prev_height = self::wave_height(0, 0, $subdivision_factor);
- $full_x = $plane_x * $subdivision_factor;
- $full_y = $plane_y * $subdivision_factor;
-
- for ($x = 1; $x <= $full_x; ++$x)
- {
- $cur_height = self::wave_height($x, 0, $subdivision_factor);
- $offset = $cur_height - $prev_height;
- $img_pos_cur = array($img_pos_prev[0] + $dxx, $img_pos_prev[1] + $dxy + $offset);
-
- $img_buffer[0][$x] = $img_pos_cur;
- $img_pos_prev = $img_pos_cur;
- $prev_height = $cur_height;
- }
-
- for ($y = 1; $y <= $full_y; ++$y)
- {
- // swap buffers
- $buffer_cur = $y & 1;
- $buffer_prev = 1 - $buffer_cur;
-
- $prev_height = self::wave_height(0, $y, $subdivision_factor);
- $offset = $prev_height - self::wave_height(0, $y - 1, $subdivision_factor);
- $img_pos_cur = array($img_buffer[$buffer_prev][0][0] + $dyx, min($img_buffer[$buffer_prev][0][1] + $dyy + $offset, $img_y - 1));
-
- // make sure we don't try to write off the page
- $img_pos_prev = $img_pos_cur;
-
- $img_buffer[$buffer_cur][0] = $img_pos_cur;
-
- for ($x = 1; $x <= $full_x; ++$x)
- {
- $cur_height = self::wave_height($x, $y, $subdivision_factor) + self::grid_height($x, $y, 1, $x_grid, $y_grid);
-
- // height is a z-factor, not a y-factor
- $offset = $cur_height - $prev_height;
- $img_pos_cur = array($img_pos_prev[0] + $dxx, $img_pos_prev[1] + $dxy + $offset);
-
- // height is float, index it to an int, get closest color
- $color = $colors[intval($cur_height)];
- $img_pos_prev = $img_pos_cur;
- $prev_height = $cur_height;
-
- $y_index_old = intval(($y - 1) / $subdivision_factor);
- $y_index_new = intval($y / $subdivision_factor);
- $x_index_old = intval(($x - 1) / $subdivision_factor);
- $x_index_new = intval($x / $subdivision_factor);
-
- if (!empty($plane[$y_index_new][$x_index_new]))
- {
- $img_pos_cur[1] += self::wave_height($x, $y, $subdivision_factor, 1) - 30 - $cur_height;
- $color = $colors[20];
- }
- $img_pos_cur[1] = min($img_pos_cur[1], $img_y - 1);
- $img_buffer[$buffer_cur][$x] = $img_pos_cur;
-
- // Smooth the edges as much as possible by having not more than one low<->high traingle per square
- // Otherwise, just
- $diag_down = (empty($plane[$y_index_old][$x_index_old]) == empty($plane[$y_index_new][$x_index_new]));
- $diag_up = (empty($plane[$y_index_old][$x_index_new]) == empty($plane[$y_index_new][$x_index_old]));
-
- // natural switching
- $mode = ($x + $y) & 1;
-
- // override if it requires it
- if ($diag_down != $diag_up)
- {
- $mode = $diag_up;
- }
-
- if ($mode)
- {
- // +-/ /
- // 1 |/ 2 /|
- // / /-+
- $poly1 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_prev][$x]);
- $poly2 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_cur][$x], $img_buffer[$buffer_prev][$x]);
- }
- else
- {
- // \ \-+
- // 1 |\ 2 \|
- // +-\ \
- $poly1 = array_merge($img_buffer[$buffer_cur][$x - 1], $img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_cur][$x]);
- $poly2 = array_merge($img_buffer[$buffer_prev][$x - 1], $img_buffer[$buffer_prev][$x], $img_buffer[$buffer_cur][$x]);
- }
-
- imagefilledpolygon($img, $poly1, 3, $color);
- imagefilledpolygon($img, $poly2, 3, $color);
- }
- }
-
- // Output image
- header('Content-Type: image/png');
- header('Cache-control: no-cache, no-store');
- //$mtime = explode(' ', microtime());
- //$totaltime = $mtime[0] + $mtime[1] - $starttime;
-
- //echo $totaltime . "<br />\n";
- //echo memory_get_usage() - $tmp;
- imagepng($img);
- imagedestroy($img);
- }
-
- static function wave_height($x, $y, $factor = 1, $tweak = 0.7)
- {
- // stretch the wave. TODO: pretty it up
- $x = $x/5 + 180;
- $y = $y/4;
- return ((sin($x / (3 * $factor)) + sin($y / (3 * $factor))) * 10 * $tweak);
- }
-
- static function grid_height($x, $y, $factor = 1, $x_grid, $y_grid)
- {
- return ((!($x % ($x_grid * $factor)) || !($y % ($y_grid * $factor))) ? 3 : 0);
- }
-
- static function captcha_bitmaps()
- {
- return array(
- 'width' => 9,
- 'height' => 13,
- 'data' => array(
- 'A' => array(
- array(0,0,1,1,1,1,0,0,0),
- array(0,1,0,0,0,0,1,0,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,1,1,1,1,1,1,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'B' => array(
- array(1,1,1,1,1,1,0,0,0),
- array(1,0,0,0,0,0,1,0,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,1,0,0),
- array(1,1,1,1,1,1,0,0,0),
- array(1,0,0,0,0,0,1,0,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,1,0,0),
- array(1,1,1,1,1,1,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'C' => array(
- array(0,0,1,1,1,1,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,1,1,1,1,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'D' => array(
- array(1,1,1,1,1,1,1,0,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,1,0),
- array(1,1,1,1,1,1,1,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'E' => array(
- array(0,0,1,1,1,1,1,1,1),
- array(0,1,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,1,1,1,1,1,1,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(0,1,0,0,0,0,0,0,0),
- array(0,0,1,1,1,1,1,1,1),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'F' => array(
- array(0,0,1,1,1,1,1,1,0),
- array(0,1,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,1,1,1,1,1,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'G' => array(
- array(0,0,1,1,1,1,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,1,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,1,1,1,1,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'H' => array(
- array(1,0,0,0,0,0,1,0,0),
- array(1,0,0,0,0,0,1,0,0),
- array(1,0,0,0,0,0,1,0,0),
- array(1,0,0,0,0,0,1,0,0),
- array(1,0,0,0,0,0,1,0,0),
- array(1,1,1,1,1,1,1,0,0),
- array(1,0,0,0,0,0,1,0,0),
- array(1,0,0,0,0,0,1,0,0),
- array(1,0,0,0,0,0,1,0,0),
- array(1,0,0,0,0,0,1,0,0),
- array(1,0,0,0,0,0,1,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'I' => array(
- array(0,1,1,1,1,1,1,1,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,1,1,1,1,1,1,1,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'J' => array(
- array(0,0,0,0,0,0,1,1,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,0,1),
- array(0,0,1,0,0,0,0,1,0),
- array(0,0,0,1,1,1,1,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'K' => array(
- array(1,0,0,0,0,0,1,0,0),
- array(1,0,0,0,0,1,0,0,0),
- array(1,0,0,0,1,0,0,0,0),
- array(1,0,0,1,0,0,0,0,0),
- array(1,0,1,0,0,0,0,0,0),
- array(1,1,0,0,0,0,0,0,0),
- array(1,0,1,0,0,0,0,0,0),
- array(1,0,0,1,0,0,0,0,0),
- array(1,0,0,0,1,0,0,0,0),
- array(1,0,0,0,0,1,0,0,0),
- array(1,0,0,0,0,0,1,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'L' => array(
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(0,1,0,0,0,0,0,0,0),
- array(0,0,1,1,1,1,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'M' => array(
- array(0,1,0,0,0,0,0,1,0),
- array(0,1,1,0,0,0,1,1,0),
- array(0,1,0,1,0,1,0,1,0),
- array(0,1,0,0,1,0,0,1,0),
- array(0,1,0,0,0,0,0,1,0),
- array(0,1,0,0,0,0,0,1,0),
- array(0,1,0,0,0,0,0,1,0),
- array(0,1,0,0,0,0,0,1,0),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'N' => array(
- array(1,0,0,0,0,0,0,0,1),
- array(1,1,0,0,0,0,0,0,1),
- array(1,0,1,0,0,0,0,0,1),
- array(1,0,0,1,0,0,0,0,1),
- array(1,0,0,0,1,0,0,0,1),
- array(1,0,0,0,0,1,0,0,1),
- array(1,0,0,0,0,0,1,0,1),
- array(1,0,0,0,0,0,0,1,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'O' => array(
- array(0,0,0,1,1,1,0,0,0),
- array(0,0,1,0,0,0,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,0,0,0,1,0,0),
- array(0,0,0,1,1,1,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'P' => array(
- array(1,1,1,1,1,1,0,0,0),
- array(1,0,0,0,0,0,1,0,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,1,0,0),
- array(1,1,1,1,1,1,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'Q' => array(
- array(0,0,1,1,1,1,0,0,0),
- array(0,1,0,0,0,0,1,0,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,1,0,0,1,0),
- array(1,0,0,0,0,1,0,1,0),
- array(0,1,0,0,0,0,1,0,0),
- array(0,0,1,1,1,1,0,1,0),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'R' => array(
- array(1,1,1,1,1,1,0,0,0),
- array(1,0,0,0,0,0,1,0,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,1,0,0),
- array(1,1,1,1,1,1,0,0,0),
- array(1,0,1,0,0,0,0,0,0),
- array(1,0,0,1,0,0,0,0,0),
- array(1,0,0,0,1,0,0,0,0),
- array(1,0,0,0,0,1,0,0,0),
- array(1,0,0,0,0,0,1,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'S' => array(
- array(0,0,1,1,1,1,1,1,1),
- array(0,1,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(0,1,0,0,0,0,0,0,0),
- array(0,0,1,1,1,1,1,0,0),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,1,0),
- array(1,1,1,1,1,1,1,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'T' => array(
- array(1,1,1,1,1,1,1,1,1),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'U' => array(
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,1,1,1,1,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'V' => array(
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,0,0,0,1,0,0),
- array(0,0,0,1,0,1,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'W' => array(
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,1,0,0,0,1),
- array(1,0,0,1,0,1,0,0,1),
- array(1,0,1,0,0,0,1,0,1),
- array(1,1,0,0,0,0,0,1,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'X' => array(
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,0,0,0,1,0,0),
- array(0,0,0,1,0,1,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,1,0,1,0,0,0),
- array(0,0,1,0,0,0,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'Y' => array(
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,0,0,0,1,0,0),
- array(0,0,0,1,0,1,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- 'Z' => array(
- array(1,1,1,1,1,1,1,1,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,1,0,0),
- array(0,0,0,0,0,1,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,1,0,0,0,0,0),
- array(0,0,1,0,0,0,0,0,0),
- array(0,1,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,1,1,1,1,1,1,1,1),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- '1' => array(
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,1,1,0,0,0,0),
- array(0,0,1,0,1,0,0,0,0),
- array(0,1,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,1,1,1,1,1,1,1,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- '2' => array(
- array(0,0,0,1,1,1,0,0,0),
- array(0,0,1,0,0,0,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,1,0,0),
- array(0,0,0,0,0,1,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,1,0,0,0,0,0),
- array(0,0,1,0,0,0,0,0,0),
- array(0,1,1,1,1,1,1,1,1),
- array(0,0,0,0,0,0,0,0,0),
- ),
- '3' => array(
- array(0,0,0,1,1,1,1,0,0),
- array(0,0,1,0,0,0,0,1,0),
- array(0,1,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,1,1,0,0),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,0,1),
- array(0,0,1,0,0,0,0,1,0),
- array(0,0,0,1,1,1,1,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- '4' => array(
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,1,1,0),
- array(0,0,0,0,0,1,0,1,0),
- array(0,0,0,0,1,0,0,1,0),
- array(0,0,0,1,0,0,0,1,0),
- array(0,0,1,0,0,0,0,1,0),
- array(0,1,1,1,1,1,1,1,1),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- '5' => array(
- array(1,1,1,1,1,1,1,1,1),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(0,1,0,0,0,0,0,0,0),
- array(0,0,1,1,1,1,1,0,0),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,1,1,1,1,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- '6' => array(
- array(0,0,1,1,1,1,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,0,0,0,0,0,0),
- array(1,0,0,1,1,1,1,0,0),
- array(1,0,1,0,0,0,0,1,0),
- array(1,1,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,1,1,1,1,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- '7' => array(
- array(1,1,1,1,1,1,1,1,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,1,0),
- array(0,0,0,0,0,0,1,0,0),
- array(0,0,0,0,0,1,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,1,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- '8' => array(
- array(0,0,1,1,1,1,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,1,1,1,1,0,0),
- array(0,1,0,0,0,0,0,1,0),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(1,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,0),
- array(0,0,1,1,1,1,1,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- '9' => array(
- array(0,0,0,1,1,1,1,0,0),
- array(0,0,1,0,0,0,0,1,0),
- array(0,1,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,1,1),
- array(0,0,1,1,1,1,1,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,0,0,0,0,0,0,0,1),
- array(0,1,0,0,0,0,0,0,1),
- array(0,0,1,0,0,0,0,1,0),
- array(0,0,0,1,1,1,1,0,0),
- array(0,0,0,0,0,0,0,0,0),
- array(0,0,0,0,0,0,0,0,0),
- ),
- )
- );
- } -}
-
-?>
\ No newline at end of file diff --git a/phpBB/includes/captcha/captcha_non_gd.php b/phpBB/includes/captcha/captcha_non_gd.php deleted file mode 100644 index 3f9db24f3a..0000000000 --- a/phpBB/includes/captcha/captcha_non_gd.php +++ /dev/null @@ -1,384 +0,0 @@ -<?php -/** -* -* @package VC -* @version $Id$ -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Main non-gd captcha class -* @ignore -* @package VC -*/ -class captcha -{ - const width = 320; - const height = 50; - - /** - * Create the image containing $code with a seed of $seed - */ - public static function execute($code, $seed) - { - $img_height = self::height - 10; - $img_width = 0; - - mt_srand($seed); - - $char_widths = $hold_chars = array(); - $code_len = strlen($code); - - // If we can we will generate a single filtered png, we avoid nastiness via emulation of some Zlib stuff - $filtered_pngs = self::define_filtered_pngs(); - - for ($i = 0; $i < $code_len; $i++) - { - $char = $code[$i]; - - $width = mt_rand(0, 4); - $raw_width = $filtered_pngs[$char]['width']; - $char_widths[$i] = $width; - $img_width += $raw_width - $width; - - // Split the char into chunks of $raw_width + 1 length - if (empty($hold_chars[$char])) - { - $hold_chars[$char] = str_split(base64_decode($filtered_pngs[$char]['data']), $raw_width + 1); - } - } - - $offset_x = mt_rand(0, self::width - $img_width); - $offset_y = mt_rand(0, self::height - $img_height); - - $image = ''; - for ($i = 0; $i < self::height; $i++) - { - $image .= chr(0); - - if ($i > $offset_y && $i < $offset_y + $img_height) - { - for ($j = 0; $j < $offset_x; $j++) - { - $image .= chr(mt_rand(140, 255)); - } - - for ($j = 0; $j < $code_len; $j++) - { - $image .= self::randomise(substr($hold_chars[$code{$j}][$i - $offset_y - 1], 1), $char_widths[$j]); - } - - for ($j = $offset_x + $img_width; $j < self::width; $j++) - { - $image .= chr(mt_rand(140, 255)); - } - } - else - { - for ($j = 0; $j < self::width; $j++) - { - $image .= chr(mt_rand(140, 255)); - } - } - } - unset($hold_chars); - - $image = self::create_png($image, self::width, self::height); - - // Output image - header('Content-Type: image/png'); - header('Cache-control: no-cache, no-store'); - echo $image; - } - - /** - * This is designed to randomise the pixels of the image data within - * certain limits so as to keep it readable. It also varies the image - * width a little - */ - private static function randomise($scanline, $width) - { - $new_line = ''; - - $end = strlen($scanline) - ceil($width / 2); - for ($i = $width >> 1; $i < $end; $i++) - { - $pixel = ord($scanline[$i]); - - if ($pixel < 190) - { - $new_line .= chr(mt_rand(0, 205)); - } - else if ($pixel > 190) - { - $new_line .= chr(mt_rand(145, 255)); - } - else - { - $new_line .= $scanline{$i}; - } - } - - return $new_line; - } - - /** - * This creates a chunk of the given type, with the given data - * of the given length adding the relevant crc - */ - private static function png_chunk($length, $type, $data) - { - $raw = $type . $data; - - return pack('N', $length) . $raw . pack('N', crc32($raw)); - } - - /** - * Creates greyscale 8bit png - The PNG spec can be found at - * http://www.libpng.org/pub/png/spec/PNG-Contents.html we use - * png because it's a fully recognised open standard and supported - * by practically all modern browsers and OSs - */ - static function create_png($raw_image, $width, $height) - { - // SIG - $image = pack('C8', 137, 80, 78, 71, 13, 10, 26, 10); - - // IHDR - $raw = pack('N2', $width, $height); - $raw .= pack('C5', 8, 0, 0, 0, 0); - $image .= self::png_chunk(13, 'IHDR', $raw); - - // IDAT - if (@extension_loaded('zlib')) - { - $raw_image = gzcompress($raw_image); - $length = strlen($raw_image); - } - else - { - // The total length of this image, uncompressed, is just a calculation of pixels - $length = ($width + 1) * $height; - - // Adler-32 hash generation - // Note: The hash is _backwards_ so we must reverse it - - if (@extension_loaded('hash')) - { - $adler_hash = strrev(hash('adler32', $raw_image, true)); - } - else if (@extension_loaded('mhash')) - { - $adler_hash = strrev(mhash(MHASH_ADLER32, $raw_image)); - } - else - { - // Optimized Adler-32 loop ported from the GNU Classpath project - $temp_length = $length; - $s1 = 1; - $s2 = $index = 0; - - while ($temp_length > 0) - { - // We can defer the modulo operation: - // s1 maximally grows from 65521 to 65521 + 255 * 3800 - // s2 maximally grows by 3800 * median(s1) = 2090079800 < 2^31 - $substract_value = ($temp_length < 3800) ? $temp_length : 3800; - $temp_length -= $substract_value; - - while (--$substract_value >= 0) - { - $s1 += ord($raw_image[$index]); - $s2 += $s1; - - $index++; - } - - $s1 %= 65521; - $s2 %= 65521; - } - $adler_hash = pack('N', ($s2 << 16) | $s1); - } - - // This is the same thing as gzcompress($raw_image, 0) but does not need zlib - $raw_image = pack('C3v2', 0x78, 0x01, 0x01, $length, ~$length) . $raw_image . $adler_hash; - - // The Zlib header + Adler hash make us add on 11 - $length += 11; - } - - // IDAT - $image .= self::png_chunk($length, 'IDAT', $raw_image); - - // IEND - $image .= self::png_chunk(0, 'IEND', ''); - - return $image; - } - - /** - * png image data - * Each 'data' element is base64_encoded uncompressed IDAT - */ - private static function define_filtered_pngs() - { - return array( - '0' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A///////////////////olFAkBAAAGDyA4P///M31/////////////wD////////////////0dAgAAAAAAAAAAAAEcPipFGHn////////////AP//////////////6DAAAAAAAAAAAAAAAAAALSEAN+T///////////8A//////////////xAAAAAAAAAAAAAAAAAAAAAACPA/////////////wD/////////////oAAAAAAAAAAAAAAAAAAAAAAAev//////////////AP////////////8oAAAAAAAAPNj/zDAAAAAAAABD//////////////8A////////////1AAAAAAAABjw////5BAAAAAAAADo/////////////wD///////////+QAAAAAAAAbP//////QgAAAAAAAKj/////////////AP///////////1wAAAAAAACs/////8AXAAAAAAAAcP////////////8A////////////OAAAAAAAAND////dNwAAAAAAAABI/////////////wD///////////8gAAAAAAAA4P//7koACwAAAAAAACT/////////////AP///////////wgAAAAAAAD///VqAwaPAAAAAAAAEP////////////8A////////////AAAAAAAAAP/8kQYDavUAAAAAAAAA/////////////wD///////////8AAAAAAAAA/6kNAEru/wAAAAAAAAD/////////////AP///////////wAAAAAAAADAIwA33f//AAAAAAAAAP////////////8A////////////FAAAAAAAADYAI8D///8AAAAAAAAQ/////////////wD///////////8kAAAAAAAAAA2p////5AAAAAAAACD/////////////AP///////////0gAAAAAAAAFkfz////UAAAAAAAAQP////////////8A////////////cAAAAAAAAET1/////7AAAAAAAABo/////////////wD///////////+oAAAAAAAAXfX/////sAAAAAAAAGj/////////////AAAAALgAAAAAAAAwAAAAAAAAAAAAAAD////////////oAAAAAAAACOT////oEAAAAAAAAOD/////////////AP////////////8+AAAAAAAAKMz/zDQAAAAAAAA0//////////////8A////////////7jgAAAAAAAAAAAAAAAAAAAAAAKT//////////////wD///////////VqAwIAAAAAAAAAAAAAAAAAAAA8////////////////AP//////////rQcDaVEAAAAAAAAAAAAAAAAAKOj///////////////8A///////////nblnu/IAIAAAAAAAAAAAAAFzw/////////////////wD////////////79////+iITCAAAAAgSITg////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////w==', - 'width' => 40 - ), - '1' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////8BAAAAAAAP//////////////////AP////////////////////////9sAAAAAAAA//////////////////8A////////////////////////pAAAAAAAAAD//////////////////wD//////////////////////6wEAAAAAAAAAP//////////////////AP////////////////////h4AAAAAAAAAAAA//////////////////8A//////////////////ygJAAAAAAAAAAAAAD//////////////////wD//////////////9x8HAAAAAAAAAAAAAAAAP//////////////////AP//////////////AAAAAAAAAAAAAAAAAAAA//////////////////8A//////////////8AAAAAAAAAAAAAAAAAAAD//////////////////wD//////////////wAAAAAAAAR4AAAAAAAAAP//////////////////AP//////////////AAAAAAA4zP8AAAAAAAAA//////////////////8A//////////////8AAAA4sP///wAAAAAAAAD//////////////////wD//////////////yR80P//////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////AAAAAAAAAP//////////////////AP////////////////////////8AAAAAAAAA//////////////////8A/////////////////////////wAAAAAAAAD//////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - '2' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP/////////////////okFAkCAAABCBIfNT///////////////////8A///////////////8hAgAAAAAAAAAAAAAAFTo/////////////////wD//////////////1QAAAAAAAAAAAAAAAAAACjo////////////////AP////////////+MAAAAAAAAAAAAAAAAAAAAADj///////////////8A////////////9BAAAAAAAAAAAAAAAAAAAAAAALD//////////////wD///////////+gAAAAAAAAAHjs+KwMAAAAAAAAVP//////////////AP///////////1gAAAAAAABM/////6QAAAAAAAAU//////////////8A////////////KAAAAAAAALj/////+AAAAAAAAAD//////////////wD///////////+MfGBMOCAI8P/////wAAAAAAAACP//////////////AP///////////////////////////5wAAAAAAAAw//////////////8A///////////////////////////oFAAAAAAAAHz//////////////wD/////////////////////////6CgAAAAAAAAE3P//////////////AP///////////////////////9ggAAAAAAAAAHT///////////////8A//////////////////////+0DAAAAAAAAAA8+P///////////////wD/////////////////////gAAAAAAAAAAAKOj/////////////////AP//////////////////9FAAAAAAAAAAADzw//////////////////8A/////////////////+g4AAAAAAAAAABk/P///////////////////wD////////////////oKAAAAAAAAAAMqP//////////////////////AP//////////////6CgAAAAAAAAAMNz///////////////////////8A//////////////g4AAAAAAAAAFT0/////////////////////////wD/////////////bAAAAAAAAABU/P//////////////////////////AP///////////8wAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A////////////SAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////9wAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////hAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////9AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////xAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - '3' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD////////////////8sGg0FAAAACA4cLz8////////////////////AP//////////////rBgAAAAAAAAAAAAAACTA//////////////////8A/////////////3QAAAAAAAAAAAAAAAAAAASs/////////////////wD///////////+YAAAAAAAAAAAAAAAAAAAAAAjc////////////////AP//////////6AwAAAAAAAAAAAAAAAAAAAAAAGT///////////////8A//////////94AAAAAAAABJDw/8g4AAAAAAAAHP///////////////wD//////////yAAAAAAAACE/////9gAAAAAAAAA////////////////AP///////////NSwiGQ4FOT//////AAAAAAAABD///////////////8A//////////////////////////+YAAAAAAAAVP///////////////wD//////////////////////P/ggAQAAAAAAATM////////////////AP////////////////////9gAAAAAAAAAAAElP////////////////8A/////////////////////0AAAAAAAAAAHLj//////////////////wD/////////////////////OAAAAAAAAAAwkPj/////////////////AP////////////////////8gAAAAAAAAAAAAINj///////////////8A/////////////////////xAAAAAAAAAAAAAAIPD//////////////wD/////////////////////uOz/4HgEAAAAAAAAhP//////////////AP///////////////////////////3wAAAAAAAAw//////////////8A////////////////////////////6AAAAAAAAAj//////////////wD/////////////////////////////AAAAAAAAAP//////////////AP//////////tJh8YEQoDNz//////+AAAAAAAAAY//////////////8A//////////88AAAAAAAAaP//////dAAAAAAAAEz//////////////wD//////////6QAAAAAAAAAdOD/5HQAAAAAAAAApP//////////////AP///////////CgAAAAAAAAAAAAAAAAAAAAAACD4//////////////8A////////////yAQAAAAAAAAAAAAAAAAAAAAEuP///////////////wD/////////////rAQAAAAAAAAAAAAAAAAABJD/////////////////AP//////////////zDQAAAAAAAAAAAAAACTA//////////////////8A/////////////////8BwOCAAAAAUNGi0/P///////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - '4' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP//////////////////////////nAAAAAAAAAD///////////////8A/////////////////////////8AEAAAAAAAAAP///////////////wD////////////////////////gGAAAAAAAAAAA////////////////AP//////////////////////9DAAAAAAAAAAAAD///////////////8A//////////////////////9UAAAAAAAAAAAAAP///////////////wD/////////////////////hAAAAAAAAAAAAAAA////////////////AP///////////////////7QAAAAAAAAAAAAAAAD///////////////8A///////////////////UDAAAAAAUAAAAAAAAAP///////////////wD/////////////////7CQAAAAABMAAAAAAAAAA////////////////AP////////////////xEAAAAAACU/wAAAAAAAAD///////////////8A////////////////cAAAAAAAZP//AAAAAAAAAP///////////////wD//////////////6AAAAAAADz8//8AAAAAAAAA////////////////AP/////////////IBAAAAAAc6P///wAAAAAAAAD///////////////8A////////////5BgAAAAADMz/////AAAAAAAAAP///////////////wD///////////g0AAAAAACk//////8AAAAAAAAA////////////////AP//////////XAAAAAAAfP///////wAAAAAAAAD///////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A////////////////////////////AAAAAAAAAP///////////////wD///////////////////////////8AAAAAAAAA////////////////AP///////////////////////////wAAAAAAAAD///////////////8A////////////////////////////AAAAAAAAAP///////////////wD///////////////////////////8AAAAAAAAA////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - '5' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP//////////////8AAAAAAAAAAAAAAAAAAAAAAA//////////////8A///////////////MAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////////6wAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////////iAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////////9kAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////////0QAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////////IAAAAAAAYP////////////////////////////8A//////////////wAAAAAAAB8/////////////////////////////wD/////////////3AAAAAAAAIj/////////////////////////////AP////////////+4AAAAAAAAoLRYHAAEKGTE//////////////////8A/////////////5QAAAAAAAAQAAAAAAAAAABY9P///////////////wD/////////////dAAAAAAAAAAAAAAAAAAAAAA89P//////////////AP////////////9QAAAAAAAAAAAAAAAAAAAAAABg//////////////8A/////////////zAAAAAAAAAAAAAAAAAAAAAAAADQ/////////////wD/////////////IAAAAAAAAGjY/+h4BAAAAAAAAGz/////////////AP//////////////9NS0lHSc//////90AAAAAAAALP////////////8A/////////////////////////////9QAAAAAAAAE/////////////wD//////////////////////////////wAAAAAAAAD/////////////AP/////////////////////////////8AAAAAAAAEP////////////8A////////////pIRwWEAgDOD//////8wAAAAAAAA8/////////////wD///////////9EAAAAAAAAaP//////ZAAAAAAAAHz/////////////AP///////////6QAAAAAAAAAaOD/4GQAAAAAAAAE4P////////////8A/////////////CQAAAAAAAAAAAAAAAAAAAAAAGD//////////////wD/////////////yAQAAAAAAAAAAAAAAAAAAAAc7P//////////////AP//////////////rAwAAAAAAAAAAAAAAAAAGNj///////////////8A////////////////0EAAAAAAAAAAAAAAAFTo/////////////////wD//////////////////8h4QCAAAAAcQHzU////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - '6' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////////////////+0ZCwMAAAUNGjI////////////////////AP/////////////////EMAAAAAAAAAAAAABM6P////////////////8A////////////////lAQAAAAAAAAAAAAAAAAo6P///////////////wD//////////////6wAAAAAAAAAAAAAAAAAAABI////////////////AP/////////////oEAAAAAAAAAAAAAAAAAAAAACw//////////////8A/////////////3AAAAAAAAAoxP/YPAAAAAAAAEj//////////////wD////////////4EAAAAAAACOD////YDCBAVGiAoP//////////////AP///////////7gAAAAAAABY//////////////////////////////8A////////////eAAAAAAAAJT//////////////////////////////wD///////////9MAAAAAAAAvP/IXBgABCx03P//////////////////AP///////////ygAAAAAAADcdAAAAAAAAAAEiP////////////////8A////////////FAAAAAAAAFAAAAAAAAAAAAAAcP///////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAlP//////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAQ8P////////////8A////////////AAAAAAAAAABAyP/kZAAAAAAAAACQ/////////////wD///////////8MAAAAAAAALPj/////WAAAAAAAAET/////////////AP///////////yQAAAAAAACY///////MAAAAAAAAFP////////////8A////////////SAAAAAAAAMD///////wAAAAAAAAA/////////////wD///////////9wAAAAAAAAvP///////wAAAAAAAAD/////////////AP///////////7QAAAAAAACI///////UAAAAAAAAJP////////////8A////////////+AwAAAAAACDw/////2wAAAAAAABY/////////////wD/////////////cAAAAAAAADC8/Ox4AAAAAAAAAKj/////////////AP/////////////oEAAAAAAAAAAAAAAAAAAAAAAk/P////////////8A//////////////+oAAAAAAAAAAAAAAAAAAAABLj//////////////wD///////////////+QAAAAAAAAAAAAAAAAAACQ////////////////AP////////////////+0JAAAAAAAAAAAAAAkuP////////////////8A///////////////////8sGg0FAAADCxgqPz//////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - '7' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAABP////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAy4/////////////wD//////////////////////////+QUAAAAAAAEuP//////////////AP/////////////////////////8QAAAAAAAAKT///////////////8A/////////////////////////4wAAAAAAAB0/////////////////wD////////////////////////cCAAAAAAANPz/////////////////AP///////////////////////0QAAAAAAATY//////////////////8A//////////////////////+0AAAAAAAAeP///////////////////wD//////////////////////CQAAAAAABTw////////////////////AP////////////////////+gAAAAAAAAkP////////////////////8A/////////////////////ywAAAAAABDw/////////////////////wD///////////////////+4AAAAAAAAbP//////////////////////AP///////////////////1wAAAAAAADQ//////////////////////8A///////////////////4DAAAAAAAMP///////////////////////wD//////////////////7QAAAAAAAB8////////////////////////AP//////////////////aAAAAAAAAMj///////////////////////8A//////////////////8oAAAAAAAM/P///////////////////////wD/////////////////8AAAAAAAAET/////////////////////////AP////////////////+0AAAAAAAAcP////////////////////////8A/////////////////4wAAAAAAACY/////////////////////////wD/////////////////WAAAAAAAAMD/////////////////////////AP////////////////80AAAAAAAA4P////////////////////////8A/////////////////xAAAAAAAAD4/////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - '8' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD////////////////////IdDQUAAAEIEiA1P//////////////////AP/////////////////gRAAAAAAAAAAAAAAAROD///////////////8A////////////////0BgAAAAAAAAAAAAAAAAAEMj//////////////wD///////////////AcAAAAAAAAAAAAAAAAAAAAHPD/////////////AP//////////////hAAAAAAAAAAAAAAAAAAAAAAAhP////////////8A//////////////8sAAAAAAAAKMz/zCgAAAAAAAAs/////////////wD//////////////wAAAAAAAADM////zAAAAAAAAAD/////////////AP//////////////BAAAAAAAAP//////AAAAAAAABP////////////8A//////////////8sAAAAAAAAzP///9QAAAAAAAAw/////////////wD//////////////3wAAAAAAAAoyP/YNAAAAAAAAIT/////////////AP//////////////7BgAAAAAAAAAAAAAAAAAAAAc8P////////////8A////////////////xBgAAAAAAAAAAAAAAAAAGNj//////////////wD/////////////////tAQAAAAAAAAAAAAAAACo////////////////AP///////////////HAAAAAAAAAAAAAAAAAAAAB8//////////////8A//////////////9gAAAAAAAAAAAAAAAAAAAAAAB8/////////////wD/////////////wAAAAAAAAABk4P/UWAAAAAAAAATQ////////////AP////////////9UAAAAAAAAaP//////XAAAAAAAAGT///////////8A/////////////xgAAAAAAADg///////cAAAAAAAAJP///////////wD/////////////AAAAAAAAAP////////8AAAAAAAAA////////////AP////////////8AAAAAAAAA4P//////3AAAAAAAAAT///////////8A/////////////ygAAAAAAABg//////9cAAAAAAAALP///////////wD/////////////ZAAAAAAAAABY1P/cXAAAAAAAAABw////////////AP/////////////QAAAAAAAAAAAAAAAAAAAAAAAABNz///////////8A//////////////9gAAAAAAAAAAAAAAAAAAAAAAB0/////////////wD///////////////Q8AAAAAAAAAAAAAAAAAAAAUPz/////////////AP////////////////x4CAAAAAAAAAAAAAAAEIT8//////////////8A///////////////////smFQwGAAAABg0ZKT0/////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - '9' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////////////////ysYCwMAAAUNGiw/P//////////////////AP////////////////+4JAAAAAAAAAAAAAAkuP////////////////8A////////////////lAQAAAAAAAAAAAAAAAAAkP///////////////wD//////////////8AEAAAAAAAAAAAAAAAAAAAAqP//////////////AP/////////////8JAAAAAAAAAAAAAAAAAAAAAAQ7P////////////8A/////////////6wAAAAAAAAAfOz8vCwAAAAAAABw/////////////wD/////////////WAAAAAAAAHD/////7BgAAAAAAAz4////////////AP////////////8kAAAAAAAA1P//////hAAAAAAAALT///////////8A/////////////wAAAAAAAAD///////+4AAAAAAAAcP///////////wD/////////////AAAAAAAAAPz//////8AAAAAAAABI////////////AP////////////8UAAAAAAAAzP//////lAAAAAAAACT///////////8A/////////////0QAAAAAAABY//////gsAAAAAAAADP///////////wD/////////////kAAAAAAAAABw5P/IPAAAAAAAAAAA////////////AP/////////////wEAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A//////////////+UAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD///////////////9wAAAAAAAAAAAAAFAAAAAAAAAU////////////AP////////////////+IBAAAAAAAAABw3AAAAAAAACj///////////8A///////////////////cdCwEABhcxP+8AAAAAAAATP///////////wD//////////////////////////////5AAAAAAAAB4////////////AP//////////////////////////////UAAAAAAAALj///////////8A//////////////+kgGxUQCAM2P///+AIAAAAAAAQ+P///////////wD//////////////0gAAAAAAAA42P/EKAAAAAAAAHD/////////////AP//////////////sAAAAAAAAAAAAAAAAAAAAAAQ6P////////////8A////////////////TAAAAAAAAAAAAAAAAAAAAKz//////////////wD////////////////oKAAAAAAAAAAAAAAAAASU////////////////AP/////////////////sUAAAAAAAAAAAAAAwxP////////////////8A////////////////////yHA0FAAADCxktP///////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'A' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD//////////////////+QAAAAAAAAAAAAAAOT/////////////////AP//////////////////kAAAAAAAAAAAAAAAkP////////////////8A//////////////////88AAAAAAAAAAAAAAA8/////////////////wD/////////////////5AAAAAAAAAAAAAAAAADk////////////////AP////////////////+QAAAAAAAAAAAAAAAAAJD///////////////8A/////////////////zwAAAAAAAAAAAAAAAAAPP///////////////wD////////////////kAAAAAAAAAAgAAAAAAAAA5P//////////////AP///////////////5AAAAAAAAAAgAAAAAAAAACQ//////////////8A////////////////PAAAAAAAAAz8HAAAAAAAADz//////////////wD//////////////+QAAAAAAAAAWP9kAAAAAAAAANz/////////////AP//////////////kAAAAAAAAACk/7wAAAAAAAAAhP////////////8A//////////////88AAAAAAAABOz//BQAAAAAAAAw/////////////wD/////////////4AAAAAAAAAA8////ZAAAAAAAAADc////////////AP////////////+EAAAAAAAAAIj///+8AAAAAAAAAIT///////////8A/////////////zAAAAAAAAAA2P////wQAAAAAAAAMP///////////wD////////////cAAAAAAAAACT//////1wAAAAAAAAA3P//////////AP///////////4QAAAAAAAAAAAAAAAAAAAAAAAAAAACE//////////8A////////////MAAAAAAAAAAAAAAAAAAAAAAAAAAAADD//////////wD//////////9wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAANz/////////AP//////////hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAhP////////8A//////////8wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAw/////////wD/////////3AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADc////////AP////////+EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIT///////8A/////////zAAAAAAAAAAhP///////////2QAAAAAAAAAMP///////wD////////cAAAAAAAAAADM////////////vAAAAAAAAAAA3P//////AP///////4QAAAAAAAAAHP/////////////4DAAAAAAAAACE//////8A////////MAAAAAAAAABk//////////////9cAAAAAAAAADD//////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'B' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAEDh83P///////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAEhP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAeP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAxP///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAABY////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAABT///////////8A//////////8AAAAAAAAAAP/////4zEwAAAAAAAAAAP///////////wD//////////wAAAAAAAAAA////////7AAAAAAAAAAQ////////////AP//////////AAAAAAAAAAD////////sAAAAAAAAAEj///////////8A//////////8AAAAAAAAAAP/////4zEQAAAAAAAAAtP///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAFz/////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAiA/P////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAIjPj//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAGKz/////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAJT///////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAABNz//////////wD//////////wAAAAAAAAAA///////sqCAAAAAAAAAAbP//////////AP//////////AAAAAAAAAAD/////////yAAAAAAAAAAs//////////8A//////////8AAAAAAAAAAP//////////AAAAAAAAAAT//////////wD//////////wAAAAAAAAAA/////////7wAAAAAAAAAAP//////////AP//////////AAAAAAAAAAD//////+ikGAAAAAAAAAAY//////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFT//////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAsP//////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAADj///////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAc6P///////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAATOj/////////////AP//////////AAAAAAAAAAAAAAAAAAAEIEBkkNj///////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'C' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP//////////////////5JRULBAAAAgkTIDQ//////////////////8A////////////////1FAAAAAAAAAAAAAAAABAyP///////////////wD//////////////4gEAAAAAAAAAAAAAAAAAAAElP//////////////AP////////////9wAAAAAAAAAAAAAAAAAAAAAAAAlP////////////8A////////////kAAAAAAAAAAAAAAAAAAAAAAAAAAEyP///////////wD//////////9wIAAAAAAAAAAAAAAAAAAAAAAAAAAAw////////////AP//////////WAAAAAAAAAAAWMz/8JwQAAAAAAAAAACw//////////8A/////////+wEAAAAAAAAAID//////9QMAAAAAAAAAET//////////wD/////////nAAAAAAAAAAo/P///////3wAAAAABDBspP//////////AP////////9gAAAAAAAAAIz/////////3BxQjMT0//////////////8A/////////zQAAAAAAAAAzP///////////////////////////////wD/////////GAAAAAAAAADo////////////////////////////////AP////////8AAAAAAAAAAP////////////////////////////////8A/////////wAAAAAAAAAA/////////////////////////////////wD/////////AAAAAAAAAAD/////////////////////////////////AP////////8cAAAAAAAAAOj///////////////////////////////8A/////////zgAAAAAAAAA0P/////////kIGio7P///////////////wD/////////bAAAAAAAAACg/////////5wAAAAAMHS49P//////////AP////////+oAAAAAAAAAEz/////////PAAAAAAAAAAc//////////8A//////////QIAAAAAAAAALz//////6QAAAAAAAAAAGT//////////wD//////////3AAAAAAAAAADIzo/+SEBAAAAAAAAAAAyP//////////AP//////////7BAAAAAAAAAAAAAAAAAAAAAAAAAAAED///////////8A////////////rAAAAAAAAAAAAAAAAAAAAAAAAAAE0P///////////wD/////////////fAAAAAAAAAAAAAAAAAAAAAAAAJz/////////////AP//////////////iAQAAAAAAAAAAAAAAAAAAASY//////////////8A////////////////yEAAAAAAAAAAAAAAAAA8yP///////////////wD//////////////////9yIUCwQAAAAIEB4yP//////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'D' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////////8AAAAAAAAAAAAAAAAADChQkOT/////////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAABGjw//////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAACDY/////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAABjk////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAED///////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAKj//////////wD///////////8AAAAAAAAAAP///+isSAAAAAAAAAAANP//////////AP///////////wAAAAAAAAAA////////hAAAAAAAAAAA2P////////8A////////////AAAAAAAAAAD/////////MAAAAAAAAACQ/////////wD///////////8AAAAAAAAAAP////////+MAAAAAAAAAFj/////////AP///////////wAAAAAAAAAA/////////8gAAAAAAAAAMP////////8A////////////AAAAAAAAAAD/////////5AAAAAAAAAAY/////////wD///////////8AAAAAAAAAAP//////////AAAAAAAAAAD/////////AP///////////wAAAAAAAAAA//////////8AAAAAAAAAAP////////8A////////////AAAAAAAAAAD//////////wAAAAAAAAAA/////////wD///////////8AAAAAAAAAAP/////////wAAAAAAAAABD/////////AP///////////wAAAAAAAAAA/////////9QAAAAAAAAAJP////////8A////////////AAAAAAAAAAD/////////qAAAAAAAAABI/////////wD///////////8AAAAAAAAAAP////////9QAAAAAAAAAHj/////////AP///////////wAAAAAAAAAA////////uAAAAAAAAAAAvP////////8A////////////AAAAAAAAAAD////w0HwEAAAAAAAAACT8/////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAoP//////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAADz8//////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAY6P///////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAKNz/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAACHT0//////////////8A////////////AAAAAAAAAAAAAAAAABg4bKj0/////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'E' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP//////////AAAAAAAAAAD///////////////////////////////8A//////////8AAAAAAAAAAP///////////////////////////////wD//////////wAAAAAAAAAA////////////////////////////////AP//////////AAAAAAAAAAD///////////////////////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////8AAAAAAAAAAP///////////////////////////////wD//////////wAAAAAAAAAA////////////////////////////////AP//////////AAAAAAAAAAD///////////////////////////////8A//////////8AAAAAAAAAAP///////////////////////////////wD//////////wAAAAAAAAAA////////////////////////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'F' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'G' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD//////////////////MB8TCgQAAAACCA4YJzs////////////////AP///////////////JQcAAAAAAAAAAAAAAAAAAhw8P////////////8A/////////////9gwAAAAAAAAAAAAAAAAAAAAAAAk2P///////////wD////////////EDAAAAAAAAAAAAAAAAAAAAAAAAAAc7P//////////AP//////////2AwAAAAAAAAAAAAAAAAAAAAAAAAAAABY//////////8A//////////wwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADQ/////////wD/////////kAAAAAAAAAAAEHzQ/P/gmCAAAAAAAAAAAFz/////////AP////////wcAAAAAAAAACjg////////8CwAAAAAAAAgWP////////8A////////vAAAAAAAAAAI2P//////////yBRAcJjI8P///////////wD///////94AAAAAAAAAGD/////////////////////////////////AP///////0AAAAAAAAAAsP////////////////////////////////8A////////IAAAAAAAAADc/////////////////////////////////wD///////8AAAAAAAAAAP///////wAAAAAAAAAAAAAAAAD/////////AP///////wAAAAAAAAAA////////AAAAAAAAAAAAAAAAAP////////8A////////AAAAAAAAAAD///////8AAAAAAAAAAAAAAAAA/////////wD///////8gAAAAAAAAAOD//////wAAAAAAAAAAAAAAAAD/////////AP///////0AAAAAAAAAAtP//////AAAAAAAAAAAAAAAAAP////////8A////////cAAAAAAAAABw//////8AAAAAAAAAAAAAAAAA/////////wD///////+8AAAAAAAAABDs////////////AAAAAAAAAAD/////////AP////////wYAAAAAAAAADz0//////////AAAAAAAAAAAP////////8A/////////5AAAAAAAAAAACCY4P//3KhcCAAAAAAAAAAA/////////wD/////////+CAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////AP//////////xAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIP////////8A////////////rAQAAAAAAAAAAAAAAAAAAAAAAAAAAGTw/////////wD/////////////vBQAAAAAAAAAAAAAAAAAAAAAADjI////////////AP//////////////8HAQAAAAAAAAAAAAAAAAAEiw//////////////8A//////////////////iwcEAgBAAABCA4aKDk/////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'H' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'I' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAP///////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAA////////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAD///////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'J' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAD//////////////wD///////////////////////////8AAAAAAAAAAP//////////////AP///////////////////////////wAAAAAAAAAA//////////////8A////////////////////////////AAAAAAAAAAj//////////////wD//////////+zMrIxwUDAQ//////wAAAAAAAAAIP//////////////AP//////////DAAAAAAAAADo////2AAAAAAAAAA0//////////////8A//////////8wAAAAAAAAAKj///+YAAAAAAAAAFj//////////////wD//////////2gAAAAAAAAAIND/yBgAAAAAAAAAkP//////////////AP//////////vAAAAAAAAAAAAAAAAAAAAAAAAADc//////////////8A////////////MAAAAAAAAAAAAAAAAAAAAAAAUP///////////////wD////////////EBAAAAAAAAAAAAAAAAAAAABjk////////////////AP////////////+sBAAAAAAAAAAAAAAAAAAY2P////////////////8A///////////////EMAAAAAAAAAAAAAAAVOj//////////////////wD/////////////////vHBAIAAAABg8fNT/////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'K' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////8AAAAAAAAAAP//////////wAQAAAAAAAAAAABw////////AP///////wAAAAAAAAAA/////////9AMAAAAAAAAAAAAcP////////8A////////AAAAAAAAAAD////////cGAAAAAAAAAAAAHD//////////wD///////8AAAAAAAAAAP//////6CgAAAAAAAAAAABs////////////AP///////wAAAAAAAAAA//////Q0AAAAAAAAAAAAVPz///////////8A////////AAAAAAAAAAD////8RAAAAAAAAAAAAFT8/////////////wD///////8AAAAAAAAAAP///1gAAAAAAAAAAABU/P//////////////AP///////wAAAAAAAAAA//9wAAAAAAAAAAAASPz///////////////8A////////AAAAAAAAAAD/jAAAAAAAAAAAADz0/////////////////wD///////8AAAAAAAAAAKQAAAAAAAAAAAA89P//////////////////AP///////wAAAAAAAAAABAAAAAAAAAAAFPT///////////////////8A////////AAAAAAAAAAAAAAAAAAAAAAAApP///////////////////wD///////8AAAAAAAAAAAAAAAAAAAAAAAAU8P//////////////////AP///////wAAAAAAAAAAAAAAAAAAAAAAAABk//////////////////8A////////AAAAAAAAAAAAAAAAAAAAAAAAAADE/////////////////wD///////8AAAAAAAAAAAAAAAAoEAAAAAAAACz8////////////////AP///////wAAAAAAAAAAAAAAGNiAAAAAAAAAAIj///////////////8A////////AAAAAAAAAAAAABjY//gYAAAAAAAACOD//////////////wD///////8AAAAAAAAAAAAY2P///5wAAAAAAAAASP//////////////AP///////wAAAAAAAAAAGNj//////CgAAAAAAAAAqP////////////8A////////AAAAAAAAAADI////////sAAAAAAAAAAc8P///////////wD///////8AAAAAAAAAAP//////////QAAAAAAAAABs////////////AP///////wAAAAAAAAAA///////////IAAAAAAAAAATI//////////8A////////AAAAAAAAAAD///////////9YAAAAAAAAADD8/////////wD///////8AAAAAAAAAAP///////////9wEAAAAAAAAAJD/////////AP///////wAAAAAAAAAA/////////////3AAAAAAAAAADOT///////8A////////AAAAAAAAAAD/////////////7BAAAAAAAAAAUP///////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'L' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAD/////////////////////////////AP////////////8AAAAAAAAAAP////////////////////////////8A/////////////wAAAAAAAAAA/////////////////////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////8AAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////wAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////////AAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'M' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A//////8AAAAAAAAAAAAAAHz//////3wAAAAAAAAAAAAAAP///////wD//////wAAAAAAAAAAAAAATP//////UAAAAAAAAAAAAAAA////////AP//////AAAAAAAAAAAAAAAc//////8cAAAAAAAAAAAAAAD///////8A//////8AAAAAAAAAAAAAAADw////8AAAAAAAAAAAAAAAAP///////wD//////wAAAAAAAAAAAAAAALz////AAAAAAAAAAAAAAAAA////////AP//////AAAAAAAAAAAAAAAAkP///5AAAAAAAAAAAAAAAAD///////8A//////8AAAAAAAAAAAAAAABc////ZAAAAAAAAAAAAAAAAP///////wD//////wAAAAAAAAAoAAAAADD///8wAAAAACQAAAAAAAAA////////AP//////AAAAAAAAAFwAAAAABPz//AgAAAAAXAAAAAAAAAD///////8A//////8AAAAAAAAAkAAAAAAA0P/UAAAAAACQAAAAAAAAAP///////wD//////wAAAAAAAADMAAAAAACg/6gAAAAAAMQAAAAAAAAA////////AP//////AAAAAAAAAPgEAAAAAHD/dAAAAAAE+AAAAAAAAAD///////8A//////8AAAAAAAAA/zQAAAAAQP9IAAAAADD/AAAAAAAAAP///////wD//////wAAAAAAAAD/bAAAAAAQ/xQAAAAAaP8AAAAAAAAA////////AP//////AAAAAAAAAP+gAAAAAADQAAAAAACc/wAAAAAAAAD///////8A//////8AAAAAAAAA/9QAAAAAAGgAAAAAAND/AAAAAAAAAP///////wD//////wAAAAAAAAD//wwAAAAAFAAAAAAM/P8AAAAAAAAA////////AP//////AAAAAAAAAP//RAAAAAAAAAAAADz//wAAAAAAAAD///////8A//////8AAAAAAAAA//94AAAAAAAAAAAAcP//AAAAAAAAAP///////wD//////wAAAAAAAAD//7AAAAAAAAAAAACo//8AAAAAAAAA////////AP//////AAAAAAAAAP//5AAAAAAAAAAAANz//wAAAAAAAAD///////8A//////8AAAAAAAAA////HAAAAAAAAAAQ////AAAAAAAAAP///////wD//////wAAAAAAAAD///9QAAAAAAAAAEz///8AAAAAAAAA////////AP//////AAAAAAAAAP///4gAAAAAAAAAfP///wAAAAAAAAD///////8A//////8AAAAAAAAA////vAAAAAAAAACw////AAAAAAAAAP///////wD//////wAAAAAAAAD////wAAAAAAAAAOz///8AAAAAAAAA////////AP//////AAAAAAAAAP////8sAAAAAAAc/////wAAAAAAAAD///////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'N' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////AAAAAAAAALD/////////////AAAAAAAAAP//////////AP////////8AAAAAAAAAFOj///////////8AAAAAAAAA//////////8A/////////wAAAAAAAAAASP///////////wAAAAAAAAD//////////wD/////////AAAAAAAAAAAAkP//////////AAAAAAAAAP//////////AP////////8AAAAAAAAAAAAI1P////////8AAAAAAAAA//////////8A/////////wAAAAAAAAAAAAAw+P///////wAAAAAAAAD//////////wD/////////AAAAAAAAAAAAAABw////////AAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAC8//////8AAAAAAAAA//////////8A/////////wAAAAAAAAAAAAAAABzs/////wAAAAAAAAD//////////wD/////////AAAAAAAAAAAAAAAAAFD/////AAAAAAAAAP//////////AP////////8AAAAAAAAAAAAAAAAAAJz///8AAAAAAAAA//////////8A/////////wAAAAAAAAAUAAAAAAAADNz//wAAAAAAAAD//////////wD/////////AAAAAAAAALQAAAAAAAAANPz/AAAAAAAAAP//////////AP////////8AAAAAAAAA/2wAAAAAAAAAfP8AAAAAAAAA//////////8A/////////wAAAAAAAAD/+CwAAAAAAAAExAAAAAAAAAD//////////wD/////////AAAAAAAAAP//0AQAAAAAAAAgAAAAAAAAAP//////////AP////////8AAAAAAAAA////jAAAAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAD/////RAAAAAAAAAAAAAAAAAD//////////wD/////////AAAAAAAAAP/////kFAAAAAAAAAAAAAAAAP//////////AP////////8AAAAAAAAA//////+sAAAAAAAAAAAAAAAA//////////8A/////////wAAAAAAAAD///////9kAAAAAAAAAAAAAAD//////////wD/////////AAAAAAAAAP////////QkAAAAAAAAAAAAAP//////////AP////////8AAAAAAAAA/////////8wEAAAAAAAAAAAA//////////8A/////////wAAAAAAAAD//////////4QAAAAAAAAAAAD//////////wD/////////AAAAAAAAAP///////////DwAAAAAAAAAAP//////////AP////////8AAAAAAAAA////////////4BAAAAAAAAAA//////////8A/////////wAAAAAAAAD/////////////qAAAAAAAAAD//////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'O' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A///////////////////0qGw4HAAAABw4aKT0/////////////////wD////////////////wcAwAAAAAAAAAAAAAAAho6P//////////////AP//////////////uBQAAAAAAAAAAAAAAAAAAAAMoP////////////8A/////////////6AEAAAAAAAAAAAAAAAAAAAAAAAAkP///////////wD///////////+4BAAAAAAAAAAAAAAAAAAAAAAAAAAAoP//////////AP//////////8BQAAAAAAAAAAAAAAAAAAAAAAAAAAAAM5P////////8A//////////9wAAAAAAAAAAAsrPD/7KQsAAAAAAAAAABg/////////wD/////////+BAAAAAAAAAAUPj///////hQAAAAAAAAAAjs////////AP////////+sAAAAAAAAABDw//////////AYAAAAAAAAAKD///////8A/////////2wAAAAAAAAAdP///////////3wAAAAAAAAAYP///////wD/////////OAAAAAAAAAC4////////////xAAAAAAAAAAw////////AP////////8cAAAAAAAAAOD////////////oAAAAAAAAABT///////8A/////////wAAAAAAAAAA//////////////8AAAAAAAAAAP///////wD/////////AAAAAAAAAAD//////////////wAAAAAAAAAA////////AP////////8AAAAAAAAAAP/////////////8AAAAAAAAAAD///////8A/////////xwAAAAAAAAA5P///////////+AAAAAAAAAAHP///////wD/////////NAAAAAAAAAC8////////////uAAAAAAAAAA4////////AP////////9oAAAAAAAAAHj///////////98AAAAAAAAAGT///////8A/////////6gAAAAAAAAAGPD/////////+BgAAAAAAAAApP///////wD/////////9AwAAAAAAAAAUPz///////xcAAAAAAAAAAjs////////AP//////////cAAAAAAAAAAALKjs//CwOAAAAAAAAAAAYP////////8A///////////wFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzk/////////wD///////////+4BAAAAAAAAAAAAAAAAAAAAAAAAAAAoP//////////AP////////////+QAAAAAAAAAAAAAAAAAAAAAAAAAJD///////////8A//////////////+sEAAAAAAAAAAAAAAAAAAAAAyg/////////////wD////////////////oZAgAAAAAAAAAAAAAAARg4P//////////////AP//////////////////9KhsOCAAAAAUMFyc7P////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'P' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP///////////wAAAAAAAAAAAAAAAAAACCxguP////////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAOOD//////////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAGOD/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAARP////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAxP///////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAABo////////////AP///////////wAAAAAAAAAA////6JwMAAAAAAAAADD///////////8A////////////AAAAAAAAAAD//////6AAAAAAAAAADP///////////wD///////////8AAAAAAAAAAP//////9AAAAAAAAAAA////////////AP///////////wAAAAAAAAAA///////0AAAAAAAAAAD///////////8A////////////AAAAAAAAAAD//////5gAAAAAAAAAHP///////////wD///////////8AAAAAAAAAAP///9iICAAAAAAAAABI////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAJD///////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAAAAAI6P///////////wD///////////8AAAAAAAAAAAAAAAAAAAAAAAAAAIT/////////////AP///////////wAAAAAAAAAAAAAAAAAAAAAAAABU/P////////////8A////////////AAAAAAAAAAAAAAAAAAAAAAAIhPz//////////////wD///////////8AAAAAAAAAAAAAAAAABCRMkOz/////////////////AP///////////wAAAAAAAAAA//////////////////////////////8A////////////AAAAAAAAAAD//////////////////////////////wD///////////8AAAAAAAAAAP//////////////////////////////AP///////////wAAAAAAAAAA//////////////////////////////8A////////////AAAAAAAAAAD//////////////////////////////wD///////////8AAAAAAAAAAP//////////////////////////////AP///////////wAAAAAAAAAA//////////////////////////////8A////////////AAAAAAAAAAD//////////////////////////////wD///////////8AAAAAAAAAAP//////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'Q' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////SoaDQcAAAAHDhoqPT///////////////////8A//////////////BwDAAAAAAAAAAAAAAACHDo/////////////////wD///////////+4FAAAAAAAAAAAAAAAAAAAABCo////////////////AP//////////nAQAAAAAAAAAAAAAAAAAAAAAAACQ//////////////8A/////////7gEAAAAAAAAAAAAAAAAAAAAAAAAAACg/////////////wD////////wFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAzo////////////AP///////3AAAAAAAAAAACyo8P/sqCwAAAAAAAAAAGT///////////8A///////4EAAAAAAAAABM+P///////FQAAAAAAAAACPT//////////wD//////7AAAAAAAAAAFPD/////////9BgAAAAAAAAApP//////////AP//////bAAAAAAAAAB4////////////fAAAAAAAAABk//////////8A//////84AAAAAAAAALz///////////+8AAAAAAAAADT//////////wD//////xwAAAAAAAAA6P///////////+QAAAAAAAAAHP//////////AP//////AAAAAAAAAAD//////////////wAAAAAAAAAA//////////8A//////8AAAAAAAAAAP//////////////AAAAAAAAAAD//////////wD//////wAAAAAAAAAA/P////////////8AAAAAAAAAAP//////////AP//////GAAAAAAAAADg////////////4AAAAAAAAAAc//////////8A//////84AAAAAAAAALT////MJHTo//+8AAAAAAAAADT//////////wD//////2wAAAAAAAAAdP///2AAABCg/3wAAAAAAAAAZP//////////AP//////rAAAAAAAAAAY9P/sCAAAAABMGAAAAAAAAACk//////////8A///////4EAAAAAAAAABU/P+0OAAAAAAAAAAAAAAACPT//////////wD///////94AAAAAAAAAAA4sPD/gAAAAAAAAAAAAABk////////////AP////////AcAAAAAAAAAAAAAAAAAAAAAAAAAAAADOT///////////8A/////////7wEAAAAAAAAAAAAAAAAAAAAAAAAAACQ/////////////wD//////////6wEAAAAAAAAAAAAAAAAAAAAAAAAABSs////////////AP///////////7gUAAAAAAAAAAAAAAAAAAAAAAAAAABAwP////////8A//////////////BwDAAAAAAAAAAAAAAABAgAAAAAAAA8/////////wD////////////////0qGg0GAAAABgwXJjkxBgAAAAAALD/////////AP//////////////////////////////////5DQAAAAk/P////////8A////////////////////////////////////+GwAAJD//////////wD//////////////////////////////////////8A49P//////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'R' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////wAAAAAAAAAAAAAAAAAAAAQgOGSk+P///////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAcuP//////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAEsP////////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQ6P///////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAADD///////////8A/////////wAAAAAAAAAA///////svDgAAAAAAAAACP///////////wD/////////AAAAAAAAAAD/////////7AAAAAAAAAAA////////////AP////////8AAAAAAAAAAP/////////cAAAAAAAAABD///////////8A/////////wAAAAAAAAAA//////DQoCQAAAAAAAAAQP///////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAACU////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAIPj///////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAzU/////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAA02P//////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAxctPz///////////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAEDY/////////////////wD/////////AAAAAAAAAAD/9LAsAAAAAAAAAAzc////////////////AP////////8AAAAAAAAAAP///+wkAAAAAAAAADD8//////////////8A/////////wAAAAAAAAAA/////8QAAAAAAAAAAJD//////////////wD/////////AAAAAAAAAAD//////1QAAAAAAAAAFPD/////////////AP////////8AAAAAAAAAAP//////3AQAAAAAAAAAgP////////////8A/////////wAAAAAAAAAA////////aAAAAAAAAAAM6P///////////wD/////////AAAAAAAAAAD////////oCAAAAAAAAABs////////////AP////////8AAAAAAAAAAP////////+AAAAAAAAAAATc//////////8A/////////wAAAAAAAAAA//////////AUAAAAAAAAAFj//////////wD/////////AAAAAAAAAAD//////////5AAAAAAAAAAAND/////////AP////////8AAAAAAAAAAP//////////+CQAAAAAAAAAQP////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'S' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP/////////////////8vHBEIAgAAAQgQHC8/P////////////////8A////////////////pCQAAAAAAAAAAAAAAAAcoP///////////////wD//////////////FwAAAAAAAAAAAAAAAAAAAAAXP//////////////AP////////////9oAAAAAAAAAAAAAAAAAAAAAAAAhP////////////8A////////////zAAAAAAAAAAAAAAAAAAAAAAAAAAI6P///////////wD///////////9cAAAAAAAAAAAAAAAAAAAAAAAAAACA////////////AP///////////xgAAAAAAAAAUOD/8KwkAAAAAAAAADj///////////8A////////////AAAAAAAAAAD0/////8wABCAgICxASP///////////wD///////////8MAAAAAAAAAMz/////////////////////////////AP///////////0AAAAAAAAAACFiQxPT///////////////////////8A////////////oAAAAAAAAAAAAAAAADBwtPT//////////////////wD////////////8QAAAAAAAAAAAAAAAAAAACFTA////////////////AP/////////////oOAAAAAAAAAAAAAAAAAAAAABM6P////////////8A///////////////4fAgAAAAAAAAAAAAAAAAAAAAY2P///////////wD/////////////////7IwwAAAAAAAAAAAAAAAAAAAo+P//////////AP/////////////////////koGw0BAAAAAAAAAAAAACU//////////8A///////////////////////////4uFgAAAAAAAAAADz//////////wD//////////2BgSEA0IBwA6P///////5QAAAAAAAAADP//////////AP//////////JAAAAAAAAACc/////////AAAAAAAAAAA//////////8A//////////9YAAAAAAAAACDo///////AAAAAAAAAABT//////////wD//////////6QAAAAAAAAAACCk7P/snBQAAAAAAAAAUP//////////AP//////////+BAAAAAAAAAAAAAAAAAAAAAAAAAAAACs//////////8A////////////kAAAAAAAAAAAAAAAAAAAAAAAAAAAOP///////////wD////////////8RAAAAAAAAAAAAAAAAAAAAAAAABjc////////////AP/////////////0PAAAAAAAAAAAAAAAAAAAAAAg2P////////////8A///////////////8hBQAAAAAAAAAAAAAAAAMdPT//////////////wD/////////////////+LRwSCAMAAAAHDhoqPT/////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'T' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD///////////////////8AAAAAAAAAAP//////////////////////AP///////////////////wAAAAAAAAAA//////////////////////8A////////////////////AAAAAAAAAAD//////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'U' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////AAAAAAAAAAD///////////8AAAAAAAAAAP//////////AP////////8AAAAAAAAAAP///////////wAAAAAAAAAA//////////8A/////////wAAAAAAAAAA////////////AAAAAAAAAAD//////////wD/////////JAAAAAAAAADk/////////+gAAAAAAAAAHP//////////AP////////9MAAAAAAAAAJz/////////nAAAAAAAAABE//////////8A/////////4gAAAAAAAAAHOj//////+ggAAAAAAAAAHz//////////wD/////////0AAAAAAAAAAAIJzs/+ykIAAAAAAAAAAA0P//////////AP//////////QAAAAAAAAAAAAAAAAAAAAAAAAAAAAED///////////8A///////////IBAAAAAAAAAAAAAAAAAAAAAAAAAAE0P///////////wD///////////+YAAAAAAAAAAAAAAAAAAAAAAAAAJj/////////////AP////////////+UBAAAAAAAAAAAAAAAAAAAAASU//////////////8A///////////////IPAAAAAAAAAAAAAAAAAAwyP///////////////wD/////////////////0IxYOCAIAAAEIEiAyP//////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'V' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD//////zAAAAAAAAAAYP//////////////ZAAAAAAAAAAw////////AP//////kAAAAAAAAAAU/P////////////8UAAAAAAAAAJD///////8A///////oBAAAAAAAAADE////////////xAAAAAAAAAAE7P///////wD///////9MAAAAAAAAAHD///////////94AAAAAAAAAEz/////////AP///////6gAAAAAAAAAJP///////////yQAAAAAAAAArP////////8A////////+BAAAAAAAAAA1P/////////YAAAAAAAAABT4/////////wD/////////aAAAAAAAAACE/////////4QAAAAAAAAAbP//////////AP/////////EAAAAAAAAADT/////////OAAAAAAAAADM//////////8A//////////8kAAAAAAAAAOT//////+QAAAAAAAAAKP///////////wD//////////4QAAAAAAAAAmP//////nAAAAAAAAACI////////////AP//////////5AAAAAAAAABE//////9EAAAAAAAABOT///////////8A////////////QAAAAAAAAAT0////9AgAAAAAAABI/////////////wD///////////+gAAAAAAAAAKT///+kAAAAAAAAAKj/////////////AP////////////QIAAAAAAAAXP///1wAAAAAAAAM+P////////////8A/////////////1wAAAAAAAAM+P/8DAAAAAAAAGT//////////////wD/////////////vAAAAAAAAAC8/7wAAAAAAAAAxP//////////////AP//////////////HAAAAAAAAGj/aAAAAAAAACT///////////////8A//////////////94AAAAAAAAHP8cAAAAAAAAhP///////////////wD//////////////9gAAAAAAAAAkAAAAAAAAADk////////////////AP///////////////zgAAAAAAAAQAAAAAAAAQP////////////////8A////////////////lAAAAAAAAAAAAAAAAACg/////////////////wD////////////////sCAAAAAAAAAAAAAAADPT/////////////////AP////////////////9QAAAAAAAAAAAAAABg//////////////////8A/////////////////7AAAAAAAAAAAAAAAMD//////////////////wD//////////////////BQAAAAAAAAAAAAc////////////////////AP//////////////////cAAAAAAAAAAAAHz///////////////////8A///////////////////MAAAAAAAAAAAA3P///////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'W' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A//8cAAAAAAAAALz/////4AAAAAAAAAAA6P////+8AAAAAAAAABz//wD//1QAAAAAAAAAjP////+gAAAAAAAAAACo/////4wAAAAAAAAAUP//AP//jAAAAAAAAABU/////2AAAAAAAAAAAGj/////VAAAAAAAAACM//8A///EAAAAAAAAACT/////IAAAAAAAAAAAKP////8kAAAAAAAAAMT//wD///gEAAAAAAAAAPD//+AAAAAAAAAAAAAA6P//8AAAAAAAAAAE9P//AP///zAAAAAAAAAAvP//oAAAAAAAAAAAAACo//+8AAAAAAAAADD///8A////bAAAAAAAAACM//9gAAAAAAAAAAAAAGT//4wAAAAAAAAAaP///wD///+kAAAAAAAAAFT//yAAAAAAAAAAAAAAIP//VAAAAAAAAACc////AP///9gAAAAAAAAAJP/gAAAAAAAAAAAAAAAA4P8kAAAAAAAAANT///8A/////xAAAAAAAAAA8KAAAAAAAAAAAAAAAACg8AAAAAAAAAAQ/////wD/////TAAAAAAAAAC8YAAAAAAAAAAAAAAAAGC8AAAAAAAAAET/////AP////+AAAAAAAAAAIwgAAAAAAAAAAAAAAAAIIwAAAAAAAAAfP////8A/////7gAAAAAAAAANAAAAAAAACwwAAAAAAAANAAAAAAAAACw/////wD/////8AAAAAAAAAAAAAAAAAAAdHgAAAAAAAAAAAAAAAAAAOz/////AP//////KAAAAAAAAAAAAAAAAAC4vAAAAAAAAAAAAAAAAAAg//////8A//////9gAAAAAAAAAAAAAAAACPj4CAAAAAAAAAAAAAAAAFj//////wD//////5QAAAAAAAAAAAAAAABE//9IAAAAAAAAAAAAAAAAkP//////AP//////0AAAAAAAAAAAAAAAAIj//4wAAAAAAAAAAAAAAADI//////8A///////8DAAAAAAAAAAAAAAAzP//1AAAAAAAAAAAAAAABPj//////wD///////88AAAAAAAAAAAAABT/////GAAAAAAAAAAAAAA0////////AP///////3QAAAAAAAAAAAAAWP////9gAAAAAAAAAAAAAHD///////8A////////sAAAAAAAAAAAAACg/////6QAAAAAAAAAAAAApP///////wD////////kAAAAAAAAAAAAAOT/////6AAAAAAAAAAAAADc////////AP////////8cAAAAAAAAAAAo////////MAAAAAAAAAAAEP////////8A/////////1QAAAAAAAAAAHD///////94AAAAAAAAAABM/////////wD/////////jAAAAAAAAAAAtP///////7wAAAAAAAAAAID/////////AP/////////EAAAAAAAAAAT0////////+AgAAAAAAAAAuP////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'X' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD///////9UAAAAAAAAAKz///////////+sAAAAAAAAAFD/////////AP///////+QQAAAAAAAAFOT/////////8BwAAAAAAAAM5P////////8A/////////5gAAAAAAAAATP////////9kAAAAAAAAAJD//////////wD//////////0AAAAAAAAAAoP//////wAAAAAAAAAA0/P//////////AP//////////2AgAAAAAAAAQ4P////gkAAAAAAAABMz///////////8A////////////iAAAAAAAAABA////dAAAAAAAAABw/////////////wD////////////8MAAAAAAAAACU/9AEAAAAAAAAHPD/////////////AP/////////////IBAAAAAAAAAzYMAAAAAAAAACs//////////////8A//////////////90AAAAAAAAABAAAAAAAAAATP///////////////wD///////////////QgAAAAAAAAAAAAAAAAAAzg////////////////AP///////////////7wAAAAAAAAAAAAAAAAAjP////////////////8A/////////////////2AAAAAAAAAAAAAAADD8/////////////////wD/////////////////7BQAAAAAAAAAAAAEyP//////////////////AP/////////////////gDAAAAAAAAAAAAAjY//////////////////8A/////////////////0AAAAAAAAAAAAAAADj8/////////////////wD///////////////+UAAAAAAAAAAAAAAAAAJD/////////////////AP//////////////4AwAAAAAAAAAAAAAAAAADOD///////////////8A//////////////9AAAAAAAAAAAAAAAAAAAAAQP///////////////wD/////////////nAAAAAAAAAAAWAAAAAAAAAAAlP//////////////AP///////////+QQAAAAAAAAAGD/YAAAAAAAAAAM4P////////////8A////////////TAAAAAAAAAAs9P/0LAAAAAAAAABM/////////////wD//////////6AAAAAAAAAADNT////UDAAAAAAAAACg////////////AP/////////kEAAAAAAAAACg//////+gAAAAAAAAABDk//////////8A/////////0wAAAAAAAAAYP////////9gAAAAAAAAAEz//////////wD///////+oAAAAAAAAACz0//////////QsAAAAAAAAAKT/////////AP//////7BQAAAAAAAAM1P///////////9QMAAAAAAAAFOz///////8A//////9UAAAAAAAAAKD//////////////6AAAAAAAAAAVP///////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'Y' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP///////1QAAAAAAAAAAGj//////////2gAAAAAAAAAAFT///////8A////////5BAAAAAAAAAAAMT////////EAAAAAAAAAAAQ5P///////wD/////////mAAAAAAAAAAAKPj/////+CgAAAAAAAAAAJj/////////AP//////////PAAAAAAAAAAAgP////+AAAAAAAAAAAA8//////////8A///////////YCAAAAAAAAAAE2P//2AQAAAAAAAAACNj//////////wD///////////+AAAAAAAAAAAA4//84AAAAAAAAAACA////////////AP////////////woAAAAAAAAAACUlAAAAAAAAAAAKPz///////////8A/////////////8gAAAAAAAAAABAQAAAAAAAAAADI/////////////wD//////////////2wAAAAAAAAAAAAAAAAAAAAAbP//////////////AP//////////////8BwAAAAAAAAAAAAAAAAAABzw//////////////8A////////////////tAAAAAAAAAAAAAAAAAAAtP///////////////wD/////////////////VAAAAAAAAAAAAAAAAFT/////////////////AP/////////////////oEAAAAAAAAAAAAAAQ6P////////////////8A//////////////////+cAAAAAAAAAAAAAJz//////////////////wD///////////////////9AAAAAAAAAAABA////////////////////AP///////////////////9gAAAAAAAAAANj///////////////////8A/////////////////////wAAAAAAAAAA/////////////////////wD/////////////////////AAAAAAAAAAD/////////////////////AP////////////////////8AAAAAAAAAAP////////////////////8A/////////////////////wAAAAAAAAAA/////////////////////wD/////////////////////AAAAAAAAAAD/////////////////////AP////////////////////8AAAAAAAAAAP////////////////////8A/////////////////////wAAAAAAAAAA/////////////////////wD/////////////////////AAAAAAAAAAD/////////////////////AP////////////////////8AAAAAAAAAAP////////////////////8A/////////////////////wAAAAAAAAAA/////////////////////wD/////////////////////AAAAAAAAAAD/////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - 'Z' => array( - 'data' => 'AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAA//////////////8A//////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAD//////////////wD//////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAP//////////////AP//////////AAAAAAAAAAAAAAAAAAAAAAAAAAAQ//////////////8A/////////////////////////1AAAAAAAAAABLz//////////////wD///////////////////////98AAAAAAAAAACY////////////////AP//////////////////////pAAAAAAAAAAAaP////////////////8A/////////////////////8QIAAAAAAAAAET8/////////////////wD////////////////////gGAAAAAAAAAAo9P//////////////////AP//////////////////9CwAAAAAAAAAFNz///////////////////8A//////////////////xMAAAAAAAAAATA/////////////////////wD/////////////////eAAAAAAAAAAAnP//////////////////////AP///////////////5wAAAAAAAAAAHT///////////////////////8A///////////////ABAAAAAAAAABM/P///////////////////////wD/////////////3BQAAAAAAAAALPT/////////////////////////AP////////////QoAAAAAAAAABjg//////////////////////////8A///////////8SAAAAAAAAAAExP///////////////////////////wD//////////2wAAAAAAAAAAKD/////////////////////////////AP////////+YAAAAAAAAAAB8//////////////////////////////8A/////////wQAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA/////////////wD/////////AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/////////////AP////////8AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8A/////////////////////////////////////////////////////wD/////////////////////////////////////////////////////AP////////////////////////////////////////////////////8=', - 'width' => 40 - ), - ); - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/captcha/captcha_plugin.php b/phpBB/includes/captcha/captcha_plugin.php deleted file mode 100644 index 3e8e508206..0000000000 --- a/phpBB/includes/captcha/captcha_plugin.php +++ /dev/null @@ -1,98 +0,0 @@ -<?php - -interface phpbb_captcha_plugin -{ - /** - * Initiates the CAPTCHA to validate codes. - * @param int $type the type as defined in constants.php - */ - function init($type); - - - /** - * Returns true if the captcha will work on the current install - */ - static function is_available(); - - /** - * Returns the translated pretty name of the captcha. - */ - static function get_name(); - - /** - * Returns the class name of the captcha. - */ - static function get_class_name(); - - /** - * Returns an instance; does not have to be the same instance twice. - */ - static function get_instance(); - - /** - * Returns the HTML needed to embed the captcha in another template - */ - function get_template(); - - - /** - * Delivers the image of image based captchas; not required for text/remote etc CAPTCHAs - */ - function execute(); - - /** - * Returns the HTML needed to display a demo of the captcha - */ - function get_demo_template($id); - - - /** - * Delivers the demo image of image based captchas; not required for text/remote etc CAPTCHAs - */ - function execute_demo(); - - /** - * Clears leftover entries in the database. - */ - static function garbage_collect($type); - - - /** - * Clears all entries from the database if the CAPTCHA is replaced - */ - function uninstall(); - - /** - * Sets up the CAPTCHA when it is selected in the ACP. - */ - function install(); - - - /** - * Checks the captcha; returns false if the code was correct; a translated error string otherwise - */ - function validate(); - - /** - * Prepares the captcha to ask a new question; required call on failed answers - */ - function reset(); - - /** - * Displays the configuration options in the ACP - */ - function acp_page($id, &$module); - - /** - * Returns the entries for the hidden field array needed to preserve the current state. - */ - function get_hidden_fields(); - - - /** - * Returns the number of solving attempts of the current user - */ - function get_attempt_count(); -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/captcha/plugins/captcha_abstract.php b/phpBB/includes/captcha/plugins/captcha_abstract.php deleted file mode 100644 index 4f494b9c69..0000000000 --- a/phpBB/includes/captcha/plugins/captcha_abstract.php +++ /dev/null @@ -1,282 +0,0 @@ -<?php -/** -* -* @package VC -* @version $Id$ -* @copyright (c) 2006 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - - -/** -* This class holds the code shared by the two default 3.0 CAPTCHAs. -*/ -abstract class phpbb_default_captcha implements phpbb_captcha_plugin -{ - protected $confirm_id; - protected $confirm_code; - protected $code; - protected $seed; - protected $type; - protected $solved = false; - - protected $min_chars = 4; - protected $max_chars = 7; - - function init($type) - { - // read input - $this->confirm_id = request_var('confirm_id', ''); - $this->confirm_code = request_var('confirm_code', ''); - $this->type = (int) $type; - - if (!strlen($this->confirm_id)) - { - // we have no confirm ID, better get ready to display something - $this->generate_code(); - } - } - - function execute_demo() - { - $this->code = gen_rand_string(mt_rand($this->min_chars, $this->max_chars)); - $this->seed = hexdec(substr(unique_id(), 4, 10)); - - // compute $seed % 0x7fffffff - $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff); - - captcha::execute($this->code, $this->seed); - } - - - function execute() - { - if (empty($this->code)) - { - if (!$this->load_code()) - { - // invalid request, bail out - return false; - } - } - captcha::execute($this->code, $this->seed); - } - - - function get_template() - { - phpbb::$template->set_filenames(array( - 'captcha' => 'captcha_default.html', - )); - - phpbb::$template->assign_vars(array( - 'CONFIRM_IMAGE' => append_sid('ucp', 'mode=confirm&confirm_id=' . $this->confirm_id . '&type=' . $this->type), - 'CONFIRM_ID' => $this->confirm_id, - )); - - return phpbb::$template->assign_display('captcha'); - } - - function get_demo_template($id) - { - phpbb::$template->set_filenames(array( - 'captcha_demo' => 'captcha_default_acp_demo.html', - )); - // acp_captcha has a delivery function; let's use it - phpbb::$template->assign_vars(array( - 'CONFIRM_IMAGE' => append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, 'captcha_demo=1&mode=visual&i=' . $id . '&select_captcha=' . $this->get_class_name()), - 'CONFIRM_ID' => $this->confirm_id, - )); - - return phpbb::$template->assign_display('captcha_demo'); - } - - function get_hidden_fields() - { - $hidden_fields = array(); - - // this is required for postig.php - otherwise we would forget about the captcha being already solved - if ($this->solved) - { - $hidden_fields['confirm_code'] = $this->confirm_code; - } - $hidden_fields['confirm_id'] = $this->confirm_id; - return $hidden_fields; - } - - static function garbage_collect($type) - { - $sql = 'SELECT DISTINCT c.session_id - FROM ' . CONFIRM_TABLE . ' c - LEFT JOIN ' . SESSIONS_TABLE . ' s ON (c.session_id = s.session_id) - WHERE s.session_id IS NULL' . - ((empty($type)) ? '' : ' AND c.confirm_type = ' . (int) $type); - $result = phpbb::$db->sql_query($sql); - - if ($row = phpbb::$db->sql_fetchrow($result)) - { - $sql_in = array(); - do - { - $sql_in[] = (string) $row['session_id']; - } - while ($row = phpbb::$db->sql_fetchrow($result)); - - if (sizeof($sql_in)) - { - $sql = 'DELETE FROM ' . CONFIRM_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('session_id', $sql_in); - phpbb::$db->sql_query($sql); - } - } - phpbb::$db->sql_freeresult($result); - } - - function uninstall() - { - self::garbage_collect(0); - } - - function install() - { - return; - } - - function validate() - { - $this->confirm_code = request_var('confirm_code', ''); - - if (!$this->confirm_id) - { - $error = phpbb::$user->lang['CONFIRM_CODE_WRONG']; - } - else - { - if ($this->check_code()) - { - // $this->delete_code(); commented out to allow posting.php to repeat the question - $this->solved = true; - } - else - { - $error = phpbb::$user->lang['CONFIRM_CODE_WRONG']; - } - } - - if (strlen($error)) - { - // okay, inorect answer. Let's ask a new question - $this->generate_code(); - return $error; - } - else - { - return false; - } - } - - - /** - * The old way to generate code, suitable for GD and non-GD. Resets the internal state. - */ - protected function generate_code() - { - $this->code = gen_rand_string(mt_rand($this->min_chars, $this->max_chars)); - $this->confirm_id = md5(unique_id(phpbb::$user->ip)); - $this->seed = hexdec(substr(unique_id(), 4, 10)); - $this->solved = false; - - // compute $seed % 0x7fffffff - $this->seed -= 0x7fffffff * floor($this->seed / 0x7fffffff); - - $sql = 'INSERT INTO ' . CONFIRM_TABLE . ' ' . phpbb::$db->sql_build_array('INSERT', array( - 'confirm_id' => (string) $this->confirm_id, - 'session_id' => (string) phpbb::$user->session_id, - 'confirm_type' => (int) $this->type, - 'code' => (string) $this->code, - 'seed' => (int) $this->seed) - ); - phpbb::$db->sql_query($sql); - } - - /** - * Look up everything we need for painting&checking. - */ - protected function load_code() - { - $sql = 'SELECT code, seed - FROM ' . CONFIRM_TABLE . " - WHERE confirm_id = '" . phpbb::$db->sql_escape($this->confirm_id) . "' - AND session_id = '" . phpbb::$db->sql_escape(phpbb::$user->session_id) . "' - AND confirm_type = " . $this->type; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - if ($row) - { - $this->code = $row['code']; - $this->seed = $row['seed']; - return true; - } - return false; - - } - - protected function check_code() - { - if (empty($this->code)) - { - if (!$this->load_code()) - { - return false; - } - } - return (strcasecmp($this->code, $this->confirm_code) === 0); - } - - protected function delete_code() - { - $sql = 'DELETE FROM ' . CONFIRM_TABLE . " - WHERE confirm_id = '" . phpbb::$db->sql_escape($this->confirm_id) . "' - AND session_id = '" . phpbb::$db->sql_escape(phpbb::$user->session_id) . "' - AND confirm_type = " . $this->type; - phpbb::$db->sql_query($sql); - } - - function get_attempt_count() - { - $sql = 'SELECT COUNT(session_id) AS attempts - FROM ' . CONFIRM_TABLE . " - WHERE session_id = '" . phpbb::$db->sql_escape(phpbb::$user->session_id) . "' - AND confirm_type = " . $this->type; - $result = phpbb::$db->sql_query($sql); - $attempts = (int) phpbb::$db->sql_fetchfield('attempts'); - phpbb::$db->sql_freeresult($result); - - return $attempts; - } - - - function reset() - { - $sql = 'DELETE FROM ' . CONFIRM_TABLE . " - WHERE session_id = '" . phpbb::$db->sql_escape(phpbb::$user->session_id) . "' - AND confirm_type = " . (int) $this->type; - phpbb::$db->sql_query($sql); - - // we leave the class usable by generating a new question - $this->generate_code(); - } - -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php deleted file mode 100644 index f795349f3d..0000000000 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_plugin.php +++ /dev/null @@ -1,101 +0,0 @@ -<?php -/** -* -* @package VC -* @version $Id$ -* @copyright (c) 2006 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Placeholder for autoload -*/ -include_once(PHPBB_ROOT_PATH . 'includes/captcha/plugins/captcha_abstract.' . PHP_EXT); - -class phpbb_captcha_gd extends phpbb_default_captcha implements phpbb_captcha_plugin -{ - - function __construct() - { - include_once(PHPBB_ROOT_PATH . 'includes/captcha/captcha_gd.' . PHP_EXT); - } - - public static function get_instance() - { - return new phpbb_captcha_gd(); - } - - static function is_available() - { - return (@extension_loaded('gd') || can_load_dll('gd')); - } - - static function get_name() - { - return 'CAPTCHA_GD'; - } - - static function get_class_name() - { - return 'phpbb_captcha_gd'; - } - - function acp_page($id, &$module) - { - $captcha_vars = array( - 'captcha_gd_x_grid' => 'CAPTCHA_GD_X_GRID', - 'captcha_gd_y_grid' => 'CAPTCHA_GD_Y_GRID', - 'captcha_gd_foreground_noise' => 'CAPTCHA_GD_FOREGROUND_NOISE', - 'captcha_gd' => 'CAPTCHA_GD_PREVIEWED' - ); - - $module->tpl_name = 'captcha_gd_acp'; - $module->page_title = 'ACP_VC_SETTINGS'; - $form_key = 'acp_captcha'; - add_form_key($form_key); - - $submit = request_var('submit', ''); - - if ($submit && check_form_key($form_key)) - { - $captcha_vars = array_keys($captcha_vars); - foreach ($captcha_vars as $captcha_var) - { - $value = request_var($captcha_var, 0); - if ($value >= 0) - { - set_config($captcha_var, $value); - } - } - trigger_error(phpbb::$user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action)); - } - else if ($submit) - { - trigger_error(phpbb::$user->lang['FORM_INVALID'] . adm_back_link($module->u_action)); - } - else - { - foreach ($captcha_vars as $captcha_var => $template_var) - { - $var = request_var($captcha_var, (int) phpbb::$config[$captcha_var]); - phpbb::$template->assign_var($template_var, $var); - } - - phpbb::$template->assign_vars(array( - 'CAPTCHA_PREVIEW' => $this->get_demo_template($id), - 'CAPTCHA_NAME' => $this->get_class_name(), - )); - - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php deleted file mode 100644 index 1dbebcdbd6..0000000000 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_gd_wave_plugin.php +++ /dev/null @@ -1,57 +0,0 @@ -<?php -/** -* -* @package VC -* @version $Id$ -* @copyright (c) 2006 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Placeholder for autoload -*/ -include_once(PHPBB_ROOT_PATH . 'includes/captcha/plugins/captcha_abstract.' . PHP_EXT); - -class phpbb_captcha_gd_wave extends phpbb_default_captcha implements phpbb_captcha_plugin -{ - - function __construct() - { - include_once(PHPBB_ROOT_PATH . 'includes/captcha/captcha_gd_wave.' . PHP_EXT); - } - - public static function get_instance() - { - return new phpbb_captcha_gd_wave(); - } - - static function is_available() - { - return (@extension_loaded('gd') || can_load_dll('gd')); - } - - static function get_name() - { - return 'CAPTCHA_GD_WAVE'; - } - - static function get_class_name() - { - return 'phpbb_captcha_gd_wave'; - } - - function acp_page($id, &$module) - { - trigger_error(phpbb::$user->lang['CAPTCHA_NO_OPTIONS'] . adm_back_link($module->u_action)); - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php b/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php deleted file mode 100644 index f76c42338e..0000000000 --- a/phpBB/includes/captcha/plugins/phpbb_captcha_nogd_plugin.php +++ /dev/null @@ -1,55 +0,0 @@ -<?php -/** -* -* @package VC -* @version $Id$ -* @copyright (c) 2006 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -include_once(PHPBB_ROOT_PATH . 'includes/captcha/plugins/captcha_abstract.' . PHP_EXT); - -class phpbb_captcha_nogd extends phpbb_default_captcha implements phpbb_captcha_plugin -{ - - function __construct() - { - include_once(PHPBB_ROOT_PATH . 'includes/captcha/captcha_non_gd.' . PHP_EXT); - } - - public static function get_instance() - { - return new phpbb_captcha_nogd(); - } - - static function is_available() - { - return true; - } - - static function get_name() - { - return 'CAPTCHA_NO_GD'; - } - - static function get_class_name() - { - return 'phpbb_captcha_nogd'; - } - - - function acp_page($id, &$module) - { - trigger_error(phpbb::$user->lang['CAPTCHA_NO_OPTIONS'] . adm_back_link($module->u_action)); - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php b/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php deleted file mode 100644 index a27909baee..0000000000 --- a/phpBB/includes/captcha/plugins/phpbb_recaptcha_plugin.php +++ /dev/null @@ -1,306 +0,0 @@ -<?php -/** -* -* @package VC -* @version $Id$ -* @copyright (c) 2006 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -// we need the classic captcha code for tracking solutions and attempts -include_once(PHPBB_ROOT_PATH . 'includes/captcha/plugins/captcha_abstract.' . PHP_EXT); - -class phpbb_recaptcha extends phpbb_default_captcha implements phpbb_captcha_plugin -{ - const recaptcha_server = 'http://api.recaptcha.net'; - const recaptcha_verify_server = 'api-verify.recaptcha.net'; - protected $challenge; - protected $response; - - function init($type) - { - phpbb::$user->add_lang('recaptcha'); - parent::init($type); - - $this->challenge = request_var('recaptcha_challenge_field', ''); - $this->response = request_var('recaptcha_response_field', ''); - } - - public static function get_instance() - { - return new phpbb_recaptcha(); - } - - static function is_available() - { - phpbb::$user->add_lang('recaptcha'); - return (isset(phpbb::$config['recaptcha_pubkey']) && !empty(phpbb::$config['recaptcha_pubkey'])); - } - - static function get_name() - { - return 'CAPTCHA_RECAPTCHA'; - } - - static function get_class_name() - { - return 'phpbb_recaptcha'; - } - - function acp_page($id, &$module) - { - $captcha_vars = array( - 'recaptcha_pubkey' => 'RECAPTCHA_PUBKEY', - 'recaptcha_privkey' => 'RECAPTCHA_PRIVKEY', - ); - - $module->tpl_name = 'captcha_recaptcha_acp'; - $module->page_title = 'ACP_VC_SETTINGS'; - $form_key = 'acp_captcha'; - add_form_key($form_key); - - $submit = request_var('submit', ''); - - if ($submit && check_form_key($form_key)) - { - $captcha_vars = array_keys($captcha_vars); - foreach ($captcha_vars as $captcha_var) - { - $value = request_var($captcha_var, ''); - if ($value) - { - set_config($captcha_var, $value); - } - } - trigger_error(phpbb::$user->lang['CONFIG_UPDATED'] . adm_back_link($module->u_action)); - } - else if ($submit) - { - trigger_error(phpbb::$user->lang['FORM_INVALID'] . adm_back_link($module->u_action)); - } - else - { - foreach ($captcha_vars as $captcha_var => $template_var) - { - $var = request_var($captcha_var, (isset(phpbb::$config[$captcha_var])) ? (string) phpbb::$config[$captcha_var] : ''); - phpbb::$template->assign_var($template_var, $var); - } - - phpbb::$template->assign_vars(array( - 'CAPTCHA_PREVIEW' => $this->get_demo_template($id), - 'CAPTCHA_NAME' => $this->get_class_name(), - )); - - } - } - - - // not needed - function execute_demo() - { - } - - - // not needed - function execute() - { - } - - - function get_template() - { - phpbb::$template->set_filenames(array( - 'captcha' => 'captcha_recaptcha.html', - )); - - phpbb::$template->assign_vars(array( - 'RECAPTCHA_SERVER' => self::recaptcha_server, - 'RECAPTCHA_PUBKEY' => isset(phpbb::$config['recaptcha_pubkey']) ? phpbb::$config['recaptcha_pubkey'] : '', - 'RECAPTCHA_ERRORGET' => '', - 'S_RECAPTCHA_AVAILABLE' => self::is_available(), - )); - - return phpbb::$template->assign_display('captcha'); - } - - function get_demo_template($id) - { - return $this->get_template(); - } - - function get_hidden_fields() - { - $hidden_fields = array(); - - // this is required for postig.php - otherwise we would forget about the captcha being already solved - if ($this->solved) - { - $hidden_fields['confirm_code'] = $this->confirm_code; - } - $hidden_fields['confirm_id'] = $this->confirm_id; - return $hidden_fields; - } - - function uninstall() - { - self::garbage_collect(0); - } - - function install() - { - return; - } - - function validate() - { - if (!parent::validate()) - { - return false; - } - else - { - return $this->recaptcha_check_answer(); - } - } - - -// Code from here on is based on recaptchalib.php -/* - * This is a PHP library that handles calling reCAPTCHA. - * - Documentation and latest version - * http://recaptcha.net/plugins/php/ - * - Get a reCAPTCHA API Key - * http://recaptcha.net/api/getkey - * - Discussion group - * http://groups.google.com/group/recaptcha - * - * Copyright (c) 2007 reCAPTCHA -- http://recaptcha.net - * AUTHORS: - * Mike Crawford - * Ben Maurer - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to deal - * in the Software without restriction, including without limitation the rights - * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell - * copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN - * THE SOFTWARE. - */ - - /** - * Submits an HTTP POST to a reCAPTCHA server - * @param string $host - * @param string $path - * @param array $data - * @param int port - * @return array response - */ - protected function _recaptcha_http_post($host, $path, $data, $port = 80) - { - $req = $this->_recaptcha_qsencode ($data); - - $http_request = "POST $path HTTP/1.0\r\n"; - $http_request .= "Host: $host\r\n"; - $http_request .= "Content-Type: application/x-www-form-urlencoded;\r\n"; - $http_request .= "Content-Length: " . strlen($req) . "\r\n"; - $http_request .= "User-Agent: reCAPTCHA/PHP/phpBB\r\n"; - $http_request .= "\r\n"; - $http_request .= $req; - - $response = ''; - if (false == ($fs = @fsockopen($host, $port, $errno, $errstr, 10))) - { - trigger_error('Could not open socket', E_USER_ERROR); - } - - fwrite($fs, $http_request); - - while (!feof($fs)) - { - // One TCP-IP packet - $response .= fgets($fs, 1160); - } - fclose($fs); - - $response = explode("\r\n\r\n", $response, 2); - - return $response; - } - - /** - * Calls an HTTP POST function to verify if the user's guess was correct - * @param array $extra_params an array of extra variables to post to the server - * @return ReCaptchaResponse - */ - protected function recaptcha_check_answer($extra_params = array()) - { - // discard spam submissions - if ($this->challenge == null || strlen($this->challenge) == 0 || $this->response == null || strlen($this->response) == 0) - { - return phpbb::$user->lang['RECAPTCHA_INCORRECT']; - } - - $response = $this->_recaptcha_http_post(self::recaptcha_verify_server, '/verify', array( - 'privatekey' => phpbb::$config['recaptcha_privkey'], - 'remoteip' => phpbb::$user->ip, - 'challenge' => $this->challenge, - 'response' => $this->response, - ) + $extra_params - ); - - $answers = explode("\n", $response[1]); - - if (trim($answers[0]) === 'true') - { - $this->solved = true; - return false; - } - else - { - if ($answers[1] === 'incorrect-captcha-sol') - { - return phpbb::$user->lang['RECAPTCHA_INCORRECT']; - } - } - } - - /** - * Encodes the given data into a query string format - * @param $data - array of string elements to be encoded - * @return string - encoded request - */ - protected function _recaptcha_qsencode($data) - { - $req = ''; - - foreach ($data as $key => $value) - { - $req .= $key . '=' . urlencode(stripslashes($value)) . '&'; - } - // Cut the last '&' - $req = substr($req, 0, strlen($req) - 1); - return $req; - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/classes/acl.php b/phpBB/includes/classes/acl.php deleted file mode 100644 index 049b0842e2..0000000000 --- a/phpBB/includes/classes/acl.php +++ /dev/null @@ -1,946 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Permission/ACL class -* @package phpBB3 -*/ -class phpbb_acl -{ - public $phpbb_required = array('acm', 'db'); - public $phpbb_optional = array(); - - public $acl_raw; - - private $acl = array(); - private $cache = array(); - public $acl_options = array(); - private $acl_element_ids = false; - private $recache = false; - - public function __construct() - { - $this->acl = $this->cache = $this->acl_options = array(); - $this->acl_element_ids = false; - - if (($this->acl_options = phpbb::$acm->get('acl_options')) === false) - { - $sql = 'SELECT auth_option_id, auth_option, is_global, is_local - FROM ' . ACL_OPTIONS_TABLE . ' - ORDER BY auth_option_id'; - $result = phpbb::$db->sql_query($sql); - - $global = $local = 0; - $this->acl_options = array(); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($row['is_global']) - { - $this->acl_options['global'][$row['auth_option']] = $global++; - } - - if ($row['is_local']) - { - $this->acl_options['local'][$row['auth_option']] = $local++; - } - - $this->acl_options['id'][$row['auth_option']] = (int) $row['auth_option_id']; - $this->acl_options['option'][(int) $row['auth_option_id']] = $row['auth_option']; - } - phpbb::$db->sql_freeresult($result); - - phpbb::$acm->put('acl_options', $this->acl_options); - $this->recache = true; - } - - // Add raw data acl class - $this->acl_raw = new phpbb_acl_raw_data(); - } - - /** - * Init permissions - */ - public function init(array &$userdata) - { - if (!trim($userdata['user_permissions']) || $this->recache) - { - $this->acl_cache($userdata); - } - - // Fill ACL array - $this->_fill_acl($userdata['user_permissions']); - - // Verify bitstring length with options provided... - $renew = false; - $global_length = sizeof($this->acl_options['global']); - $local_length = sizeof($this->acl_options['local']); - - // Specify comparing length (bitstring is padded to 31 bits) - $global_length = ($global_length % 31) ? ($global_length - ($global_length % 31) + 31) : $global_length; - $local_length = ($local_length % 31) ? ($local_length - ($local_length % 31) + 31) : $local_length; - - // You thought we are finished now? Noooo... now compare them. - foreach ($this->acl as $forum_id => $bitstring) - { - if (($forum_id && strlen($bitstring) != $local_length) || (!$forum_id && strlen($bitstring) != $global_length)) - { - $renew = true; - break; - } - } - - // If a bitstring within the list does not match the options, we have a user with incorrect permissions set and need to renew them - if ($renew) - { - $this->acl_cache($userdata); - $this->_fill_acl($userdata['user_permissions']); - } - - return; - } - - /** - * Fill ACL array with relevant bitstrings from user_permissions column - * @access private - */ - private function _fill_acl($user_permissions) - { - $this->acl = array(); - $user_permissions = explode("\n", $user_permissions); - - foreach ($user_permissions as $f => $seq) - { - if ($seq) - { - $i = 0; - - if (!isset($this->acl[$f])) - { - $this->acl[$f] = ''; - } - - while ($subseq = substr($seq, $i, 6)) - { - // We put the original bitstring into the acl array - $this->acl[$f] .= str_pad(base_convert($subseq, 36, 2), 31, 0, STR_PAD_LEFT); - $i += 6; - } - } - } - } - - /** - * Look up an option - * if the option is prefixed with !, then the result becomes negated - * - * If a forum id is specified the local option will be combined with a global option if one exist. - * If a forum id is not specified, only the global option will be checked. - */ - public function acl_get($opt, $f = 0) - { - $negate = false; - - if (strpos($opt, '!') === 0) - { - $negate = true; - $opt = substr($opt, 1); - } - - if (!isset($this->cache[$f][$opt])) - { - // We combine the global/local option with an OR because some options are global and local. - // If the user has the global permission the local one is true too and vice versa - $this->cache[$f][$opt] = false; - - // Is this option a global permission setting? - if (isset($this->acl_options['global'][$opt])) - { - if (isset($this->acl[0])) - { - $this->cache[$f][$opt] = $this->acl[0][$this->acl_options['global'][$opt]]; - } - } - - // Is this option a local permission setting? - // But if we check for a global option only, we won't combine the options... - if ($f != 0 && isset($this->acl_options['local'][$opt])) - { - if (isset($this->acl[$f]) && isset($this->acl[$f][$this->acl_options['local'][$opt]])) - { - $this->cache[$f][$opt] |= $this->acl[$f][$this->acl_options['local'][$opt]]; - } - } - } - - // Founder always has all global options set to true... - return $negate xor $this->cache[$f][$opt]; - } - - /** - * Get forums with the specified permission setting - * if the option is prefixed with !, then the result becomes negated - * - * @param bool $clean set to true if only values needs to be returned which are set/unset - */ - public function acl_getf($opt, $clean = false) - { - $acl_f = array(); - $negate = false; - - if (strpos($opt, '!') === 0) - { - $negate = true; - $opt = substr($opt, 1); - } - - // If we retrieve a list of forums not having permissions in, we need to get every forum_id - if ($negate) - { - if ($this->acl_forum_ids === false) - { - $sql = 'SELECT forum_id - FROM ' . FORUMS_TABLE; - - if (sizeof($this->acl)) - { - $sql .= ' WHERE ' . phpbb::$db->sql_in_set('forum_id', array_keys($this->acl), true); - } - $result = phpbb::$db->sql_query($sql); - - $this->acl_forum_ids = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $this->acl_forum_ids[] = $row['forum_id']; - } - phpbb::$db->sql_freeresult($result); - } - } - - if (isset($this->acl_options['local'][$opt])) - { - foreach ($this->acl as $f => $bitstring) - { - // Skip global settings - if (!$f) - { - continue; - } - - $allowed = (!isset($this->cache[$f][$opt])) ? $this->acl_get($opt, $f) : $this->cache[$f][$opt]; - - if (!$clean) - { - $acl_f[$f][$opt] = $negate xor $allowed; - } - else if ($negate xor $allowed) - { - $acl_f[$f][$opt] = 1; - } - } - } - - // If we get forum_ids not having this permission, we need to fill the remaining parts - if ($negate && sizeof($this->acl_forum_ids)) - { - foreach ($this->acl_forum_ids as $f) - { - $acl_f[$f][$opt] = 1; - } - } - - return $acl_f; - } - - /** - * Get local permission state for any forum. - * - * Returns true if user has the permission in one or more forums, false if in no forum. - * If global option is checked it returns the global state (same as acl_get($opt)) - * Local option has precedence... - */ - public function acl_getf_global($opt) - { - if (is_array($opt)) - { - // evaluates to true as soon as acl_getf_global is true for one option - foreach ($opt as $check_option) - { - if ($this->acl_getf_global($check_option)) - { - return true; - } - } - - return false; - } - - if (isset($this->acl_options['local'][$opt])) - { - foreach ($this->acl as $f => $bitstring) - { - // Skip global settings - if (!$f) - { - continue; - } - - // as soon as the user has any permission we're done so return true - if ((!isset($this->cache[$f][$opt])) ? $this->acl_get($opt, $f) : $this->cache[$f][$opt]) - { - return true; - } - } - } - else if (isset($this->acl_options['global'][$opt])) - { - return $this->acl_get($opt); - } - - return false; - } - - /** - * Get permission settings (more than one) - */ - public function acl_gets() - { - $args = func_get_args(); - $f = array_pop($args); - - if (!is_numeric($f)) - { - $args[] = $f; - $f = 0; - } - - // alternate syntax: acl_gets(array('m_', 'a_'), $forum_id) - if (is_array($args[0])) - { - $args = $args[0]; - } - - $acl = 0; - foreach ($args as $opt) - { - $acl |= $this->acl_get($opt, $f); - } - - return $acl; - } - - /** - * Get permission listing based on user_id/options/forum_ids - */ - public function acl_get_list($user_id = false, $opts = false, $forum_id = false) - { - if ($user_id !== false && !is_array($user_id) && $opts === false && $forum_id === false) - { - $hold_ary = array($user_id => $this->acl_raw->single_user($user_id)); - } - else - { - $hold_ary = $this->acl_raw->data($user_id, $opts, $forum_id); - } - - $auth_ary = array(); - foreach ($hold_ary as $user_id => $forum_ary) - { - foreach ($forum_ary as $forum_id => $auth_option_ary) - { - foreach ($auth_option_ary as $auth_option => $auth_setting) - { - if ($auth_setting) - { - $auth_ary[$forum_id][$auth_option][] = $user_id; - } - } - } - } - - return $auth_ary; - } - - /** - * Cache data to user_permissions row - */ - public function acl_cache(array &$userdata) - { - // Empty user_permissions - $userdata['user_permissions'] = ''; - - $hold_ary = $this->acl_raw->single_user($userdata['user_id']); - - // Key 0 in $hold_ary are global options, all others are forum_ids - - // If this user is founder we're going to force fill the admin options ... - if ($userdata['user_type'] == phpbb::USER_FOUNDER) - { - foreach ($this->acl_options['global'] as $opt => $id) - { - if (strpos($opt, 'a_') === 0) - { - $hold_ary[0][$this->acl_options['id'][$opt]] = phpbb::ACL_YES; - } - } - } - - $hold_str = $this->build_bitstring($hold_ary); - - if ($hold_str) - { - $userdata['user_permissions'] = $hold_str; - - $sql = 'UPDATE ' . USERS_TABLE . " - SET user_permissions = '" . phpbb::$db->sql_escape($userdata['user_permissions']) . "', - user_perm_from = 0 - WHERE user_id = " . $userdata['user_id']; - phpbb::$db->sql_query($sql); - } - - return; - } - - /** - * Build bitstring from permission set - */ - protected function build_bitstring(&$hold_ary) - { - $hold_str = ''; - - if (sizeof($hold_ary)) - { - ksort($hold_ary); - - $last_f = 0; - - foreach ($hold_ary as $f => $auth_ary) - { - $ary_key = (!$f) ? 'global' : 'local'; - - $bitstring = array(); - foreach ($this->acl_options[$ary_key] as $opt => $id) - { - if (isset($auth_ary[$this->acl_options['id'][$opt]])) - { - $bitstring[$id] = $auth_ary[$this->acl_options['id'][$opt]]; - - $option_key = substr($opt, 0, strpos($opt, '_') + 1); - - // If one option is allowed, the global permission for this option has to be allowed too - // example: if the user has the a_ permission this means he has one or more a_* permissions - if ($auth_ary[$this->acl_options['id'][$opt]] == phpbb::ACL_YES && (!isset($bitstring[$this->acl_options[$ary_key][$option_key]]) || $bitstring[$this->acl_options[$ary_key][$option_key]] == phpbb::ACL_NEVER)) - { - $bitstring[$this->acl_options[$ary_key][$option_key]] = phpbb::ACL_YES; - } - } - else - { - $bitstring[$id] = phpbb::ACL_NEVER; - } - } - - // Now this bitstring defines the permission setting for the current forum $f (or global setting) - $bitstring = implode('', $bitstring); - - // The line number indicates the id, therefore we have to add empty lines for those ids not present - $hold_str .= str_repeat("\n", $f - $last_f); - - // Convert bitstring for storage - we do not use binary/bytes because PHP's string functions are not fully binary safe - for ($i = 0, $bit_length = strlen($bitstring); $i < $bit_length; $i += 31) - { - $hold_str .= str_pad(base_convert(str_pad(substr($bitstring, $i, 31), 31, 0, STR_PAD_RIGHT), 2, 36), 6, 0, STR_PAD_LEFT); - } - - $last_f = $f; - } - unset($bitstring); - - $hold_str = rtrim($hold_str); - } - - return $hold_str; - } - - /** - * Clear one or all users cached permission settings - */ - public function acl_clear_prefetch($user_id = false) - { - // Rebuild options cache - phpbb::$acm->destroy('role_cache'); - - $sql = 'SELECT * - FROM ' . ACL_ROLES_DATA_TABLE . ' - ORDER BY role_id ASC'; - $result = phpbb::$db->sql_query($sql); - - $this->role_cache = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $this->role_cache[$row['role_id']][$row['auth_option_id']] = (int) $row['auth_setting']; - } - phpbb::$db->sql_freeresult($result); - - foreach ($this->role_cache as $role_id => $role_options) - { - $this->role_cache[$role_id] = serialize($role_options); - } - - phpbb::$acm->put('role_cache', $this->role_cache); - - // Now empty user permissions - $where_sql = ''; - - if ($user_id !== false) - { - $user_id = (!is_array($user_id)) ? $user_id = array((int) $user_id) : array_map('intval', $user_id); - $where_sql = ' WHERE ' . phpbb::$db->sql_in_set('user_id', $user_id); - } - - $sql = 'UPDATE ' . USERS_TABLE . " - SET user_permissions = '', - user_perm_from = 0 - $where_sql"; - phpbb::$db->sql_query($sql); - - return; - } - -/** -} - - * Role-specific methods/definitionis used by phpbb_acl -class phpbb_acl_role -{ - */ - - /** - * Get assigned roles - * @todo: protected or public? - */ - public function acl_role_data($user_type, $role_type, $ug_id = false, $forum_id = false) - { - $roles = array(); - - $sql_id = ($user_type == 'user') ? 'user_id' : 'group_id'; - - $sql_ug = ($ug_id !== false) ? ((!is_array($ug_id)) ? "AND a.$sql_id = $ug_id" : 'AND ' . phpbb::$db->sql_in_set("a.$sql_id", $ug_id)) : ''; - $sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? "AND a.forum_id = $forum_id" : 'AND ' . phpbb::$db->sql_in_set('a.forum_id', $forum_id)) : ''; - - // Grab assigned roles... - $sql = 'SELECT a.auth_role_id, a.' . $sql_id . ', a.forum_id - FROM ' . (($user_type == 'user') ? ACL_USERS_TABLE : ACL_GROUPS_TABLE) . ' a, ' . ACL_ROLES_TABLE . " r - WHERE a.auth_role_id = r.role_id - AND r.role_type = '" . phpbb::$db->sql_escape($role_type) . "' - $sql_ug - $sql_forum - ORDER BY r.role_order ASC"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $roles[$row[$sql_id]][$row['forum_id']] = $row['auth_role_id']; - } - phpbb::$db->sql_freeresult($result); - - return $roles; - } -} - -/** -* data-specific methods/definitionis used by phpbb_acl -*/ -class phpbb_acl_raw_data -{ - /** - * Get raw acl data based on user/option/forum - * @todo: protected or public? - */ - public function data($user_id = false, $opts = false, $forum_id = false) - { - $sql_user = ($user_id !== false) ? ((!is_array($user_id)) ? 'user_id = ' . (int) $user_id : phpbb::$db->sql_in_set('user_id', array_map('intval', $user_id))) : ''; - $sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? 'AND a.forum_id = ' . (int) $forum_id : 'AND ' . phpbb::$db->sql_in_set('a.forum_id', array_map('intval', $forum_id))) : ''; - - $sql_opts = $sql_opts_select = $sql_opts_from = ''; - $hold_ary = array(); - - if ($opts !== false) - { - $sql_opts_select = ', ao.auth_option'; - $sql_opts_from = ', ' . ACL_OPTIONS_TABLE . ' ao'; - $this->build_auth_option_statement('ao.auth_option', $opts, $sql_opts); - } - - $sql_ary = array(); - - // Grab non-role settings - user-specific - $sql_ary[] = 'SELECT a.user_id, a.forum_id, a.auth_setting, a.auth_option_id' . $sql_opts_select . ' - FROM ' . ACL_USERS_TABLE . ' a' . $sql_opts_from . ' - WHERE a.auth_role_id = 0 ' . - (($sql_opts_from) ? 'AND a.auth_option_id = ao.auth_option_id ' : '') . - (($sql_user) ? 'AND a.' . $sql_user : '') . " - $sql_forum - $sql_opts"; - - // Now the role settings - user-specific - $sql_ary[] = 'SELECT a.user_id, a.forum_id, r.auth_option_id, r.auth_setting, r.auth_option_id' . $sql_opts_select . ' - FROM ' . ACL_USERS_TABLE . ' a, ' . ACL_ROLES_DATA_TABLE . ' r' . $sql_opts_from . ' - WHERE a.auth_role_id = r.role_id ' . - (($sql_opts_from) ? 'AND r.auth_option_id = ao.auth_option_id ' : '') . - (($sql_user) ? 'AND a.' . $sql_user : '') . " - $sql_forum - $sql_opts"; - - foreach ($sql_ary as $sql) - { - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $option = ($sql_opts_select) ? $row['auth_option'] : $this->acl_options['option'][$row['auth_option_id']]; - $hold_ary[$row['user_id']][$row['forum_id']][$option] = $row['auth_setting']; - } - phpbb::$db->sql_freeresult($result); - } - - $sql_ary = array(); - - // Now grab group settings - non-role specific... - $sql_ary[] = 'SELECT ug.user_id, a.forum_id, a.auth_setting, a.auth_option_id' . $sql_opts_select . ' - FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug' . $sql_opts_from . ' - WHERE a.auth_role_id = 0 ' . - (($sql_opts_from) ? 'AND a.auth_option_id = ao.auth_option_id ' : '') . ' - AND a.group_id = ug.group_id - AND ug.user_pending = 0 - ' . (($sql_user) ? 'AND ug.' . $sql_user : '') . " - $sql_forum - $sql_opts"; - - // Now grab group settings - role specific... - $sql_ary[] = 'SELECT ug.user_id, a.forum_id, r.auth_setting, r.auth_option_id' . $sql_opts_select . ' - FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug, ' . ACL_ROLES_DATA_TABLE . ' r' . $sql_opts_from . ' - WHERE a.auth_role_id = r.role_id ' . - (($sql_opts_from) ? 'AND r.auth_option_id = ao.auth_option_id ' : '') . ' - AND a.group_id = ug.group_id - AND ug.user_pending = 0 - ' . (($sql_user) ? 'AND ug.' . $sql_user : '') . " - $sql_forum - $sql_opts"; - - foreach ($sql_ary as $sql) - { - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $option = ($sql_opts_select) ? $row['auth_option'] : $this->acl_options['option'][$row['auth_option_id']]; - - // @todo: use the ref technique to reduce opcode generation - if (!isset($hold_ary[$row['user_id']][$row['forum_id']][$option]) || (isset($hold_ary[$row['user_id']][$row['forum_id']][$option]) && $hold_ary[$row['user_id']][$row['forum_id']][$option] != phpbb::ACL_NEVER)) - { - $hold_ary[$row['user_id']][$row['forum_id']][$option] = $row['auth_setting']; - - // If we detect phpbb::ACL_NEVER, we will unset the flag option (within building the bitstring it is correctly set again) - if ($row['auth_setting'] == phpbb::ACL_NEVER) - { - $flag = substr($option, 0, strpos($option, '_') + 1); - - if (isset($hold_ary[$row['user_id']][$row['forum_id']][$flag]) && $hold_ary[$row['user_id']][$row['forum_id']][$flag] == phpbb::ACL_YES) - { - unset($hold_ary[$row['user_id']][$row['forum_id']][$flag]); - -/* if (in_array(phpbb::ACL_YES, $hold_ary[$row['user_id']][$row['forum_id']])) - { - $hold_ary[$row['user_id']][$row['forum_id']][$flag] = phpbb::ACL_YES; - } -*/ - } - } - } - } - phpbb::$db->sql_freeresult($result); - } - - return $hold_ary; - } - - /** - * Get raw user based permission settings - */ - public function user($user_id = false, $opts = false, $forum_id = false) - { - $sql_user = ($user_id !== false) ? ((!is_array($user_id)) ? 'user_id = ' . (int) $user_id : phpbb::$db->sql_in_set('user_id', array_map('intval', $user_id))) : ''; - $sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? 'AND a.forum_id = ' . (int) $forum_id : 'AND ' . phpbb::$db->sql_in_set('a.forum_id', array_map('intval', $forum_id))) : ''; - - $sql_opts = ''; - $hold_ary = $sql_ary = array(); - - if ($opts !== false) - { - $this->build_auth_option_statement('ao.auth_option', $opts, $sql_opts); - } - - // Grab user settings - non-role specific... - $sql_ary[] = 'SELECT a.user_id, a.forum_id, a.auth_setting, a.auth_option_id, ao.auth_option - FROM ' . ACL_USERS_TABLE . ' a, ' . ACL_OPTIONS_TABLE . ' ao - WHERE a.auth_role_id = 0 - AND a.auth_option_id = ao.auth_option_id ' . - (($sql_user) ? 'AND a.' . $sql_user : '') . " - $sql_forum - $sql_opts - ORDER BY a.forum_id, ao.auth_option"; - - // Now the role settings - user-specific - $sql_ary[] = 'SELECT a.user_id, a.forum_id, r.auth_option_id, r.auth_setting, r.auth_option_id, ao.auth_option - FROM ' . ACL_USERS_TABLE . ' a, ' . ACL_ROLES_DATA_TABLE . ' r, ' . ACL_OPTIONS_TABLE . ' ao - WHERE a.auth_role_id = r.role_id - AND r.auth_option_id = ao.auth_option_id ' . - (($sql_user) ? 'AND a.' . $sql_user : '') . " - $sql_forum - $sql_opts - ORDER BY a.forum_id, ao.auth_option"; - - foreach ($sql_ary as $sql) - { - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $hold_ary[$row['user_id']][$row['forum_id']][$row['auth_option']] = $row['auth_setting']; - } - phpbb::$db->sql_freeresult($result); - } - - return $hold_ary; - } - - /** - * Get raw group based permission settings - */ - public function group($group_id = false, $opts = false, $forum_id = false) - { - $sql_group = ($group_id !== false) ? ((!is_array($group_id)) ? 'group_id = ' . (int) $group_id : phpbb::$db->sql_in_set('group_id', array_map('intval', $group_id))) : ''; - $sql_forum = ($forum_id !== false) ? ((!is_array($forum_id)) ? 'AND a.forum_id = ' . (int) $forum_id : 'AND ' . phpbb::$db->sql_in_set('a.forum_id', array_map('intval', $forum_id))) : ''; - - $sql_opts = ''; - $hold_ary = $sql_ary = array(); - - if ($opts !== false) - { - $this->build_auth_option_statement('ao.auth_option', $opts, $sql_opts); - } - - // Grab group settings - non-role specific... - $sql_ary[] = 'SELECT a.group_id, a.forum_id, a.auth_setting, a.auth_option_id, ao.auth_option - FROM ' . ACL_GROUPS_TABLE . ' a, ' . ACL_OPTIONS_TABLE . ' ao - WHERE a.auth_role_id = 0 - AND a.auth_option_id = ao.auth_option_id ' . - (($sql_group) ? 'AND a.' . $sql_group : '') . " - $sql_forum - $sql_opts - ORDER BY a.forum_id, ao.auth_option"; - - // Now grab group settings - role specific... - $sql_ary[] = 'SELECT a.group_id, a.forum_id, r.auth_setting, r.auth_option_id, ao.auth_option - FROM ' . ACL_GROUPS_TABLE . ' a, ' . ACL_ROLES_DATA_TABLE . ' r, ' . ACL_OPTIONS_TABLE . ' ao - WHERE a.auth_role_id = r.role_id - AND r.auth_option_id = ao.auth_option_id ' . - (($sql_group) ? 'AND a.' . $sql_group : '') . " - $sql_forum - $sql_opts - ORDER BY a.forum_id, ao.auth_option"; - - foreach ($sql_ary as $sql) - { - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $hold_ary[$row['group_id']][$row['forum_id']][$row['auth_option']] = $row['auth_setting']; - } - phpbb::$db->sql_freeresult($result); - } - - return $hold_ary; - } - - /** - * Get raw acl data based on user for caching user_permissions - * This function returns the same data as data(), but without the user id as the first key within the array. - */ - public function single_user($user_id) - { - // Check if the role-cache is there - if (($this->role_cache = phpbb::$acm->get('role_cache')) === false) - { - $this->role_cache = array(); - - // We pre-fetch roles - $sql = 'SELECT * - FROM ' . ACL_ROLES_DATA_TABLE . ' - ORDER BY role_id ASC'; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $this->role_cache[$row['role_id']][$row['auth_option_id']] = (int) $row['auth_setting']; - } - phpbb::$db->sql_freeresult($result); - - foreach ($this->role_cache as $role_id => $role_options) - { - $this->role_cache[$role_id] = serialize($role_options); - } - - phpbb::$acm->put('role_cache', $this->role_cache); - } - - $hold_ary = array(); - - // Grab user-specific permission settings - $sql = 'SELECT forum_id, auth_option_id, auth_role_id, auth_setting - FROM ' . ACL_USERS_TABLE . ' - WHERE user_id = ' . $user_id; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - // If a role is assigned, assign all options included within this role. Else, only set this one option. - if ($row['auth_role_id']) - { - $hold_ary[$row['forum_id']] = (empty($hold_ary[$row['forum_id']])) ? unserialize($this->role_cache[$row['auth_role_id']]) : $hold_ary[$row['forum_id']] + unserialize($this->role_cache[$row['auth_role_id']]); - } - else - { - $hold_ary[$row['forum_id']][$row['auth_option_id']] = $row['auth_setting']; - } - } - phpbb::$db->sql_freeresult($result); - - // Now grab group-specific permission settings - $sql = 'SELECT a.forum_id, a.auth_option_id, a.auth_role_id, a.auth_setting - FROM ' . ACL_GROUPS_TABLE . ' a, ' . USER_GROUP_TABLE . ' ug - WHERE a.group_id = ug.group_id - AND ug.user_pending = 0 - AND ug.user_id = ' . $user_id; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if (!$row['auth_role_id']) - { - $this->_set_group_hold_ary($hold_ary[$row['forum_id']], $row['auth_option_id'], $row['auth_setting']); - } - else if (!empty($this->role_cache[$row['auth_role_id']])) - { - foreach (unserialize($this->role_cache[$row['auth_role_id']]) as $option_id => $setting) - { - $this->_set_group_hold_ary($hold_ary[$row['forum_id']], $option_id, $setting); - } - } - } - phpbb::$db->sql_freeresult($result); - - return $hold_ary; - } - - /** - * Private function snippet for setting a specific piece of the hold_ary - */ - private function _set_group_hold_ary(&$hold_ary, $option_id, $setting) - { - if (!isset($hold_ary[$option_id]) || (isset($hold_ary[$option_id]) && $hold_ary[$option_id] != phpbb::ACL_NEVER)) - { - $hold_ary[$option_id] = $setting; - - // If we detect phpbb::ACL_NEVER, we will unset the flag option (within building the bitstring it is correctly set again) - if ($setting == phpbb::ACL_NEVER) - { - $flag = substr($this->acl_options['option'][$option_id], 0, strpos($this->acl_options['option'][$option_id], '_') + 1); - $flag = (int) $this->acl_options['id'][$flag]; - - if (isset($hold_ary[$flag]) && $hold_ary[$flag] == phpbb::ACL_YES) - { - unset($hold_ary[$flag]); - -/* This is uncommented, because i suspect this being slightly wrong due to mixed permission classes being possible - if (in_array(phpbb::ACL_YES, $hold_ary)) - { - $hold_ary[$flag] = phpbb::ACL_YES; - }*/ - } - } - } - } - - /** - * Fill auth_option statement for later querying based on the supplied options - */ - private function build_auth_option_statement($key, $auth_options, &$sql_opts) - { - if (!is_array($auth_options)) - { - if (strpos($auth_options, '%') !== false) - { - $sql_opts = "AND $key " . phpbb::$db->sql_like_expression(str_replace('%', phpbb::$db->any_char, $auth_options)); - } - else - { - $sql_opts = "AND $key = '" . phpbb::$db->sql_escape($auth_options) . "'"; - } - } - else - { - $is_like_expression = false; - - foreach ($auth_options as $option) - { - if (strpos($option, '%') !== false) - { - $is_like_expression = true; - } - } - - if (!$is_like_expression) - { - $sql_opts = 'AND ' . phpbb::$db->sql_in_set($key, $auth_options); - } - else - { - $sql = array(); - - foreach ($auth_options as $option) - { - if (strpos($option, '%') !== false) - { - $sql[] = $key . ' ' . phpbb::$db->sql_like_expression(str_replace('%', phpbb::$db->any_char, $option)); - } - else - { - $sql[] = $key . " = '" . phpbb::$db->sql_escape($option) . "'"; - } - } - - $sql_opts = 'AND (' . implode(' OR ', $sql) . ')'; - } - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/classes/cache.php b/phpBB/includes/classes/cache.php deleted file mode 100644 index eeeae58989..0000000000 --- a/phpBB/includes/classes/cache.php +++ /dev/null @@ -1,425 +0,0 @@ -<?php -/** -* -* @package acm -* @version $Id$ -* @copyright (c) 2005, 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Class for obtaining cached entries, for example censor word list, configuration... -* @package acm -*/ -class phpbb_cache -{ - /** - * We do not want this object instantiable - */ - private function ___construct() { } - - /** - * Required phpBB objects - */ - public $phpbb_required = array('config', 'acm', 'db'); - - /** - * Optional phpBB objects - */ - public $phpbb_optional = array(); - - /** - * Get config values - * - * @return array configuration - * @access public - */ - public static function obtain_config() - { - if ((phpbb::$config = phpbb::$acm->get('#config')) !== false) - { - $sql = 'SELECT config_name, config_value - FROM ' . CONFIG_TABLE . ' - WHERE is_dynamic = 1'; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - phpbb::$config[$row['config_name']] = $row['config_value']; - } - phpbb::$db->sql_freeresult($result); - } - else - { - phpbb::$config = $cached_config = array(); - - $sql = 'SELECT config_name, config_value, is_dynamic - FROM ' . CONFIG_TABLE; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if (!$row['is_dynamic']) - { - $cached_config[$row['config_name']] = $row['config_value']; - } - - phpbb::$config[$row['config_name']] = $row['config_value']; - } - phpbb::$db->sql_freeresult($result); - - phpbb::$acm->put('#config', $cached_config); - } - - return phpbb::$config; - } - - /** - * Obtain list of naughty words and build preg style replacement arrays for use by the calling script - * - * @return array Censored words - * @access public - */ - public static function obtain_word_list() - { - if (($censors = phpbb::$acm->get('word_censors')) === false) - { - $sql = 'SELECT word, replacement - FROM ' . WORDS_TABLE; - $result = phpbb::$db->sql_query($sql); - - $censors = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $censors['match'][] = '#(?<!\w)(' . str_replace('\*', '\w*?', preg_quote($row['word'], '#')) . ')(?!\w)#i'; - $censors['replace'][] = $row['replacement']; - } - phpbb::$db->sql_freeresult($result); - - phpbb::$acm->put('word_censors', $censors); - } - - return $censors; - } - - /** - * Obtain currently listed icons - * - * @return array Icons - * @access public - */ - public static function obtain_icons() - { - if (($icons = phpbb::$acm->get('icons')) === false) - { - // Topic icons - $sql = 'SELECT * - FROM ' . ICONS_TABLE . ' - ORDER BY icons_order'; - $result = phpbb::$db->sql_query($sql); - - $icons = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $icons[$row['icons_id']]['img'] = $row['icons_url']; - $icons[$row['icons_id']]['width'] = (int) $row['icons_width']; - $icons[$row['icons_id']]['height'] = (int) $row['icons_height']; - $icons[$row['icons_id']]['display'] = (bool) $row['display_on_posting']; - } - phpbb::$db->sql_freeresult($result); - - phpbb::$acm->put('icons', $icons); - } - - return $icons; - } - - /** - * Obtain ranks - * - * @return Ranks - * @access public - */ - public static function obtain_ranks() - { - if (($ranks = phpbb::$acm->get('ranks')) === false) - { - $sql = 'SELECT * - FROM ' . RANKS_TABLE . ' - ORDER BY rank_min DESC'; - $result = phpbb::$db->sql_query($sql); - - $ranks = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($row['rank_special']) - { - $ranks['special'][$row['rank_id']] = array( - 'rank_title' => $row['rank_title'], - 'rank_image' => $row['rank_image'] - ); - } - else - { - $ranks['normal'][] = array( - 'rank_title' => $row['rank_title'], - 'rank_min' => $row['rank_min'], - 'rank_image' => $row['rank_image'] - ); - } - } - phpbb::$db->sql_freeresult($result); - - phpbb::$acm->put('ranks', $ranks); - } - - return $ranks; - } - - /** - * Put attachment extensions data into cache - * - * @return array Cached extensions - * @access private - */ - private static function cache_extensions() - { - $extensions = array( - '_allowed_post' => array(), - '_allowed_pm' => array(), - ); - - // The rule is to only allow those extensions defined. ;) - $sql = 'SELECT e.extension, g.* - FROM ' . EXTENSIONS_TABLE . ' e, ' . EXTENSION_GROUPS_TABLE . ' g - WHERE e.group_id = g.group_id - AND (g.allow_group = 1 OR g.allow_in_pm = 1)'; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $extension = strtolower(trim($row['extension'])); - - $extensions[$extension] = array( - 'display_cat' => (int) $row['cat_id'], - 'download_mode' => (int) $row['download_mode'], - 'upload_icon' => trim($row['upload_icon']), - 'max_filesize' => (int) $row['max_filesize'], - 'allow_group' => $row['allow_group'], - 'allow_in_pm' => $row['allow_in_pm'], - ); - - $allowed_forums = ($row['allowed_forums']) ? unserialize(trim($row['allowed_forums'])) : array(); - - // Store allowed extensions forum wise - if ($row['allow_group']) - { - $extensions['_allowed_post'][$extension] = (!sizeof($allowed_forums)) ? 0 : $allowed_forums; - } - - if ($row['allow_in_pm']) - { - $extensions['_allowed_pm'][$extension] = 0; - } - } - phpbb::$db->sql_freeresult($result); - - phpbb::$acm->put('extensions', $extensions); - return $extensions; - } - - /** - * Obtain allowed attachment extensions in private messages - * - * @return array Allowed extensions - * @access public - */ - public static function obtain_extensions_pm() - { - if (($extensions = phpbb::$acm->get('extensions')) === false) - { - $extensions = self::cache_extensions(); - } - - // We are checking for private messages, therefore we only need to get the pm extensions... - $result = array('_allowed_' => array()); - - foreach ($extensions['_allowed_pm'] as $extension => $check) - { - $result['_allowed_'][$extension] = 0; - $result[$extension] = $extensions[$extension]; - } - - return $result; - } - - /** - * Obtain allowed attachment extensions in specific forum - * - * @param int $forum_id The forum id - * @return array Allowed extensions within the specified forum - * @access public - */ - public static function obtain_extensions_forum($forum_id) - { - if (($extensions = phpbb::$acm->get('extensions')) === false) - { - $extensions = self::cache_extensions(); - } - - $forum_id = (int) $forum_id; - $result = array('_allowed_' => array()); - - foreach ($extensions['_allowed_post'] as $extension => $check) - { - // Check for allowed forums - if (is_array($check)) - { - $allowed = (!in_array($forum_id, $check)) ? false : true; - } - else - { - $allowed = true; - } - - if ($allowed) - { - $result['_allowed_'][$extension] = 0; - $result[$extension] = $extensions[$extension]; - } - } - - if (!isset($result['_allowed_'])) - { - $result['_allowed_'] = array(); - } - - return $result; - } - - /** - * Obtain general attachment extension information - * - * @return array Cached extension information - * @access public - */ - public static function obtain_extensions() - { - if (($extensions = phpbb::$acm->get('extensions')) === false) - { - $extensions = self::cache_extensions(); - } - - return $extensions; - } - - /** - * Obtain active bots - * - * @return array Active bots - * @access public - */ - public static function obtain_bots() - { - if (($bots = phpbb::$acm->get('bots')) === false) - { - // @todo We order by last visit date. This way we are able to safe some cycles by checking the most active ones first. - $sql = 'SELECT user_id, bot_agent, bot_ip - FROM ' . BOTS_TABLE . ' - WHERE bot_active = 1 - ORDER BY ' . phpbb::$db->sql_function('length_varchar', 'bot_agent') . 'DESC'; - $result = phpbb::$db->sql_query($sql); - - $bots = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $bots[] = $row; - } - phpbb::$db->sql_freeresult($result); - - phpbb::$acm->put('bots', $bots); - } - - return $bots; - } - - /** - * Obtain Styles .cfg file data - * - * @param array $theme An array containing the path to the items - * @param string $item The specific item to get: 'theme', 'template', or 'imageset' - * @return array The configuration - * @access public - */ - public static function obtain_cfg_item($theme, $item = 'theme') - { - $parsed_array = phpbb::$acm->get('cfg_' . $item . '_' . $theme[$item . '_path']); - - if ($parsed_array === false) - { - $parsed_array = array(); - } - - $reparse = false; - $filename = PHPBB_ROOT_PATH . 'styles/' . $theme[$item . '_path'] . '/' . $item . '/' . $item . '.cfg'; - - if (!file_exists($filename)) - { - return $parsed_array; - } - - if (!isset($parsed_array['filetime']) || ((phpbb::$config['load_tplcompile'] && @filemtime($filename) > $parsed_array['filetime']))) - { - $reparse = true; - } - - // Re-parse cfg file - if ($reparse) - { - $parsed_array = parse_cfg_file($filename); - $parsed_array['filetime'] = @filemtime($filename); - - phpbb::$acm->put('cfg_' . $item . '_' . $theme[$item . '_path'], $parsed_array); - } - - return $parsed_array; - } - - /** - * Obtain disallowed usernames - * - * @return array Disallowed usernames - * @access public - */ - public static function obtain_disallowed_usernames() - { - if (($usernames = phpbb::$acm->get('disallowed_usernames')) === false) - { - $sql = 'SELECT disallow_username - FROM ' . DISALLOW_TABLE; - $result = phpbb::$db->sql_query($sql); - - $usernames = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $usernames[] = str_replace('%', '.*?', preg_quote(utf8_clean_string($row['disallow_username']), '#')); - } - phpbb::$db->sql_freeresult($result); - - phpbb::$acm->put('disallowed_usernames', $usernames); - } - - return $usernames; - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/classes/session.php b/phpBB/includes/classes/session.php deleted file mode 100644 index ca54bae552..0000000000 --- a/phpBB/includes/classes/session.php +++ /dev/null @@ -1,1289 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005, 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Session class -* @package phpBB3 -*/ -abstract class phpbb_session -{ - /** - * @var array Cookie informations - */ - private $cookie_data = array(); - - /** - * @var array User data - */ - public $data = array(); - - /** - * @var string Session id - */ - public $session_id = ''; - - /** - * @var int Current time - */ - public $time_now = 0; - - /** - * @var bool True if the current page is updated within the sessions table - */ - public $update_session_page = true; - - /** - * @var mixed Reference to authentication system. - */ - public $auth = NULL; - - /** - * @var mixed Reference to system array for obtaining server/system information - */ - public $system = NULL; - - /** - * @var array Extra url parameter to append to every URL in phpBB - */ - public $extra_url = array(); - - /** - * @var bool If this is true then the session id (?sid=[session_id]) is required - */ - public $need_sid = false; - - /** - * @var array Information about current page - */ - public $page = array(); - - /** - * @var string The users IP - */ - public $ip = '127.0.0.1'; - - /** - * Init session. Empties the user data and assigns the system object (phpbb::$instances['system']) - * @access public - */ - public function __construct() - { - // Reset data array ;) - $this->data = array(); - - // Set auth to false (only valid for an user object) - $this->auth = false; - - // Some system/server variables, directly generated by phpbb_system_info methods. Used like an array. - // We use the phpbb:: one, because it could've been modified and being a completely different class - $this->system =& phpbb::$instances['server-vars']; - } - - /** - * Specifiy the need for a session id within the URL - * - * @param bool $need_sid Specify if the session id is needed or not. Default is false. - * @access public - */ - public function need_sid($need_sid = false) - { - $this->need_sid = $need_sid; - } - - /** - * Start session management - * - * This is where all session activity begins. We gather various pieces of - * information from the client and server. We test to see if a session already - * exists. If it does, fine and dandy. If it doesn't we'll go on to create a - * new one ... pretty logical heh? We also examine the system load (if we're - * running on a system which makes such information readily available) and - * halt if it's above an admin definable limit. - * - * @param bool $update_session_page If true the session page gets updated. - * This can be set to false to circumvent certain scripts to update the users last visited page. - * - * @return bool True if the session exist or has been created, else False. - * @access public - */ - public function session_begin($update_session_page = true) - { - // Give us some basic information - $this->time_now = time(); - $this->cookie_data = array('u' => 0, 'k' => ''); - $this->update_session_page = $update_session_page; - $this->page = $this->system['page']; - $this->ip = $this->system['ip']; - - if (phpbb_request::is_set(phpbb::$config['cookie_name'] . '_sid', phpbb_request::COOKIE) || phpbb_request::is_set(phpbb::$config['cookie_name'] . '_u', phpbb_request::COOKIE)) - { - $this->cookie_data['u'] = request_var(phpbb::$config['cookie_name'] . '_u', 0, false, true); - $this->cookie_data['k'] = request_var(phpbb::$config['cookie_name'] . '_k', '', false, true); - $this->session_id = request_var(phpbb::$config['cookie_name'] . '_sid', '', false, true); - - if (empty($this->session_id)) - { - $this->session_id = request_var('sid', ''); - $this->cookie_data = array('u' => 0, 'k' => ''); - $this->need_sid = true; - } - } - else - { - $this->session_id = request_var('sid', ''); - $this->need_sid = true; - } - - $this->extra_url = array(); - - // Now check for an existing session - if ($this->session_exist()) - { - return true; - } - - // If we reach here then no (valid) session exists. So we'll create a new one - return $this->session_create(); - } - - /** - * Create a new session - * - * If upon trying to start a session we discover there is nothing existing we - * jump here. Additionally this method is called directly during login to regenerate - * the session for the specific user. In this method we carry out a number of tasks; - * garbage collection, (search)bot checking, banned user comparison. Basically - * though this method will result in a new session for a specific user. - * - * @param int $user_id The user id to create the session for. - * @param bool $set_admin Set the users admin field to identify him/her as an admin? - * @param bool $persist_login Allow persistent login - * @param bool $viewonline If false then the user will be logged in as hidden - * - * @return bool True if session got created successfully. - * @access public - */ - public function session_create($user_id = false, $set_admin = false, $persist_login = false, $viewonline = true) - { - // There is one case where we need to add a "failsafe" user... when we are not able to query the database - if (!phpbb::registered('db')) - { - $this->data = $this->default_data(); - return true; - } - - // If the data array is filled, chances are high that there was a different session active - if (sizeof($this->data)) - { - // Kill the session and do not create a new one - $this->session_kill(false); - } - - $this->data = array(); - - // Do we allow autologin on this board? No? Then override anything - // that may be requested here - if (!phpbb::$config['allow_autologin']) - { - $this->cookie_data['k'] = $persist_login = false; - } - - // Check for autologin key. ;) - if ($this->auth !== false && method_exists($this->auth, 'autologin')) - { - $this->data = $this->auth->autologin(); - - if (sizeof($this->data)) - { - $this->cookie_data['k'] = ''; - $this->cookie_data['u'] = $this->data['user_id']; - } - } - - // NULL indicates we need to check for a bot later. Sometimes it is apparant that it is not a bot. ;) No need to always check this. - $bot = NULL; - - // If we're presented with an autologin key we'll join against it. - // Else if we've been passed a user_id we'll grab data based on that - if (isset($this->cookie_data['k']) && $this->cookie_data['k'] && $this->cookie_data['u'] && !sizeof($this->data)) - { - $sql = 'SELECT u.* - FROM ' . USERS_TABLE . ' u, ' . SESSIONS_KEYS_TABLE . ' k - WHERE u.user_id = ' . (int) $this->cookie_data['u'] . ' - AND u.user_type IN (' . phpbb::USER_NORMAL . ', ' . phpbb::USER_FOUNDER . ") - AND k.user_id = u.user_id - AND k.key_id = '" . phpbb::$db->sql_escape(md5($this->cookie_data['k'])) . "'"; - $result = phpbb::$db->sql_query($sql); - $this->data = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - $bot = false; - } - else if ($user_id !== false && !sizeof($this->data)) - { - $this->cookie_data['k'] = ''; - $this->cookie_data['u'] = $user_id; - - $sql = 'SELECT * - FROM ' . USERS_TABLE . ' - WHERE user_id = ' . (int) $this->cookie_data['u'] . ' - AND user_type IN (' . phpbb::USER_NORMAL . ', ' . phpbb::USER_FOUNDER . ')'; - $result = phpbb::$db->sql_query($sql); - $this->data = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - $bot = false; - } - - if ($bot === NULL) - { - $bot = $this->check_bot(); - } - - // If no data was returned one or more of the following occurred: - // Key didn't match one in the DB - // User does not exist - // User is inactive - // User is bot - if (!sizeof($this->data) || !is_array($this->data)) - { - $this->cookie_data['k'] = ''; - $this->cookie_data['u'] = ($bot) ? $bot : ANONYMOUS; - - if (!$bot) - { - $sql = 'SELECT * - FROM ' . USERS_TABLE . ' - WHERE user_id = ' . (int) $this->cookie_data['u']; - } - else - { - // We give bots always the same session if it is not yet expired. - $sql = 'SELECT u.*, s.* - FROM ' . USERS_TABLE . ' u - LEFT JOIN ' . SESSIONS_TABLE . ' s ON (s.session_user_id = u.user_id) - WHERE u.user_id = ' . (int) $bot; - } - - $result = phpbb::$db->sql_query($sql); - $this->data = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - $this->is_registered = false; - } - else - { - $this->is_registered = true; - $this->is_guest = false; - $this->is_founder = $this->data['user_type'] == phpbb::USER_FOUNDER; - } - - // Force user id to be integer... - $this->data['user_id'] = (int) $this->data['user_id']; - - // Code for ANONYMOUS user, INACTIVE user and BOTS - if (!$this->is_registered) - { - // Set last visit date to 'now' - $this->data['session_last_visit'] = $this->time_now; - $this->is_bot = ($bot) ? true : false; - - // If our friend is a bot, we re-assign a previously assigned session - if ($this->is_bot && $bot == $this->data['user_id'] && $this->data['session_id']) - { - if ($this->session_valid(false)) - { - $this->session_id = $this->data['session_id']; - - // Only update session DB a minute or so after last update or if page changes - if ($this->time_now - $this->data['session_time'] > 60 || ($this->update_session_page && $this->data['session_page'] != $this->system['page']['page'])) - { - $this->data['session_time'] = $this->data['session_last_visit'] = $this->time_now; - $sql_ary = array('session_time' => $this->time_now, 'session_last_visit' => $this->time_now, 'session_admin' => 0); - - if ($this->update_session_page) - { - $sql_ary['session_page'] = substr($this->system['page']['page'], 0, 199); - } - - $sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . phpbb::$db->sql_build_array('UPDATE', $sql_ary) . " - WHERE session_id = '" . phpbb::$db->sql_escape($this->session_id) . "'"; - phpbb::$db->sql_query($sql); - - // Update the last visit time - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_lastvisit = ' . (int) $this->data['session_time'] . ' - WHERE user_id = ' . (int) $this->data['user_id']; - phpbb::$db->sql_query($sql); - } - - $this->session_id = ''; - - return true; - } - else - { - // If the ip and browser does not match make sure we only have one bot assigned to one session - phpbb::$db->sql_query('DELETE FROM ' . SESSIONS_TABLE . ' WHERE session_user_id = ' . $this->data['user_id']); - } - } - } - else - { - // Code for registered users - $this->data['session_last_visit'] = (!empty($this->data['session_time'])) ? $this->data['session_time'] : (($this->data['user_lastvisit']) ? $this->data['user_lastvisit'] : $this->time_now); - $this->is_bot = false; - } - - // At this stage we should have a filled data array, defined cookie u and k data. - // data array should contain recent session info if we're a real user and a recent - // session exists in which case session_id will also be set - - // Is user banned? Are they excluded? Won't return on ban, exists within method - if ($this->data['user_type'] != phpbb::USER_FOUNDER) - { - if (!phpbb::$config['forwarded_for_check']) - { - $this->check_ban($this->data['user_id'], $this->system['ip']); - } - else - { - $ips = explode(', ', $this->forwarded_for); - $ips[] = $this->system['ip']; - $this->check_ban($this->data['user_id'], $ips); - } - } - - $session_autologin = (($this->cookie_data['k'] || $persist_login) && $this->is_registered) ? true : false; - $set_admin = ($set_admin && $this->is_registered) ? true : false; - - // Create or update the session - $sql_ary = array( - 'session_user_id' => (int) $this->data['user_id'], - 'session_start' => (int) $this->time_now, - 'session_last_visit' => (int) $this->data['session_last_visit'], - 'session_time' => (int) $this->time_now, - 'session_browser' => (string) trim(substr($this->system['browser'], 0, 149)), - 'session_forwarded_for' => (string) $this->system['forwarded_for'], - 'session_ip' => (string) $this->system['ip'], - 'session_autologin' => ($session_autologin) ? 1 : 0, - 'session_admin' => ($set_admin) ? 1 : 0, - 'session_viewonline' => ($viewonline) ? 1 : 0, - ); - - if ($this->update_session_page) - { - $sql_ary['session_page'] = (string) substr($this->system['page']['page'], 0, 199); - } - - phpbb::$db->sql_return_on_error(true); - - // Delete old session, if user id now different from anonymous - if (!defined('IN_ERROR_HANDLER')) - { - // We do not care about the user id, because we assign a new session later - $sql = 'DELETE - FROM ' . SESSIONS_TABLE . " - WHERE session_id = '" . phpbb::$db->sql_escape($this->session_id) . "'"; - $result = phpbb::$db->sql_query($sql); - - // If there were no sessions or the session id empty (then the affected rows will be empty too), then we have a brand new session and can check the active sessions limit - if ((!$result || !phpbb::$db->sql_affectedrows()) && (empty($this->data['session_time']) && phpbb::$config['active_sessions'])) - { - $sql = 'SELECT COUNT(session_id) AS sessions - FROM ' . SESSIONS_TABLE . ' - WHERE session_time >= ' . ($this->time_now - 60); - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ((int) $row['sessions'] > (int) phpbb::$config['active_sessions']) - { - header('HTTP/1.1 503 Service Unavailable'); - trigger_error('BOARD_UNAVAILABLE'); - } - } - } - - // Something quite important: session_page always holds the *last* page visited, except for the *first* visit. - // We are not able to simply have an empty session_page btw, therefore we need to tell phpBB how to detect this special case. - // If the session id is empty, we have a completely new one and will set an "identifier" here. This identifier is able to be checked later. - if (empty($this->data['session_id'])) - { - // This is a temporary variable, only set for the very first visit - $this->data['session_created'] = true; - } - - $this->session_id = $this->data['session_id'] = md5(phpbb::$security->unique_id()); - - $sql_ary['session_id'] = (string) $this->session_id; - - $sql = 'INSERT INTO ' . SESSIONS_TABLE . ' ' . phpbb::$db->sql_build_array('INSERT', $sql_ary); - phpbb::$db->sql_query($sql); - - phpbb::$db->sql_return_on_error(false); - - // Regenerate autologin/persistent login key - if ($session_autologin) - { - $this->set_login_key(); - } - - // refresh data - $this->data = array_merge($this->data, $sql_ary); - - if (!$bot) - { - $cookie_expire = $this->time_now + ((phpbb::$config['max_autologin_time']) ? 86400 * (int) phpbb::$config['max_autologin_time'] : 31536000); - - $this->set_cookie('u', $this->cookie_data['u'], $cookie_expire); - $this->set_cookie('k', $this->cookie_data['k'], $cookie_expire); - $this->set_cookie('sid', $this->session_id, $cookie_expire); - - unset($cookie_expire); - - // Only one session entry present... - $sql = 'SELECT COUNT(session_id) AS sessions - FROM ' . SESSIONS_TABLE . ' - WHERE session_user_id = ' . (int) $this->data['user_id'] . ' - AND session_time >= ' . (int) ($this->time_now - (max(phpbb::$config['session_length'], phpbb::$config['form_token_lifetime']))); - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ((int) $row['sessions'] <= 1 || empty($this->data['user_form_salt'])) - { - $this->data['user_form_salt'] = phpbb::$security->unique_id(); - - // Update the form key - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_form_salt = \'' . phpbb::$db->sql_escape($this->data['user_form_salt']) . '\' - WHERE user_id = ' . (int) $this->data['user_id']; - phpbb::$db->sql_query($sql); - } - } - else - { - $this->data['session_time'] = $this->data['session_last_visit'] = $this->time_now; - - // Update the last visit time - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_lastvisit = ' . (int) $this->data['session_time'] . ' - WHERE user_id = ' . (int) $this->data['user_id']; - phpbb::$db->sql_query($sql); - - $this->session_id = ''; - } - - return true; - } - - /** - * Kills a session - * - * This method does what it says on the tin. It will delete a pre-existing session. - * It resets cookie information (destroying any autologin key within that cookie data) - * and update the users information from the relevant session data. It will then - * grab guest user information. - * - * @param bool $new_session If true a new session will be generated after the original one got killed. - * @access public - */ - public function session_kill($new_session = true) - { - $sql = 'DELETE FROM ' . SESSIONS_TABLE . " - WHERE session_id = '" . phpbb::$db->sql_escape($this->session_id) . "' - AND session_user_id = " . (int) $this->data['user_id']; - phpbb::$db->sql_query($sql); - - // Allow connecting logout with external auth method logout - if ($this->auth !== false && method_exists($this->auth, 'logout')) - { - $this->auth->logout($this, $new_session); - } - - if ($this->data['user_id'] != ANONYMOUS) - { - // Delete existing session, update last visit info first! - if (!isset($this->data['session_time'])) - { - $this->data['session_time'] = time(); - } - - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_lastvisit = ' . (int) $this->data['session_time'] . ' - WHERE user_id = ' . (int) $this->data['user_id']; - phpbb::$db->sql_query($sql); - - if ($this->cookie_data['k']) - { - $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . ' - WHERE user_id = ' . (int) $this->data['user_id'] . " - AND key_id = '" . phpbb::$db->sql_escape(md5($this->cookie_data['k'])) . "'"; - phpbb::$db->sql_query($sql); - } - - // Reset the data array - $this->data = array(); - - $sql = 'SELECT * - FROM ' . USERS_TABLE . ' - WHERE user_id = ' . ANONYMOUS; - $result = phpbb::$db->sql_query($sql); - $this->data = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - } - - $cookie_expire = $this->time_now - 31536000; - $this->set_cookie('u', '', $cookie_expire); - $this->set_cookie('k', '', $cookie_expire); - $this->set_cookie('sid', '', $cookie_expire); - unset($cookie_expire); - - $this->session_id = ''; - - // To make sure a valid session is created we create one for the anonymous user - if ($new_session) - { - $this->session_create(ANONYMOUS); - } - } - - /** - * Session garbage collection - * - * This looks a lot more complex than it really is. Effectively we are - * deleting any sessions older than an admin definable limit. Due to the - * way in which we maintain session data we have to ensure we update user - * data before those sessions are destroyed. In addition this method - * removes autologin key information that is older than an admin defined - * limit. - * - * @access public - */ - public function session_gc() - { - $batch_size = 10; - - if (!$this->time_now) - { - $this->time_now = time(); - } - - // Firstly, delete guest sessions - $sql = 'DELETE FROM ' . SESSIONS_TABLE . ' - WHERE session_user_id = ' . ANONYMOUS . ' - AND session_time < ' . (int) ($this->time_now - phpbb::$config['session_length']); - phpbb::$db->sql_query($sql); - - // Get expired sessions, only most recent for each user - $sql = 'SELECT session_user_id, session_page, MAX(session_time) AS recent_time - FROM ' . SESSIONS_TABLE . ' - WHERE session_time < ' . ($this->time_now - phpbb::$config['session_length']) . ' - GROUP BY session_user_id, session_page'; - $result = phpbb::$db->sql_query_limit($sql, $batch_size); - - $del_user_id = array(); - $del_sessions = 0; - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_lastvisit = ' . (int) $row['recent_time'] . ", user_lastpage = '" . phpbb::$db->sql_escape($row['session_page']) . "' - WHERE user_id = " . (int) $row['session_user_id']; - phpbb::$db->sql_query($sql); - - $del_user_id[] = (int) $row['session_user_id']; - $del_sessions++; - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($del_user_id)) - { - // Delete expired sessions - $sql = 'DELETE FROM ' . SESSIONS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('session_user_id', $del_user_id) . ' - AND session_time < ' . ($this->time_now - phpbb::$config['session_length']); - phpbb::$db->sql_query($sql); - } - - if ($del_sessions < $batch_size) - { - // Less than 10 users, update gc timer ... else we want gc - // called again to delete other sessions - set_config('session_last_gc', $this->time_now, true); - - if (phpbb::$config['max_autologin_time']) - { - $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . ' - WHERE last_login < ' . (time() - (86400 * (int) phpbb::$config['max_autologin_time'])); - phpbb::$db->sql_query($sql); - } - - // only called from CRON; should be a safe workaround until the infrastructure gets going - if (!class_exists('captcha_factory')) - { - include(PHPBB_ROOT_PATH . "includes/captcha/captcha_factory." . PHP_EXT); - } - captcha_factory::garbage_collect(phpbb::$config['captcha_plugin']); - } - - return; - } - - - /** - * Sets a cookie of the given name with the specified data for the given length of time. If no time is specified, a session cookie will be set. - * - * @param string $name Name of the cookie, will be automatically prefixed with the phpBB cookie name. Track becomes [cookie_name]_track then. - * @param string $cookiedata The data to hold within the cookie - * @param int $cookietime The expiration time as UNIX timestamp. If 0 is provided, a session cookie is set. - * - * @access public - */ - public function set_cookie($name, $cookiedata, $cookietime) - { - $name_data = rawurlencode(phpbb::$config['cookie_name'] . '_' . $name) . '=' . rawurlencode($cookiedata); - $expire = gmdate('D, d-M-Y H:i:s \\G\\M\\T', $cookietime); - $domain = (!phpbb::$config['cookie_domain'] || phpbb::$config['cookie_domain'] == 'localhost' || phpbb::$config['cookie_domain'] == '127.0.0.1') ? '' : '; domain=' . phpbb::$config['cookie_domain']; - - header('Set-Cookie: ' . $name_data . (($cookietime) ? '; expires=' . $expire : '') . '; path=' . phpbb::$config['cookie_path'] . $domain . ((!phpbb::$config['cookie_secure']) ? '' : '; secure') . '; HttpOnly', false); - } - - /** - * Check for banned user - * - * Checks whether the supplied user is banned by id, ip or email. If no parameters - * are passed to the method pre-existing session data is used. If $return is false - * this routine does not return on finding a banned user, it outputs a relevant - * message and stops execution. - * - * @param int $user_id The user id to check. If false then do not check user ids - * @param string|array $user_ips Can contain a string with one IP or an array of multiple IPs. If false then no ips are checked. - * @param int $user_email The email address to check - * @param bool $return If false then the banned message is displayed and script halted - * - * @return bool|string True if banned and no reason given. - * False if not banned. A ban reason if banned and ban reason given. Check for !== false. - * @access public - */ - public function check_ban($user_id = false, $user_ips = false, $user_email = false, $return = false) - { - if (defined('IN_CHECK_BAN')) - { - return; - } - - $banned = false; - $cache_ttl = 3600; - $where_sql = array(); - - $sql = 'SELECT ban_ip, ban_userid, ban_email, ban_exclude, ban_give_reason, ban_end - FROM ' . BANLIST_TABLE . ' - WHERE '; - - // Determine which entries to check, only return those - if ($user_email === false) - { - $where_sql[] = "ban_email = ''"; - } - - if ($user_ips === false) - { - $where_sql[] = "(ban_ip = '' OR ban_exclude = 1)"; - } - - if ($user_id === false) - { - $where_sql[] = '(ban_userid = 0 OR ban_exclude = 1)'; - } - else - { - $cache_ttl = ($user_id == ANONYMOUS) ? 3600 : 0; - $_sql = '(ban_userid = ' . $user_id; - - if ($user_email !== false) - { - $_sql .= " OR ban_email <> ''"; - } - - if ($user_ips !== false) - { - $_sql .= " OR ban_ip <> ''"; - } - - $_sql .= ')'; - - $where_sql[] = $_sql; - } - - $sql .= (sizeof($where_sql)) ? implode(' AND ', $where_sql) : ''; - $result = phpbb::$db->sql_query($sql, $cache_ttl); - - $ban_triggered_by = 'user'; - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($row['ban_end'] && $row['ban_end'] < time()) - { - continue; - } - - $ip_banned = false; - if (!empty($row['ban_ip'])) - { - if (!is_array($user_ips)) - { - $ip_banned = preg_match('#^' . str_replace('\*', '.*?', preg_quote($row['ban_ip'], '#')) . '$#i', $user_ips); - } - else - { - foreach ($user_ips as $user_ip) - { - if (preg_match('#^' . str_replace('\*', '.*?', preg_quote($row['ban_ip'], '#')) . '$#i', $user_ip)) - { - $ip_banned = true; - break; - } - } - } - } - - if ((!empty($row['ban_userid']) && intval($row['ban_userid']) == $user_id) || - $ip_banned || - (!empty($row['ban_email']) && preg_match('#^' . str_replace('\*', '.*?', preg_quote($row['ban_email'], '#')) . '$#i', $user_email))) - { - if (!empty($row['ban_exclude'])) - { - $banned = false; - break; - } - else - { - $banned = true; - $ban_row = $row; - - if (!empty($row['ban_userid']) && intval($row['ban_userid']) == $user_id) - { - $ban_triggered_by = 'user'; - } - else if ($ip_banned) - { - $ban_triggered_by = 'ip'; - } - else - { - $ban_triggered_by = 'email'; - } - - // Don't break. Check if there is an exclude rule for this user - } - } - } - phpbb::$db->sql_freeresult($result); - - if ($banned && !$return) - { - // If the session is empty we need to create a valid one... - if (empty($this->session_id)) - { - // This seems to be no longer needed? - #14971 -// $this->session_create(ANONYMOUS); - } - - // Initiate environment ... since it won't be set at this stage - $this->setup(); - - // Logout the user, banned users are unable to use the normal 'logout' link - if ($this->data['user_id'] != ANONYMOUS) - { - $this->session_kill(); - } - - // We show a login box here to allow founders accessing the board if banned by IP - if (defined('IN_LOGIN') && $this->data['user_id'] == ANONYMOUS) - { - $this->setup('ucp'); - $this->is_registered = $this->is_bot = $this->is_founder = false; - $this->is_guest = true; - - // Set as a precaution to allow login_box() handling this case correctly as well as this function not being executed again. - define('IN_CHECK_BAN', 1); - - login_box('index.' . PHP_EXT); - - // The false here is needed, else the user is able to circumvent the ban. - $this->session_kill(false); - } - - // Ok, we catch the case of an empty session id for the anonymous user... - // This can happen if the user is logging in, banned by username and the login_box() being called "again". - if (empty($this->session_id) && defined('IN_CHECK_BAN')) - { - $this->session_create(ANONYMOUS); - } - - - // Determine which message to output - $till_date = ($ban_row['ban_end']) ? $this->format_date($ban_row['ban_end']) : ''; - $message = ($ban_row['ban_end']) ? 'BOARD_BAN_TIME' : 'BOARD_BAN_PERM'; - - $message = sprintf($this->lang[$message], $till_date, '<a href="mailto:' . phpbb::$config['board_contact'] . '">', '</a>'); - $message .= ($ban_row['ban_give_reason']) ? '<br /><br />' . sprintf($this->lang['BOARD_BAN_REASON'], $ban_row['ban_give_reason']) : ''; - $message .= '<br /><br /><em>' . $this->lang['BAN_TRIGGERED_BY_' . strtoupper($ban_triggered_by)] . '</em>'; - - // To circumvent session_begin returning a valid value and the check_ban() not called on second page view, we kill the session again - $this->session_kill(false); - - // A very special case... we are within the cron script which is not supposed to print out the ban message... show blank page - if (defined('IN_CRON')) - { - garbage_collection(); - exit_handler(); - exit; - } - - trigger_error($message); - } - - return ($banned && $ban_row['ban_give_reason']) ? $ban_row['ban_give_reason'] : $banned; - } - - /** - * Check if ip is blacklisted - * This should be called only where absolutly necessary - * - * Only IPv4 (rbldns does not support AAAA records/IPv6 lookups) - * - * @param string $mode Possible modes are: register and post - * spamhaus.org is used for both modes. Spamcop.net is additionally used for register. - * @param string $ip The ip to check. If false then the current IP is used - * - * @return bool|array False if ip is not blacklisted, else an array([checked server], [lookup]) - * @author satmd (from the php manual) - * @access public - */ - public function check_dnsbl($mode, $ip = false) - { - if ($ip === false) - { - $ip = $this->system['ip']; - } - - $dnsbl_check = array( - 'sbl-xbl.spamhaus.org' => 'http://www.spamhaus.org/query/bl?ip=', - ); - - if ($mode == 'register') - { - $dnsbl_check['bl.spamcop.net'] = 'http://spamcop.net/bl.shtml?'; - } - - if ($ip) - { - $quads = explode('.', $ip); - $reverse_ip = $quads[3] . '.' . $quads[2] . '.' . $quads[1] . '.' . $quads[0]; - - // Need to be listed on all servers... - $listed = true; - $info = array(); - - foreach ($dnsbl_check as $dnsbl => $lookup) - { - if (phpbb_checkdnsrr($reverse_ip . '.' . $dnsbl . '.', 'A') === true) - { - $info = array($dnsbl, $lookup . $ip); - } - else - { - $listed = false; - } - } - - if ($listed) - { - return $info; - } - } - - return false; - } - - /** - * Set/Update a persistent login key - * - * This method creates or updates a persistent session key. When a user makes - * use of persistent (formerly auto-) logins a key is generated and stored in the - * DB. When they revisit with the same key it's automatically updated in both the - * DB and cookie. Multiple keys may exist for each user representing different - * browsers or locations. As with _any_ non-secure-socket no passphrase login this - * remains vulnerable to exploit. - * - * @param int $user_id The user id. If false the current users user id will be used - * @param string $key A login key. If false then the current users login key stored within the cookie will be used - * @param string $user_ip The users ip. If false, then the current users IP will be used - * @access public - */ - public function set_login_key($user_id = false, $key = false, $user_ip = false) - { - $user_id = ($user_id === false) ? $this->data['user_id'] : $user_id; - $user_ip = ($user_ip === false) ? $this->system['ip'] : $user_ip; - $key = ($key === false) ? (($this->cookie_data['k']) ? $this->cookie_data['k'] : false) : $key; - - $key_id = phpbb::$security->unique_id(hexdec(substr($this->session_id, 0, 8))); - - $sql_ary = array( - 'key_id' => (string) md5($key_id), - 'last_ip' => (string) $this->system['ip'], - 'last_login' => (int) $this->time_now, - ); - - if (!$key) - { - $sql_ary += array( - 'user_id' => (int) $user_id - ); - } - - if ($key) - { - $sql = 'UPDATE ' . SESSIONS_KEYS_TABLE . ' - SET ' . phpbb::$db->sql_build_array('UPDATE', $sql_ary) . ' - WHERE user_id = ' . (int) $user_id . " - AND key_id = '" . phpbb::$db->sql_escape(md5($key)) . "'"; - } - else - { - $sql = 'INSERT INTO ' . SESSIONS_KEYS_TABLE . ' ' . phpbb::$db->sql_build_array('INSERT', $sql_ary); - } - phpbb::$db->sql_query($sql); - - $this->cookie_data['k'] = $key_id; - } - - /** - * Reset all login keys for the specified user - * - * This method removes all current login keys for a specified (or the current) - * user. It will be called on password change to render old keys unusable - * - * @param int $user_id The user id. If false then the current users user id is used. - * @access public - */ - public function reset_login_keys($user_id = false) - { - $user_id = ($user_id === false) ? $this->data['user_id'] : $user_id; - - $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . ' - WHERE user_id = ' . (int) $user_id; - phpbb::$db->sql_query($sql); - - // Let's also clear any current sessions for the specified user_id - // If it's the current user then we'll leave this session intact - $sql_where = 'session_user_id = ' . (int) $user_id; - $sql_where .= ($user_id === $this->data['user_id']) ? " AND session_id <> '" . phpbb::$db->sql_escape($this->session_id) . "'" : ''; - - $sql = 'DELETE FROM ' . SESSIONS_TABLE . " - WHERE $sql_where"; - phpbb::$db->sql_query($sql); - - // We're changing the password of the current user and they have a key - // Lets regenerate it to be safe - if ($user_id === $this->data['user_id'] && $this->cookie_data['k']) - { - $this->set_login_key($user_id); - } - } - - /** - * Reset all admin sessions - * - * @access public - */ - public function unset_admin() - { - $sql = 'UPDATE ' . SESSIONS_TABLE . " - SET session_admin = 0 - WHERE session_id = '" . phpbb::$db->sql_escape($this->session_id) . "'"; - phpbb::$db->sql_query($sql); - } - - /** - * Check if a valid, non-expired session exist. Also make sure it errors out correctly if we do not have a db-setup yet. ;) - * - * @return bool True if a valid, non-expired session exist - * @access private - */ - private function session_exist() - { - // If session is empty or does not match the session within the URL (if required - set by NEED_SID), then we need a new session - if (empty($this->session_id) || ($this->need_sid && $this->session_id !== phpbb_request::variable('sid', '', false, phpbb_request::GET))) - { - return false; - } - - // If the db is not initialized/registered, then we also need a new session (we are not able to go forward then... - if (!phpbb::registered('db')) - { - return false; - } - - // Now finally check the db for our provided session - $sql = 'SELECT u.*, s.* - FROM ' . SESSIONS_TABLE . ' s, ' . USERS_TABLE . " u - WHERE s.session_id = '" . phpbb::$db->sql_escape($this->session_id) . "' - AND u.user_id = s.session_user_id"; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - // Also new session if it has not been found. ;) - if (!$row) - { - return false; - } - - $this->data = $row; - - // Now check the ip, the browser, forwarded for and referer - if (!$this->session_valid()) - { - return false; - } - - // Ok, we are not finished yet. We need to know if the session is expired - - // Check whether the session is still valid if we have one - if ($this->auth !== false && method_exists($this->auth, 'validate_session')) - { - if (!$this->auth->validate_session($this)) - { - return false; - } - } - - // Check the session length timeframe if autologin is not enabled. - // Else check the autologin length... and also removing those having autologin enabled but no longer allowed board-wide. - if (!$this->data['session_autologin']) - { - if ($this->data['session_time'] < $this->time_now - (phpbb::$config['session_length'] + 60)) - { - return false; - } - } - else if (!phpbb::$config['allow_autologin'] || (phpbb::$config['max_autologin_time'] && $this->data['session_time'] < $this->time_now - (86400 * (int) phpbb::$config['max_autologin_time']) + 60)) - { - return false; - } - - // Only update session DB a minute or so after last update or if page changes - if ($this->time_now - $this->data['session_time'] > 60 || ($this->update_session_page && $this->data['session_page'] != $this->system['page']['page'])) - { - $sql_ary = array('session_time' => $this->time_now); - - if ($this->update_session_page) - { - $sql_ary['session_page'] = substr($this->system['page']['page'], 0, 199); - $sql_ary['session_forum_id'] = $this->system['page']['forum']; - } - - $sql = 'UPDATE ' . SESSIONS_TABLE . ' SET ' . phpbb::$db->sql_build_array('UPDATE', $sql_ary) . " - WHERE session_id = '" . phpbb::$db->sql_escape($this->session_id) . "'"; - phpbb::$db->sql_query($sql); - } - - $this->is_registered = ($this->data['user_id'] != ANONYMOUS && ($this->data['user_type'] == phpbb::USER_NORMAL || $this->data['user_type'] == phpbb::USER_FOUNDER)) ? true : false; - $this->is_bot = (!$this->is_registered && $this->data['user_id'] != ANONYMOUS) ? true : false; - $this->is_founder = $this->data['user_type'] == phpbb::USER_FOUNDER; - $this->is_guest = (!$this->is_registered && $this->data['user_id'] == ANONYMOUS) ? true : false; - $this->data['user_lang'] = basename($this->data['user_lang']); - - return true; - } - - /** - * Check if the request originated from the same page. - * - * @param bool $check_script_path If true, the path will be checked as well - * - * @return bool True if the referer is valid - * @access private - */ - private function validate_referer($check_script_path = false) - { - // no referer - nothing to validate, user's fault for turning it off (we only check on POST; so meta can't be the reason) - if (empty($this->system['referer']) || empty($this->system['host'])) - { - return true; - } - - // Specialchar host, because it's the only one not specialchared - $host = htmlspecialchars($this->system['host']); - $ref = substr($this->system['referer'], strpos($this->system['referer'], '://') + 3); - - if (!(stripos($ref, $host) === 0)) - { - return false; - } - else if ($check_script_path && rtrim($this->system['page']['root_script_path'], '/') !== '') - { - $ref = substr($ref, strlen($host)); - $server_port = $this->system['port']; - - if ($server_port !== 80 && $server_port !== 443 && stripos($ref, ":$server_port") === 0) - { - $ref = substr($ref, strlen(":$server_port")); - } - - if (!(stripos(rtrim($ref, '/'), rtrim($this->system['page']['root_script_path'], '/')) === 0)) - { - return false; - } - } - - return true; - } - - /** - * Fill data array with a "faked" user account - * - * @return array Default user data array - * @access private - */ - private function default_data() - { - return array( - 'user_id' => ANONYMOUS, - ); - } - - /** - * Check for a bot by comparing user agent and ip - * - * Here we do a bot check, oh er saucy! No, not that kind of bot - * check. We loop through the list of bots defined by the admin and - * see if we have any useragent and/or IP matches. If we do, this is a - * bot, act accordingly - * - * @return bool True if it is a bot. - * @access private - */ - private function check_bot() - { - $bot = false; - - foreach (phpbb_cache::obtain_bots() as $row) - { - if ($row['bot_agent'] && preg_match('#' . str_replace('\*', '.*?', preg_quote($row['bot_agent'], '#')) . '#i', $this->system['browser'])) - { - $bot = $row['user_id']; - } - - // If ip is supplied, we will make sure the ip is matching too... - if ($row['bot_ip'] && ($bot || !$row['bot_agent'])) - { - // Set bot to false, then we only have to set it to true if it is matching - $bot = false; - - foreach (explode(',', $row['bot_ip']) as $bot_ip) - { - if (!trim($bot_ip)) - { - continue; - } - - if (strpos($this->system['ip'], $bot_ip) === 0) - { - $bot = (int) $row['user_id']; - break; - } - } - } - - if ($bot) - { - break; - } - } - - return $bot; - } - - /** - * Check if session is valid by comparing ip, forwarded for, browser and referer - * - * @param bool $log_failure If true then a non-match will be logged. Can cause huge logs. - * - * @return bool True if the session is valid - * @access private - */ - private function session_valid($log_failure = true) - { - // Validate IP length according to admin ... enforces an IP - // check on bots if admin requires this -// $quadcheck = (phpbb::$config['ip_check_bot'] && $this->data['user_type'] & USER_BOT) ? 4 : phpbb::$config['ip_check']; - - if (strpos($this->system['ip'], ':') !== false && strpos($this->data['session_ip'], ':') !== false) - { - $session_ip = short_ipv6($this->data['session_ip'], phpbb::$config['ip_check']); - $user_ip = short_ipv6($this->system['ip'], phpbb::$config['ip_check']); - } - else - { - $session_ip = implode('.', array_slice(explode('.', $this->data['session_ip']), 0, phpbb::$config['ip_check'])); - $user_ip = implode('.', array_slice(explode('.', $this->system['ip']), 0, phpbb::$config['ip_check'])); - } - - $session_browser = (phpbb::$config['browser_check']) ? trim(strtolower(substr($this->data['session_browser'], 0, 149))) : ''; - $user_browser = (phpbb::$config['browser_check']) ? trim(strtolower(substr($this->system['browser'], 0, 149))) : ''; - - $session_forwarded_for = (phpbb::$config['forwarded_for_check']) ? substr($this->data['session_forwarded_for'], 0, 254) : ''; - $user_forwarded_for = (phpbb::$config['forwarded_for_check']) ? substr($this->system['forwarded_for'], 0, 254) : ''; - - // referer checks - $check_referer_path = phpbb::$config['referer_validation'] == REFERER_VALIDATE_PATH; - $referer_valid = true; - - // we assume HEAD and TRACE to be foul play and thus only whitelist GET - if (phpbb::$config['referer_validation'] && $this->system['request_method']) - { - $referer_valid = $this->validate_referer($check_referer_path); - } - - if ($user_ip !== $session_ip || $user_browser !== $session_browser || $user_forwarded_for !== $session_forwarded_for || !$referer_valid) - { - // Added logging temporarly to help debug bugs... - if (phpbb::$base_config['debug_extra'] && $this->data['user_id'] != ANONYMOUS && $log_failure) - { - if ($referer_valid) - { - add_log('critical', 'LOG_IP_BROWSER_FORWARDED_CHECK', $user_ip, $session_ip, $user_browser, $session_browser, htmlspecialchars($user_forwarded_for), htmlspecialchars($session_forwarded_for)); - } - else - { - add_log('critical', 'LOG_REFERER_INVALID', $this->system['referer']); - } - } - - return false; - } - - return true; - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/classes/template.php b/phpBB/includes/classes/template.php deleted file mode 100644 index 1ef29545d2..0000000000 --- a/phpBB/includes/classes/template.php +++ /dev/null @@ -1,531 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group, sections (c) 2001 ispi of Lincoln Inc -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* @todo -* IMG_ for image substitution? -* {IMG_[key]:[alt]:[type]} -* {IMG_ICON_CONTACT:CONTACT:full} -> phpbb::$user->img('icon_contact', 'CONTACT', 'full'); -* -* More in-depth... -* yadayada -*/ - -/** -* Base Template class. -* @package phpBB3 -*/ -class phpbb_template -{ - public $phpbb_required = array('user', 'config'); - public $phpbb_optional = array(); - - /** - * variable that holds all the data we'll be substituting into - * the compiled templates. Takes form: - * --> $this->_tpldata[block][iteration#][child][iteration#][child2][iteration#][variablename] == value - * if it's a root-level variable, it'll be like this: - * --> $this->_tpldata[.][0][varname] == value - * @var array - */ - private $_tpldata = array('.' => array(0 => array())); - - /** - * @var array Reference to template->_tpldata['.'][0] - */ - private $_rootref; - - /** - * @var string Root dir for template. - */ - private $root = ''; - - /** - * @var string Path of the cache directory for the template - */ - public $cachepath = ''; - - /** - * @var array Hash of handle => file path pairs - */ - public $files = array(); - - /** - * @var array Hash of handle => filename pairs - */ - public $filename = array(); - - /** - * Set template location - * @access public - */ - public function set_template() - { - if (file_exists(PHPBB_ROOT_PATH . 'styles/' . phpbb::$user->theme['template_path'] . '/template')) - { - $this->root = PHPBB_ROOT_PATH . 'styles/' . phpbb::$user->theme['template_path'] . '/template'; - $this->cachepath = PHPBB_ROOT_PATH . 'cache/tpl_' . phpbb::$user->theme['template_path'] . '_'; - } - else - { - trigger_error('Template path could not be found: styles/' . phpbb::$user->theme['template_path'] . '/template', E_USER_ERROR); - } - - $this->_rootref = &$this->_tpldata['.'][0]; - } - - /** - * Set custom template location (able to use directory outside of phpBB) - * @access public - * @param string $template_path Path to template directory - * @param string $template_name Name of template - */ - public function set_custom_template($template_path, $template_name) - { - $this->root = $template_path; - $this->cachepath = PHPBB_ROOT_PATH . 'cache/ctpl_' . str_replace('_', '-', $template_name) . '_'; - } - - /** - * Sets the template filenames for handles. $filename_array - * @access public - * @param array $filname_array Should be a hash of handle => filename pairs. - */ - public function set_filenames(array $filename_array) - { - foreach ($filename_array as $handle => $filename) - { - if (empty($filename)) - { - trigger_error("template->set_filenames: Empty filename specified for $handle", E_USER_ERROR); - } - - $this->filename[$handle] = $filename; - $this->files[$handle] = $this->root . '/' . $filename; - } - - return true; - } - - /** - * Destroy template data set - * @access public - */ - public function __destruct() - { - $this->_tpldata = array('.' => array(0 => array())); - } - - /** - * Reset/empty complete block - * @access public - * @param string $blockname Name of block to destroy - */ - public function destroy_block_vars($blockname) - { - if (strpos($blockname, '.') !== false) - { - // Nested block. - $blocks = explode('.', $blockname); - $blockcount = sizeof($blocks) - 1; - - $str = &$this->_tpldata; - for ($i = 0; $i < $blockcount; $i++) - { - $str = &$str[$blocks[$i]]; - $str = &$str[sizeof($str) - 1]; - } - - unset($str[$blocks[$blockcount]]); - } - else - { - // Top-level block. - unset($this->_tpldata[$blockname]); - } - } - - /** - * Display handle - * @access public - * @param string $handle Handle to display - * @param bool $include_once Allow multiple inclusions - * @return bool True on success, false on failure - */ - public function display($handle, $include_once = true) - { -/* - if (!empty($phpbb_hook) && $phpbb_hook->call_hook(array(__CLASS__, __FUNCTION__), $handle, $include_once)) - { - if ($phpbb_hook->hook_return(array(__CLASS__, __FUNCTION__))) - { - return $phpbb_hook->hook_return_result(array(__CLASS__, __FUNCTION__)); - } - } -*/ -/* if (defined('IN_ERROR_HANDLER')) - { - if ((E_NOTICE & error_reporting()) == E_NOTICE) - { - //error_reporting(error_reporting() ^ E_NOTICE); - } - }*/ - - $_tpldata = &$this->_tpldata; - $_rootref = &$this->_rootref; - $_lang = &phpbb::$user->lang; - - if (($filename = $this->_tpl_load($handle)) !== false) - { - ($include_once) ? include_once($filename) : include($filename); - } - else if (($code = $this->_tpl_eval($handle)) !== false) - { - $code = ' ?> ' . $code . ' <?php '; - eval($code); - } - else - { - // if we could not eval AND the file exists, something horrific has occured - return false; - } - - return true; - } - - /** - * Display the handle and assign the output to a template variable or return the compiled result. - * @access public - * @param string $handle Handle to operate on - * @param string $template_var Template variable to assign compiled handle to - * @param bool $return_content If true return compiled handle, otherwise assign to $template_var - * @param bool $include_once Allow multiple inclusions of the file - * @return bool|string If $return_content is true return string of the compiled handle, otherwise return true - */ - public function assign_display($handle, $template_var = '', $return_content = true, $include_once = false) - { - ob_start(); - $this->display($handle, $include_once); - $contents = ob_get_clean(); - - if ($return_content) - { - return $contents; - } - - $this->assign_var($template_var, $contents); - - return true; - } - - /** - * Load a compiled template if possible, if not, recompile it - * @access private - * @param string $handle Handle of the template to load - * @return string|bool Return filename on success otherwise false - * @uses template_compile is used to compile uncached templates - */ - private function _tpl_load($handle) - { - if (!isset($this->filename[$handle])) - { - trigger_error("template->_tpl_load(): No file specified for handle $handle", E_USER_ERROR); - } - - $filename = $this->cachepath . str_replace('/', '.', $this->filename[$handle]) . '.' . PHP_EXT; - - $recompile = (!file_exists($filename) || @filesize($filename) === 0 || (phpbb::$config['load_tplcompile'] && @filemtime($filename) < filemtime($this->files[$handle]))) ? true : false; - - if (phpbb::$base_config['debug_extra']) - { - $recompile = true; - } - - // Recompile page if the original template is newer, otherwise load the compiled version - if ($recompile) - { - $compile = new phpbb_template_compile($this); - - // If we don't have a file assigned to this handle, die. - if (!isset($this->files[$handle])) - { - trigger_error("template->_tpl_load(): No file specified for handle $handle", E_USER_ERROR); - } - - if ($compile->_tpl_load_file($handle) === false) - { - return false; - } - } - - return $filename; - } - - /** - * This code should only run when some high level error prevents us from writing to the cache. - * @access private - * @param string $handle Template handle to compile - * @return string|bool Return compiled code on success otherwise false - * @uses template_compile is used to compile template - */ - private function _tpl_eval($handle) - { - $compile = new phpbb_template_compile($this); - - // If we don't have a file assigned to this handle, die. - if (!isset($this->files[$handle])) - { - trigger_error("template->_tpl_eval(): No file specified for handle $handle", E_USER_ERROR); - } - - if (($code = $compile->_tpl_gen_src($handle)) === false) - { - return false; - } - - return $code; - } - - /** - * Assign key variable pairs from an array - * @access public - * @param array $vararray A hash of variable name => value pairs - */ - public function assign_vars(array $vararray) - { - foreach ($vararray as $key => $val) - { - $this->_rootref[$key] = $val; - } - } - - /** - * Assign a single variable to a single key - * @access public - * @param string $varname Variable name - * @param string $varval Value to assign to variable - */ - public function assign_var($varname, $varval) - { - $this->_rootref[$varname] = $varval; - } - - /** - * Assign key variable pairs from an array to a specified block - * @access public - * @param string $blockname Name of block to assign $vararray to - * @param array $vararray A hash of variable name => value pairs - */ - public function assign_block_vars($blockname, array $vararray) - { - if (strpos($blockname, '.') !== false) - { - // Nested block. - $blocks = explode('.', $blockname); - $blockcount = sizeof($blocks) - 1; - - $str = &$this->_tpldata; - for ($i = 0; $i < $blockcount; $i++) - { - $str = &$str[$blocks[$i]]; - $str = &$str[sizeof($str) - 1]; - } - - // Now we add the block that we're actually assigning to. - // We're adding a new iteration to this block with the given - // variable assignments. - $str[$blocks[$blockcount]][] = $vararray; - } - else - { - // Top-level block. - - // Add a new iteration to this block with the variable assignments we were given. - $this->_tpldata[$blockname][] = $vararray; - } - } - - /** - * Change already assigned key variable pair (one-dimensional - single loop entry) - * - * An example of how to use this function: - * - * @param string $blockname the blockname, for example 'loop' - * @param array $vararray the var array to insert/add or merge - * @param mixed $key Key to search for - * - * array: KEY => VALUE [the key/value pair to search for within the loop to determine the correct position] - * - * int: Position [the position to change or insert at directly given] - * - * If key is false the position is set to 0 - * If key is true the position is set to the last entry - * - * @param string $mode Mode to execute (valid modes are 'insert' and 'change') - * - * If insert, the vararray is inserted at the given position (position counting from zero). - * If change, the current block gets merged with the vararray (resulting in new key/value pairs be added and existing keys be replaced by the new value). - * - * Since counting begins by zero, inserting at the last position will result in this array: array(vararray, last positioned array) - * and inserting at position 1 will result in this array: array(first positioned array, vararray, following vars) - * - * @return bool false on error, true on success - * @access public - */ - public function alter_block_array($blockname, array $vararray, $key = false, $mode = 'insert') - { - if (strpos($blockname, '.') !== false) - { - // Nested block. - $blocks = explode('.', $blockname); - $blockcount = sizeof($blocks) - 1; - - $block = &$this->_tpldata; - for ($i = 0; $i < $blockcount; $i++) - { - if (($pos = strpos($blocks[$i], '[')) !== false) - { - $name = substr($blocks[$i], 0, $pos); - - if (strpos($blocks[$i], '[]') === $pos) - { - $index = sizeof($block[$name]) - 1; - } - else - { - $index = min((int) substr($blocks[$i], $pos + 1, -1), sizeof($block[$name]) - 1); - } - } - else - { - $name = $blocks[$i]; - $index = sizeof($block[$name]) - 1; - } - $block = &$block[$name]; - $block = &$block[$index]; - } - - $block = &$block[$blocks[$i]]; // Traverse the last block - } - else - { - // Top-level block. - $block = &$this->_tpldata[$blockname]; - } - - // Change key to zero (change first position) if false and to last position if true - if ($key === false || $key === true) - { - $key = ($key === false) ? 0 : sizeof($block); - } - - // Get correct position if array given - if (is_array($key)) - { - // Search array to get correct position - list($search_key, $search_value) = @each($key); - - $key = NULL; - foreach ($block as $i => $val_ary) - { - if ($val_ary[$search_key] === $search_value) - { - $key = $i; - break; - } - } - - // key/value pair not found - if ($key === NULL) - { - return false; - } - } - - // Insert Block - if ($mode == 'insert') - { - // Re-position template blocks - for ($i = sizeof($block); $i > $key; $i--) - { - $block[$i] = $block[$i-1]; - } - - // Insert vararray at given position - $block[$key] = $vararray; - - return true; - } - - // Which block to change? - if ($mode == 'change') - { - if ($key == sizeof($block)) - { - $key--; - } - - $block[$key] = array_merge($block[$key], $vararray); - - return true; - } - - return false; - } - - /** - * Include a separate template - * @access private - * @param string $filename Template filename to include - * @param bool $include True to include the file, false to just load it - * @uses template_compile is used to compile uncached templates - */ - private function _tpl_include($filename, $include = true) - { - $handle = $filename; - $this->filename[$handle] = $filename; - $this->files[$handle] = $this->root . '/' . $filename; - - $filename = $this->_tpl_load($handle); - - if ($include) - { - $_tpldata = &$this->_tpldata; - $_rootref = &$this->_rootref; - $_lang = &phpbb::$user->lang; - - if ($filename) - { - include($filename); - return; - } - else - { - $compile = new phpbb_template_compile($this); - - if (($code = $compile->_tpl_gen_src($handle)) !== false) - { - $code = ' ?> ' . $code . ' <?php '; - eval($code); - } - } - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/classes/template_compile.php b/phpBB/includes/classes/template_compile.php deleted file mode 100644 index 7880babc51..0000000000 --- a/phpBB/includes/classes/template_compile.php +++ /dev/null @@ -1,904 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group, sections (c) 2001 ispi of Lincoln Inc -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* The template filter that does the actual compilation -* @see template_compile -* @package phpBB3 -*/ -class phpbb_template_filter extends php_user_filter -{ - const REGEX_NS = '[a-z][a-z_0-9]+'; - - const REGEX_VAR = '[A-Z][A-Z_0-9]+'; - - const REGEX_TAG = '<!-- ([A-Z][A-Z_0-9]+)(?: (.*?) ?)?-->'; - - const REGEX_TOKENS = '~<!-- ([A-Z][A-Z_0-9]+)(?: (.*?) ?)?-->|{((?:[a-z][a-z_0-9]+\.)*\\$?[A-Z][A-Z_0-9]+)}~'; - - /** - * @var array - */ - private $block_names = array(); - - /** - * @var array - */ - private $block_else_level = array(); - - /** - * @var string - */ - private $chunk; - - public function filter($in, $out, &$consumed, $closing) - { - $written = false; - - while ($bucket = stream_bucket_make_writeable($in)) - { - $consumed += $bucket->datalen; - - $data = $this->chunk . $bucket->data; - $last_nl = strrpos($data, "\n"); - $this->chunk = substr($data, $last_nl); - $data = substr($data, 0, $last_nl); - - if (!strlen($data)) - { - continue; - } - - $written = true; - - $bucket->data = $this->compile($data); - $bucket->datalen = strlen($bucket->data); - stream_bucket_append($out, $bucket); - } - - if ($closing && strlen($this->chunk)) - { - $written = true; - $bucket = stream_bucket_new($this->stream, $this->compile($this->chunk)); - stream_bucket_append($out, $bucket); - } - - return $written ? PSFS_PASS_ON : PSFS_FEED_ME; - } - - public function onCreate() - { - $this->chunk = ''; - return true; - } - - private function compile($data) - { - $data = preg_replace('#<(?:[\\?%]|script)#s', '<?php echo\'\\0\';?>', $data); - return str_replace('?><?php', '', preg_replace_callback(self::REGEX_TOKENS, array($this, 'replace'), $data)); - } - - private function replace($matches) - { - if (isset($matches[3])) - { - return $this->compile_var_tags($matches[0]); - } - - switch ($matches[1]) - { - case 'BEGIN': - $this->block_else_level[] = false; - return '<?php ' . $this->compile_tag_block($matches[2]) . ' ?>'; - break; - - case 'BEGINELSE': - $this->block_else_level[sizeof($this->block_else_level) - 1] = true; - return '<?php }} else { ?>'; - break; - - case 'END': - array_pop($this->block_names); - return '<?php ' . ((array_pop($this->block_else_level)) ? '}' : '}}') . ' ?>'; - break; - - case 'IF': - return '<?php ' . $this->compile_tag_if($matches[2], false) . ' ?>'; - break; - - case 'ELSE': - return '<?php } else { ?>'; - break; - - case 'ELSEIF': - return '<?php ' . $this->compile_tag_if($matches[2], true) . ' ?>'; - break; - - case 'ENDIF': - return '<?php } ?>'; - break; - - case 'DEFINE': - return '<?php ' . $this->compile_tag_define($matches[2], true) . ' ?>'; - break; - - case 'UNDEFINE': - return '<?php ' . $this->compile_tag_define($matches[2], false) . ' ?>'; - break; - - case 'INCLUDE': - return '<?php ' . $this->compile_tag_include($matches[2]) . ' ?>'; - break; - - case 'INCLUDEPHP': - return (phpbb::$config['tpl_allow_php']) ? '<?php ' . $this->compile_tag_include_php($matches[2]) . ' ?>' : ''; - break; - - case 'PHP': - return (phpbb::$config['tpl_allow_php']) ? '<?php ' : '<!-- '; - break; - - case 'ENDPHP': - return (phpbb::$config['tpl_allow_php']) ? ' ?>' : ' -->'; - break; - - default: - return $matches[0]; - break; - - } - return ''; - } - - /** - * Compile variables - * @access private - */ - private function compile_var_tags(&$text_blocks) - { - // change template varrefs into PHP varrefs - $varrefs = array(); - - // This one will handle varrefs WITH namespaces - preg_match_all('#\{((?:' . self::REGEX_NS . '\.)+)(\$)?(' . self::REGEX_VAR . ')\}#', $text_blocks, $varrefs, PREG_SET_ORDER); - - foreach ($varrefs as $var_val) - { - $namespace = $var_val[1]; - $varname = $var_val[3]; - $new = $this->generate_block_varref($namespace, $varname, true, $var_val[2]); - - $text_blocks = str_replace($var_val[0], $new, $text_blocks); - } - - // Handle special language tags L_ and LA_ - $this->compile_language_tags($text_blocks); - - // This will handle the remaining root-level varrefs - $text_blocks = preg_replace('#\{(' . self::REGEX_VAR . ')\}#', "<?php echo (isset(\$_rootref['\\1'])) ? \$_rootref['\\1'] : ''; ?>", $text_blocks); - $text_blocks = preg_replace('#\{\$(' . self::REGEX_VAR . ')\}#', "<?php echo (isset(\$_tpldata['DEFINE']['.']['\\1'])) ? \$_tpldata['DEFINE']['.']['\\1'] : ''; ?>", $text_blocks); - - return $text_blocks; - } - - /** - * Handles special language tags L_ and LA_ - */ - private function compile_language_tags(&$text_blocks) - { - // transform vars prefixed by L_ into their language variable pendant if nothing is set within the tpldata array - if (strpos($text_blocks, '{L_') !== false) - { - $text_blocks = preg_replace('#\{L_(' . self::REGEX_VAR . ')\}#', "<?php echo ((isset(\$_rootref['L_\\1'])) ? \$_rootref['L_\\1'] : ((isset(\$_lang['\\1'])) ? \$_lang['\\1'] : '{ \\1 }')); ?>", $text_blocks); - } - - // Handle addslashed language variables prefixed with LA_ - // If a template variable already exist, it will be used in favor of it... - if (strpos($text_blocks, '{LA_') !== false) - { - $text_blocks = preg_replace('#\{LA_(' . self::REGEX_VAR . '+)\}#', "<?php echo ((isset(\$_rootref['LA_\\1'])) ? \$_rootref['LA_\\1'] : ((isset(\$_rootref['L_\\1'])) ? addslashes(\$_rootref['L_\\1']) : ((isset(\$_lang['\\1'])) ? addslashes(\$_lang['\\1']) : '{ \\1 }'))); ?>", $text_blocks); - } - } - - /** - * Compile blocks - * @access private - */ - private function compile_tag_block($tag_args) - { - $no_nesting = false; - - // Is the designer wanting to call another loop in a loop? - // <!-- BEGIN loop --> - // <!-- BEGIN !loop2 --> - // <!-- END !loop2 --> - // <!-- END loop --> - // 'loop2' is actually on the same nesting level as 'loop' you assign - // variables to it with template->assign_block_vars('loop2', array(...)) - if (strpos($tag_args, '!') === 0) - { - // Count the number if ! occurrences (not allowed in vars) - $no_nesting = substr_count($tag_args, '!'); - $tag_args = substr($tag_args, $no_nesting); - } - - // Allow for control of looping (indexes start from zero): - // foo(2) : Will start the loop on the 3rd entry - // foo(-2) : Will start the loop two entries from the end - // foo(3,4) : Will start the loop on the fourth entry and end it on the fifth - // foo(3,-4) : Will start the loop on the fourth entry and end it four from last - $match = array(); - - if (preg_match('#^([^()]*)\(([\-\d]+)(?:,([\-\d]+))?\)$#', $tag_args, $match)) - { - $tag_args = $match[1]; - - if ($match[2] < 0) - { - $loop_start = '($_' . $tag_args . '_count ' . $match[2] . ' < 0 ? 0 : $_' . $tag_args . '_count ' . $match[2] . ')'; - } - else - { - $loop_start = '($_' . $tag_args . '_count < ' . $match[2] . ' ? $_' . $tag_args . '_count : ' . $match[2] . ')'; - } - - if (!isset($match[3]) || strlen($match[3]) < 1 || $match[3] == -1) - { - $loop_end = '$_' . $tag_args . '_count'; - } - else if ($match[3] >= 0) - { - $loop_end = '(' . ($match[3] + 1) . ' > $_' . $tag_args . '_count ? $_' . $tag_args . '_count : ' . ($match[3] + 1) . ')'; - } - else //if ($match[3] < -1) - { - $loop_end = '$_' . $tag_args . '_count' . ($match[3] + 1); - } - } - else - { - $loop_start = 0; - $loop_end = '$_' . $tag_args . '_count'; - } - - $tag_template_php = ''; - array_push($this->block_names, $tag_args); - - if ($no_nesting !== false) - { - // We need to implode $no_nesting times from the end... - $block = array_slice($this->block_names, -$no_nesting); - } - else - { - $block = $this->block_names; - } - - if (sizeof($block) < 2) - { - // Block is not nested. - $tag_template_php = '$_' . $tag_args . "_count = (isset(\$_tpldata['$tag_args'])) ? sizeof(\$_tpldata['$tag_args']) : 0;"; - $varref = "\$_tpldata['$tag_args']"; - } - else - { - // This block is nested. - // Generate a namespace string for this block. - $namespace = implode('.', $block); - - // Get a reference to the data array for this block that depends on the - // current indices of all parent blocks. - $varref = $this->generate_block_data_ref($namespace, false); - - // Create the for loop code to iterate over this block. - $tag_template_php = '$_' . $tag_args . '_count = (isset(' . $varref . ')) ? sizeof(' . $varref . ') : 0;'; - } - - $tag_template_php .= 'if ($_' . $tag_args . '_count) {'; - - /** - * The following uses foreach for iteration instead of a for loop, foreach is faster but requires PHP to make a copy of the contents of the array which uses more memory - * <code> - * if (!$offset) - * { - * $tag_template_php .= 'foreach (' . $varref . ' as $_' . $tag_args . '_i => $_' . $tag_args . '_val){'; - * } - * </code> - */ - - $tag_template_php .= 'for ($_' . $tag_args . '_i = ' . $loop_start . '; $_' . $tag_args . '_i < ' . $loop_end . '; ++$_' . $tag_args . '_i){'; - $tag_template_php .= '$_' . $tag_args . '_val = &' . $varref . '[$_' . $tag_args . '_i];'; - - return $tag_template_php; - } - - /** - * Compile a general expression - much of this is from Smarty with - * some adaptions for our block level methods - * @access private - */ - private function compile_expression($tag_args, &$vars = array()) - { - $match = array(); - preg_match_all('/(?: - "[^"\\\\]*(?:\\\\.[^"\\\\]*)*" | - \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\' | - [(),] | - [^\s(),]+)/x', $tag_args, $match); - - $tokens = $match[0]; - $is_arg_stack = array(); - - for ($i = 0, $size = sizeof($tokens); $i < $size; $i++) - { - $token = &$tokens[$i]; - - switch ($token) - { - case '!==': - case '===': - case '<<': - case '>>': - case '|': - case '^': - case '&': - case '~': - case ')': - case ',': - case '+': - case '-': - case '*': - case '/': - case '@': - break; - - case '==': - case 'eq': - $token = '=='; - break; - - case '!=': - case '<>': - case 'ne': - case 'neq': - $token = '!='; - break; - - case '<': - case 'lt': - $token = '<'; - break; - - case '<=': - case 'le': - case 'lte': - $token = '<='; - break; - - case '>': - case 'gt': - $token = '>'; - break; - - case '>=': - case 'ge': - case 'gte': - $token = '>='; - break; - - case '&&': - case 'and': - $token = '&&'; - break; - - case '||': - case 'or': - $token = '||'; - break; - - case '!': - case 'not': - $token = '!'; - break; - - case '%': - case 'mod': - $token = '%'; - break; - - case '(': - array_push($is_arg_stack, $i); - break; - - case 'is': - $is_arg_start = ($tokens[$i-1] == ')') ? array_pop($is_arg_stack) : $i-1; - $is_arg = implode(' ', array_slice($tokens, $is_arg_start, $i - $is_arg_start)); - - $new_tokens = $this->_parse_is_expr($is_arg, array_slice($tokens, $i+1)); - - array_splice($tokens, $is_arg_start, sizeof($tokens), $new_tokens); - - $i = $is_arg_start; - - // no break - - default: - $varrefs = array(); - if (preg_match('#^((?:' . self::REGEX_NS . '\.)+)?(\$)?(?=[A-Z])([A-Z0-9\-_]+)#s', $token, $varrefs)) - { - if (!empty($varrefs[1])) - { - $namespace = substr($varrefs[1], 0, -1); - $namespace = (strpos($namespace, '.') === false) ? $namespace : strrchr($namespace, '.'); - - // S_ROW_COUNT is deceptive, it returns the current row number now the number of rows - // hence S_ROW_COUNT is deprecated in favour of S_ROW_NUM - switch ($varrefs[3]) - { - case 'S_ROW_NUM': - case 'S_ROW_COUNT': - $token = "\$_${namespace}_i"; - break; - - case 'S_NUM_ROWS': - $token = "\$_${namespace}_count"; - break; - - case 'S_FIRST_ROW': - $token = "(\$_${namespace}_i == 0)"; - break; - - case 'S_LAST_ROW': - $token = "(\$_${namespace}_i == \$_${namespace}_count - 1)"; - break; - - case 'S_BLOCK_NAME': - $token = "'$namespace'"; - break; - - default: - $token = $this->generate_block_data_ref(substr($varrefs[1], 0, -1), true, $varrefs[2]) . '[\'' . $varrefs[3] . '\']'; - $vars[$token] = true; - break; - } - } - else - { - $token = ($varrefs[2]) ? '$_tpldata[\'DEFINE\'][\'.\'][\'' . $varrefs[3] . '\']' : '$_rootref[\'' . $varrefs[3] . '\']'; - $vars[$token] = true; - } - - } - else if (preg_match('#^\.((?:' . self::REGEX_NS . '\.?)+)$#s', $token, $varrefs)) - { - // Allow checking if loops are set with .loopname - // It is also possible to check the loop count by doing <!-- IF .loopname > 1 --> for example - $blocks = explode('.', $varrefs[1]); - - // If the block is nested, we have a reference that we can grab. - // If the block is not nested, we just go and grab the block from _tpldata - if (sizeof($blocks) > 1) - { - $block = array_pop($blocks); - $namespace = implode('.', $blocks); - $varref = $this->generate_block_data_ref($namespace, true); - - // Add the block reference for the last child. - $varref .= "['" . $block . "']"; - } - else - { - $varref = '$_tpldata'; - - // Add the block reference for the last child. - $varref .= "['" . $blocks[0] . "']"; - } - $token = "isset($varref) && sizeof($varref)"; - } - - break; - } - } - - return $tokens; - } - - - private function compile_tag_if($tag_args, $elseif) - { - $vars = array(); - - $tokens = $this->compile_expression($tag_args, $vars); - - $tpl = ($elseif) ? '} else if (' : 'if ('; - - if (!empty($vars)) - { - $tpl .= '(isset(' . implode(') && isset(', array_keys($vars)) . ')) && '; - } - - $tpl .= implode(' ', $tokens); - $tpl .= ') { '; - - return $tpl; - } - - /** - * Compile DEFINE tags - * @access private - */ - private function compile_tag_define($tag_args, $op) - { - $match = array(); - preg_match('#^((?:' . self::REGEX_NS . '\.)+)?\$(?=[A-Z])([A-Z0-9_\-]*)(?: = (.*?))?$#', $tag_args, $match); - - if (empty($match[2]) || (!isset($match[3]) && $op)) - { - return ''; - } - - if (!$op) - { - return 'unset(' . (($match[1]) ? $this->generate_block_data_ref(substr($match[1], 0, -1), true, true) . '[\'' . $match[2] . '\']' : '$_tpldata[\'DEFINE\'][\'.\'][\'' . $match[2] . '\']') . ');'; - } - - $parsed_statement = implode(' ', $this->compile_expression($match[3])); - - return (($match[1]) ? $this->generate_block_data_ref(substr($match[1], 0, -1), true, true) . '[\'' . $match[2] . '\']' : '$_tpldata[\'DEFINE\'][\'.\'][\'' . $match[2] . '\']') . ' = ' . $parsed_statement . ';'; - } - - /** - * Compile INCLUDE tag - * @access private - */ - private function compile_tag_include($tag_args) - { - return "\$this->_tpl_include('$tag_args');"; - } - - /** - * Compile INCLUDE_PHP tag - * @access private - */ - private function compile_tag_include_php($tag_args) - { - return "include('$tag_args');"; - } - - /** - * parse expression - * This is from Smarty - * @access private - */ - private function _parse_is_expr($is_arg, $tokens) - { - $expr_end = 0; - $negate_expr = false; - - if (($first_token = array_shift($tokens)) == 'not') - { - $negate_expr = true; - $expr_type = array_shift($tokens); - } - else - { - $expr_type = $first_token; - } - - switch ($expr_type) - { - case 'even': - if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') - { - $expr_end++; - $expr_arg = $tokens[$expr_end++]; - $expr = "!(($is_arg / $expr_arg) & 1)"; - } - else - { - $expr = "!($is_arg & 1)"; - } - break; - - case 'odd': - if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') - { - $expr_end++; - $expr_arg = $tokens[$expr_end++]; - $expr = "(($is_arg / $expr_arg) & 1)"; - } - else - { - $expr = "($is_arg & 1)"; - } - break; - - case 'div': - if (isset($tokens[$expr_end]) && $tokens[$expr_end] == 'by') - { - $expr_end++; - $expr_arg = $tokens[$expr_end++]; - $expr = "!($is_arg % $expr_arg)"; - } - break; - } - - if ($negate_expr) - { - if ($expr[0] == '!') - { - // Negated expression, de-negate it. - $expr = substr($expr, 1); - } - else - { - $expr = "!($expr)"; - } - } - - array_splice($tokens, 0, $expr_end, $expr); - - return $tokens; - } - - /** - * Generates a reference to the given variable inside the given (possibly nested) - * block namespace. This is a string of the form: - * ' . $_tpldata['parent'][$_parent_i]['$child1'][$_child1_i]['$child2'][$_child2_i]...['varname'] . ' - * It's ready to be inserted into an "echo" line in one of the templates. - * - * @access private - * @param string $namespace Namespace to access (expects a trailing "." on the namespace) - * @param string $varname Variable name to use - * @param bool $echo If true return an echo statement, otherwise a reference to the internal variable - * @param bool $defop If true this is a variable created with the DEFINE construct, otherwise template variable - * @return string Code to access variable or echo it if $echo is true - */ - private function generate_block_varref($namespace, $varname, $echo = true, $defop = false) - { - // Strip the trailing period. - $namespace = substr($namespace, 0, -1); - - $expr = true; - $isset = false; - - // S_ROW_COUNT is deceptive, it returns the current row number now the number of rows - // hence S_ROW_COUNT is deprecated in favour of S_ROW_NUM - switch ($varname) - { - case 'S_ROW_NUM': - case 'S_ROW_COUNT': - $varref = "\$_${namespace}_i"; - break; - - case 'S_NUM_ROWS': - $varref = "\$_${namespace}_count"; - break; - - case 'S_FIRST_ROW': - $varref = "(\$_${namespace}_i == 0)"; - break; - - case 'S_LAST_ROW': - $varref = "(\$_${namespace}_i == \$_${namespace}_count - 1)"; - break; - - case 'S_BLOCK_NAME': - $varref = "'$namespace'"; - break; - - default: - // Get a reference to the data block for this namespace. - $varref = $this->generate_block_data_ref($namespace, true, $defop); - // Prepend the necessary code to stick this in an echo line. - - // Append the variable reference. - $varref .= "['$varname']"; - - $expr = false; - $isset = true; - break; - } - // @todo Test the !$expr more - $varref = ($echo) ? '<?php echo ' . ($isset ? "isset($varref) ? $varref : ''" : $varref) . '; ?>' : (($expr || isset($varref)) ? $varref : ''); - - return $varref; - } - - /** - * Generates a reference to the array of data values for the given - * (possibly nested) block namespace. This is a string of the form: - * $_tpldata['parent'][$_parent_i]['$child1'][$_child1_i]['$child2'][$_child2_i]...['$childN'] - * - * @access private - * @param string $blockname Block to access (does not expect a trailing "." on the blockname) - * @param bool $include_last_iterator If $include_last_iterator is true, then [$_childN_i] will be appended to the form shown above. - * @param bool $defop If true this is a variable created with the DEFINE construct, otherwise template variable - * @return string Code to access variable - */ - private function generate_block_data_ref($blockname, $include_last_iterator, $defop = false) - { - // Get an array of the blocks involved. - $blocks = explode('.', $blockname); - $blockcount = sizeof($blocks) - 1; - - // DEFINE is not an element of any referenced variable, we must use _tpldata to access it - if ($defop) - { - $varref = '$_tpldata[\'DEFINE\']'; - // Build up the string with everything but the last child. - for ($i = 0; $i < $blockcount; $i++) - { - $varref .= "['" . $blocks[$i] . "'][\$_" . $blocks[$i] . '_i]'; - } - // Add the block reference for the last child. - $varref .= "['" . $blocks[$blockcount] . "']"; - // Add the iterator for the last child if requried. - if ($include_last_iterator) - { - $varref .= '[$_' . $blocks[$blockcount] . '_i]'; - } - return $varref; - } - else if ($include_last_iterator) - { - return '$_'. $blocks[$blockcount] . '_val'; - } - else - { - return '$_'. $blocks[$blockcount - 1] . '_val[\''. $blocks[$blockcount]. '\']'; - } - } -} - -stream_filter_register('phpbb_template', 'phpbb_template_filter'); - -/** -* Extension of template class - Functions needed for compiling templates only. -* -* psoTFX, phpBB Development Team - Completion of file caching, decompilation -* routines and implementation of conditionals/keywords and associated changes -* -* The interface was inspired by PHPLib templates, and the template file (formats are -* quite similar) -* -* The keyword/conditional implementation is currently based on sections of code from -* the Smarty templating engine (c) 2001 ispi of Lincoln, Inc. which is released -* (on its own and in whole) under the LGPL. Section 3 of the LGPL states that any code -* derived from an LGPL application may be relicenced under the GPL, this applies -* to this source -* -* DEFINE directive inspired by a request by Cyberalien -* -* @package phpBB3 -* @uses template_filter As a PHP stream filter to perform compilation of templates -*/ -class phpbb_template_compile -{ - /** - * @var phpbb_template Reference to the {@link phpbb_template template} object performing compilation - */ - private $template; - - /** - * Constructor - * @param phpbb_template $template {@link phpbb_template Template} object performing compilation - */ - public function __construct(phpbb_template $template) - { - $this->template = $template; - } - - /** - * Load template source from file - * @access public - * @param string $handle Template handle we wish to load - * @return bool Return true on success otherwise false - */ - public function _tpl_load_file($handle) - { - // Try and open template for read - if (!file_exists($this->template->files[$handle])) - { - trigger_error("template->_tpl_load_file(): File {$this->template->files[$handle]} does not exist or is empty", E_USER_ERROR); - } - - // Actually compile the code now. - return $this->compile_write($handle, $this->template->files[$handle]); - } - - /** - * Load template source from file - * @access public - * @param string $handle Template handle we wish to compile - * @return string|bool Return compiled code on successful compilation otherwise false - */ - public function _tpl_gen_src($handle) - { - // Try and open template for read - if (!file_exists($this->template->files[$handle])) - { - trigger_error("template->_tpl_load_file(): File {$this->template->files[$handle]} does not exist or is empty", E_USER_ERROR); - } - - // Actually compile the code now. - return $this->compile_gen($this->template->files[$handle]); - } - - /** - * Write compiled file to cache directory - * @access private - * @param string $handle Template handle to compile - * @param string $source_file Source template file - * @return bool Return true on success otherwise false - */ - private function compile_write($handle, $source_file) - { - $filename = $this->template->cachepath . str_replace('/', '.', $this->template->filename[$handle]) . '.' . PHP_EXT; - - $source_handle = @fopen($source_file, 'rb'); - $destination_handle = @fopen($filename, 'wb'); - - if (!$source_handle || !$destination_handle) - { - return false; - } - - @flock($destination_handle, LOCK_EX); - - stream_filter_append($source_handle, 'phpbb_template'); - stream_copy_to_stream($source_handle, $destination_handle); - - @fclose($source_handle); - @flock($destination_handle, LOCK_UN); - @fclose($destination_handle); - - phpbb::$system->chmod($filename, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); - - clearstatcache(); - - return true; - } - - /** - * Generate source for eval() - * @access private - * @param string $source_file Source template file - * @return string|bool Return compiled code on successful compilation otherwise false - */ - private function compile_gen($source_file) - { - $source_handle = @fopen($source_file, 'rb'); - $destination_handle = @fopen('php://temp' ,'r+b'); - - if (!$source_handle || !$destination_handle) - { - return false; - } - - stream_filter_append($source_handle, 'phpbb_template'); - stream_copy_to_stream($source_handle, $destination_handle); - - @fclose($source_handle); - - rewind($destination_handle); - return stream_get_contents($destination_handle); - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/classes/user.php b/phpBB/includes/classes/user.php deleted file mode 100644 index 83e8fce4eb..0000000000 --- a/phpBB/includes/classes/user.php +++ /dev/null @@ -1,1124 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005, 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Base user class -* -* This is the overarching class which contains (through session extend) -* all methods utilised for user functionality during a session. -* -* @package phpBB3 -*/ -class phpbb_user extends phpbb_session -{ - /** - * @var array required phpBB objects - */ - public $phpbb_required = array('config', 'acl', 'db', 'template', 'security', 'server-vars', 'acm', 'api:user'); - - /** - * @var array Optional phpBB objects - */ - public $phpbb_optional = array(); - - /** - * @var array language entries - */ - public $lang = array(); - - /** - * @var array help entries - */ - public $help = array(); - - /** - * @var array theme entries - */ - public $theme = array(); - - /** - * @var string users date format - */ - public $date_format; - - /** - * @var double users time zone - */ - public $timezone; - - /** - * @var int users summer time setting. 0 if not in DST, else DST offset. - */ - public $dst; - - /** - * @var string language name, for example 'en' - */ - public $lang_name = false; - - /** - * @var int the language id for the specified language name - */ - public $lang_id = false; - - /** - * @var string the language path phpBB can find installed languages - */ - public $lang_path; - - /** - * @var string Imageset language name. If no fallback happens it is the same as {@link lang_name lang_name}. - */ - public $img_lang; - - /** - * @var array Holds information about the imageset to build {@link img() images}. - */ - public $img_array = array(); - - /** - * @var bool Is true if the user is a logged in registered user - */ - public $is_registered = false; - - /** - * @var bool Is true if the user is logged in and a search engine/bot - */ - public $is_bot = false; - - /** - * @var bool Is true if user is founder - */ - public $is_founder = false; - - /** - * @var bool Is true if user is anonymous/guest - */ - public $is_guest = true; - - /** - * Ablility to add new option (id 7). Enabled user options is stored in $data['user_options']. - * @var array user options defining their possibilities to view flash, images, etc. User options only supports set/unset (true/false) - */ - public $keyoptions = array('viewimg' => 0, 'viewflash' => 1, 'viewsmilies' => 2, 'viewsigs' => 3, 'viewavatars' => 4, 'viewcensors' => 5, 'attachsig' => 6, 'bbcode' => 8, 'smilies' => 9, 'popuppm' => 10); - - /** - * @var array The respective true/false values for the {@link keyoptions keyoptions}. - */ - public $keyvalues = array(); - - /** - * Constructor to set the lang path. Calls parrent::__construct() - * - * @param string $auth_method The authentication method to use, for example 'db' - * @param string $lang_path Language pack path - * @access public - */ - public function __construct($auth_method, $lang_path) - { - parent::__construct(); - - // Init auth object - $method = basename(trim($auth_method)); - $class = 'phpbb_auth_' . $method; - - if (class_exists($class)) - { - $this->auth = new $class(); - } - - // Set language path - $this->lang_path = $lang_path; - - // Make sure last character is a directory separator - if (substr($this->lang_path, -1) != '/') - { - $this->lang_path .= '/'; - } - } - - /** - * Determine and set language - */ - public function set_language($lang_name = '') - { - // Try to determine language from browser - if (!$lang_name && !empty($_SERVER['HTTP_ACCEPT_LANGUAGE'])) - { - $accept_lang_ary = explode(',', strtolower($_SERVER['HTTP_ACCEPT_LANGUAGE'])); - - foreach ($accept_lang_ary as $accept_lang) - { - // Set correct format ... guess full xx_yy form - $accept_lang = substr($accept_lang, 0, 2) . '_' . substr($accept_lang, 3, 2); - - if (file_exists($this->lang_path . basename($accept_lang))) - { - $lang_name = $accept_lang; - break; - } - else - { - // No match on xx_yy so try xx - $accept_lang = substr($accept_lang, 0, 2); - if (file_exists($this->lang_path . basename($accept_lang))) - { - $lang_name = $accept_lang; - break; - } - } - } - } - - // Still no luck? - $lang_name = (!$lang_name && isset(phpbb::$config['default_lang'])) ? phpbb::$config['default_lang'] : basename($lang_name); - - // No appropriate language found ... so let's use the first one in the language - // dir, this may or may not be English - if (!$lang_name) - { - $dir = @opendir($this->lang_path); - - if (!$dir) - { - trigger_error('Unable to access the language directory', E_USER_ERROR); - } - - while (($file = readdir($dir)) !== false) - { - $path = $this->lang_path . $file; - - if (!is_file($path) && !is_link($path) && file_exists($path . '/iso.txt')) - { - $lang_name = $file; - break; - } - } - closedir($dir); - } - - // Update language name if changed - if ($this->lang_name !== $lang_name) - { - $this->lang_name = $lang_name; - } - - // Set data language in case we have a user where this is not set - if (empty($this->data['user_lang'])) - { - $this->data['user_lang'] = $this->lang_name; - } - - // We include common language file here to not load it every time a custom language file is included - $lang = &$this->lang; - - if ((include $this->lang_path . $this->lang_name . "/common." . PHP_EXT) === false) - { - die('Language file ' . $this->lang_path . $this->lang_name . "/common." . PHP_EXT . " couldn't be opened."); - } - } - - /** - * Setup basic user-specific items (style, language, ...) - * - * @param string|array $lang_set Language set to setup. - * Can be a string or an array of language files without a path and extension. - * Format must match {@link add_lang() add_lang}. - * @param int $style If not set to false this specifies the style id to use. - * The page will then use the specified style id instead of the default one. - * @access public - */ - public function setup($lang_set = false, $style = false) - { - // Check if there is a valid session - if (empty($this->data)) - { - $this->session_begin(); - - if (phpbb::registered('acl')) - { - phpbb::$acl->init($this->data); - } - } - - if ($this->data['user_id'] != ANONYMOUS) - { - $this->lang_name = (file_exists($this->lang_path . $this->data['user_lang'] . "/common." . PHP_EXT)) ? $this->data['user_lang'] : basename(phpbb::$config['default_lang']); - $this->date_format = $this->data['user_dateformat']; - $this->timezone = $this->data['user_timezone'] * 3600; - $this->dst = $this->data['user_dst'] * 3600; - } - else - { - $this->lang_name = basename(phpbb::$config['default_lang']); - $this->date_format = phpbb::$config['default_dateformat']; - $this->timezone = phpbb::$config['board_timezone'] * 3600; - $this->dst = phpbb::$config['board_dst'] * 3600; - } - - $this->set_language($this->lang_name); - - $this->add_lang($lang_set); - unset($lang_set); - - if (phpbb_request::variable('style', false, false, phpbb_request::GET) && phpbb::$acl->acl_get('a_styles')) - { - $style = request_var('style', 0); - $this->extra_url = array('style=' . $style); - } - else - { - // Set up style - $style = ($style) ? $style : ((!phpbb::$config['override_user_style']) ? $this->data['user_style'] : phpbb::$config['default_style']); - } - - $sql = 'SELECT s.style_id, t.template_path, t.template_id, t.bbcode_bitfield, c.theme_path, c.theme_name, c.theme_storedb, c.theme_id, i.imageset_path, i.imageset_id, i.imageset_name - FROM ' . STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c, ' . STYLES_IMAGESET_TABLE . " i - WHERE s.style_id = $style - AND t.template_id = s.template_id - AND c.theme_id = s.theme_id - AND i.imageset_id = s.imageset_id"; - $result = phpbb::$db->sql_query($sql, 3600); - $this->theme = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - // User has wrong style - if (!$this->theme && $style == $this->data['user_style']) - { - $style = $this->data['user_style'] = phpbb::$config['default_style']; - - $sql = 'UPDATE ' . USERS_TABLE . " - SET user_style = $style - WHERE user_id = {$this->data['user_id']}"; - phpbb::$db->sql_query($sql); - - $sql = 'SELECT s.style_id, t.template_path, t.template_id, t.bbcode_bitfield, c.theme_path, c.theme_name, c.theme_storedb, c.theme_id, i.imageset_path, i.imageset_id, i.imageset_name - FROM ' . STYLES_TABLE . ' s, ' . STYLES_TEMPLATE_TABLE . ' t, ' . STYLES_THEME_TABLE . ' c, ' . STYLES_IMAGESET_TABLE . " i - WHERE s.style_id = $style - AND t.template_id = s.template_id - AND c.theme_id = s.theme_id - AND i.imageset_id = s.imageset_id"; - $result = phpbb::$db->sql_query($sql, 3600); - $this->theme = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - } - - if (!$this->theme) - { - trigger_error('Could not get style data', E_USER_ERROR); - } - - // Now parse the cfg file and cache it, - // we are only interested in the theme configuration for now - $parsed_items = phpbb_cache::obtain_cfg_item($this->theme, 'theme'); - - $check_for = array( - 'parse_css_file' => (int) 0, - 'pagination_sep' => (string) ', ', - ); - - foreach ($check_for as $key => $default_value) - { - $this->theme[$key] = (isset($parsed_items[$key])) ? $parsed_items[$key] : $default_value; - settype($this->theme[$key], gettype($default_value)); - - if (is_string($default_value)) - { - $this->theme[$key] = htmlspecialchars($this->theme[$key]); - } - } - - // If the style author specified the theme needs to be cached - // (because of the used paths and variables) than make sure it is the case. - // For example, if the theme uses language-specific images it needs to be stored in db. - if (!$this->theme['theme_storedb'] && $this->theme['parse_css_file']) - { - $this->theme['theme_storedb'] = 1; - - $stylesheet = file_get_contents(PHPBB_ROOT_PATH . "styles/{$this->theme['theme_path']}/theme/stylesheet.css"); - // Match CSS imports - $matches = array(); - preg_match_all('/@import url\(["\'](.*)["\']\);/i', $stylesheet, $matches); - - if (sizeof($matches)) - { - $content = ''; - foreach ($matches[0] as $idx => $match) - { - if ($content = @file_get_contents(PHPBB_ROOT_PATH . "styles/{$this->theme['theme_path']}/theme/" . $matches[1][$idx])) - { - $content = trim($content); - } - else - { - $content = ''; - } - $stylesheet = str_replace($match, $content, $stylesheet); - } - unset($content); - } - - $stylesheet = str_replace('./', 'styles/' . $this->theme['theme_path'] . '/theme/', $stylesheet); - - $sql_ary = array( - 'theme_data' => $stylesheet, - 'theme_mtime' => time(), - 'theme_storedb' => 1 - ); - - phpbb::$db->sql_query('UPDATE ' . STYLES_THEME_TABLE . ' SET ' . phpbb::$db->sql_build_array('UPDATE', $sql_ary) . ' WHERE theme_id = ' . $this->theme['theme_id']); - unset($sql_ary); - } - - phpbb::$template->set_template(); - - $this->img_lang = (file_exists(PHPBB_ROOT_PATH . 'styles/' . $this->theme['imageset_path'] . '/imageset/' . $this->lang_name)) ? $this->lang_name : phpbb::$config['default_lang']; - - $sql = 'SELECT image_name, image_filename, image_lang, image_height, image_width - FROM ' . STYLES_IMAGESET_DATA_TABLE . ' - WHERE imageset_id = ' . $this->theme['imageset_id'] . " - AND image_filename <> '' - AND image_lang IN ('" . phpbb::$db->sql_escape($this->img_lang) . "', '')"; - $result = phpbb::$db->sql_query($sql, 3600); - - $localised_images = false; - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($row['image_lang']) - { - $localised_images = true; - } - - $row['image_filename'] = rawurlencode($row['image_filename']); - $this->img_array[$row['image_name']] = $row; - } - phpbb::$db->sql_freeresult($result); - - // there were no localised images, try to refresh the localised imageset for the user's language - if (!$localised_images) - { - // Attention: this code ignores the image definition list from acp_styles and just takes everything - // that the config file contains - $sql_ary = array(); - - phpbb::$db->sql_transaction('begin'); - - $sql = 'DELETE FROM ' . STYLES_IMAGESET_DATA_TABLE . ' - WHERE imageset_id = ' . $this->theme['imageset_id'] . ' - AND image_lang = \'' . phpbb::$db->sql_escape($this->img_lang) . '\''; - $result = phpbb::$db->sql_query($sql); - - if (@file_exists(PHPBB_ROOT_PATH . "styles/{$this->theme['imageset_path']}/imageset/{$this->img_lang}/imageset.cfg")) - { - $cfg_data_imageset_data = parse_cfg_file(PHPBB_ROOT_PATH . "styles/{$this->theme['imageset_path']}/imageset/{$this->img_lang}/imageset.cfg"); - foreach ($cfg_data_imageset_data as $image_name => $value) - { - if (strpos($value, '*') !== false) - { - if (substr($value, -1, 1) === '*') - { - list($image_filename, $image_height) = explode('*', $value); - $image_width = 0; - } - else - { - list($image_filename, $image_height, $image_width) = explode('*', $value); - } - } - else - { - $image_filename = $value; - $image_height = $image_width = 0; - } - - if (strpos($image_name, 'img_') === 0 && $image_filename) - { - $image_name = substr($image_name, 4); - $sql_ary[] = array( - 'image_name' => (string) $image_name, - 'image_filename' => (string) $image_filename, - 'image_height' => (int) $image_height, - 'image_width' => (int) $image_width, - 'imageset_id' => (int) $this->theme['imageset_id'], - 'image_lang' => (string) $this->img_lang, - ); - } - } - } - - if (sizeof($sql_ary)) - { - phpbb::$db->sql_multi_insert(STYLES_IMAGESET_DATA_TABLE, $sql_ary); - phpbb::$db->sql_transaction('commit'); - phpbb::$acm->destroy_sql(STYLES_IMAGESET_DATA_TABLE); - - add_log('admin', 'LOG_IMAGESET_LANG_REFRESHED', $this->theme['imageset_name'], $this->img_lang); - } - else - { - phpbb::$db->sql_transaction('commit'); - add_log('admin', 'LOG_IMAGESET_LANG_MISSING', $this->theme['imageset_name'], $this->img_lang); - } - } - - // Call phpbb_user_session_handler() in case external application want to "bend" some variables or replace classes... - // After calling it we continue script execution... - // phpbb_user_session_handler(); - - // If this function got called from the error handler we are finished here. - if (defined('IN_ERROR_HANDLER')) - { - return; - } - - // Disable board if the install/ directory is still present - // For the brave development army we do not care about this, else we need to comment out this everytime we develop locally - if (!phpbb::$base_config['debug_extra'] && !defined('ADMIN_START') && !defined('IN_INSTALL') && !defined('IN_LOGIN') && file_exists(PHPBB_ROOT_PATH . 'install')) - { - // Adjust the message slightly according to the permissions - if (phpbb::$acl->acl_gets('a_', 'm_') || phpbb::$acl->acl_getf_global('m_')) - { - $message = 'REMOVE_INSTALL'; - } - else - { - $message = (!empty(phpbb::$config['board_disable_msg'])) ? phpbb::$config['board_disable_msg'] : 'BOARD_DISABLE'; - } - trigger_error($message); - } - - // Is board disabled and user not an admin or moderator? - if (phpbb::$config['board_disable'] && !defined('IN_LOGIN') && !phpbb::$acl->acl_gets('a_', 'm_') && !phpbb::$acl->acl_getf_global('m_')) - { - header('HTTP/1.1 503 Service Unavailable'); - - $message = (!empty(phpbb::$config['board_disable_msg'])) ? phpbb::$config['board_disable_msg'] : 'BOARD_DISABLE'; - trigger_error($message); - } - - // Is load exceeded? - if (phpbb::$config['limit_load'] && $this->load !== false) - { - if ($this->load > floatval(phpbb::$config['limit_load']) && !defined('IN_LOGIN')) - { - // Set board disabled to true to let the admins/mods get the proper notification - phpbb::$config['board_disable'] = '1'; - - if (!phpbb::$acl->acl_gets('a_', 'm_') && !phpbb::$acl->acl_getf_global('m_')) - { - header('HTTP/1.1 503 Service Unavailable'); - trigger_error('BOARD_UNAVAILABLE'); - } - } - } - - if (isset($this->data['session_viewonline'])) - { - // Make sure the user is able to hide his session - if (!$this->data['session_viewonline']) - { - // Reset online status if not allowed to hide the session... - if (!phpbb::$acl->acl_get('u_hideonline')) - { - $sql = 'UPDATE ' . SESSIONS_TABLE . ' - SET session_viewonline = 1 - WHERE session_user_id = ' . $this->data['user_id']; - phpbb::$db->sql_query($sql); - $this->data['session_viewonline'] = 1; - } - } - else if (!$this->data['user_allow_viewonline']) - { - // the user wants to hide and is allowed to -> cloaking device on. - if (phpbb::$acl->acl_get('u_hideonline')) - { - $sql = 'UPDATE ' . SESSIONS_TABLE . ' - SET session_viewonline = 0 - WHERE session_user_id = ' . $this->data['user_id']; - phpbb::$db->sql_query($sql); - $this->data['session_viewonline'] = 0; - } - } - } - - - // Does the user need to change their password? If so, redirect to the - // ucp profile reg_details page ... of course do not redirect if we're already in the ucp - if (!defined('IN_ADMIN') && !defined('ADMIN_START') && phpbb::$config['chg_passforce'] && $this->is_registered && phpbb::$acl->acl_get('u_chgpasswd') && $this->data['user_passchg'] < time() - (phpbb::$config['chg_passforce'] * 86400)) - { - if (strpos($this->page['query_string'], 'mode=reg_details') === false && $this->page['page_name'] != 'ucp.' . PHP_EXT) - { - redirect(append_sid('ucp', 'i=profile&mode=reg_details')); - } - } - - return; - } - - /** - * More advanced language substitution - * - * Function to mimic sprintf() with the possibility of using phpBB's language system to substitute nullar/singular/plural forms. - * Params are the language key and the parameters to be substituted. - * This function/functionality was inspired by SHS` and Ashe. - * - * For example: - * <code> - * phpbb::$user->lang('NUM_POSTS_IN_QUEUE', 1); - * </code> - * - * @param string $key The language key to use - * @param mixed $parameter,... An unlimited number of parameter to apply. - * - * @return string Substituted language string - * @see sprintf() - * @access public - */ - public function lang() - { - $args = func_get_args(); - $key = $args[0]; - - if (is_array($key)) - { - $lang = &$this->lang[array_shift($key)]; - - foreach ($key as $_key) - { - $lang = &$lang[$_key]; - } - } - else - { - $lang = &$this->lang[$key]; - } - - // Return if language string does not exist - if (!isset($lang) || (!is_string($lang) && !is_array($lang))) - { - return $key; - } - - // If the language entry is a string, we simply mimic sprintf() behaviour - if (is_string($lang)) - { - if (sizeof($args) == 1) - { - return $lang; - } - - // Replace key with language entry and simply pass along... - $args[0] = $lang; - return call_user_func_array('sprintf', $args); - } - - // It is an array... now handle different nullar/singular/plural forms - $key_found = false; - - // We now get the first number passed and will select the key based upon this number - for ($i = 1, $num_args = sizeof($args); $i < $num_args; $i++) - { - if (is_int($args[$i])) - { - $numbers = array_keys($lang); - - foreach ($numbers as $num) - { - if ($num > $args[$i]) - { - break; - } - - $key_found = $num; - } - } - } - - // Ok, let's check if the key was found, else use the last entry (because it is mostly the plural form) - if ($key_found === false) - { - $numbers = array_keys($lang); - $key_found = end($numbers); - } - - // Use the language string we determined and pass it to sprintf() - $args[0] = $lang[$key_found]; - return call_user_func_array('sprintf', $args); - } - - /** - * Add Language Items - use_db and use_help are assigned where needed (only use them to force inclusion) - * - * Examples: - * <code> - * $lang_set = array('posting', 'help' => 'faq'); - * $lang_set = array('posting', 'viewtopic', 'help' => array('bbcode', 'faq')) - * $lang_set = array(array('posting', 'viewtopic'), 'help' => array('bbcode', 'faq')) - * $lang_set = 'posting' - * $lang_set = array('help' => 'faq', 'db' => array('help:faq', 'posting')) - * </code> - * - * @param mixed $lang_set specifies the language entries to include - * @param bool $use_db internal variable for recursion, do not use - * @param bool $use_help internal variable for recursion, do not use - * @access public - */ - public function add_lang($lang_set, $use_db = false, $use_help = false) - { - if (is_array($lang_set)) - { - foreach ($lang_set as $key => $lang_file) - { - // Please do not delete this line. - // We have to force the type here, else [array] language inclusion will not work - $key = (string) $key; - - if ($key == 'db') - { - $this->add_lang($lang_file, true, $use_help); - } - else if ($key == 'help') - { - $this->add_lang($lang_file, $use_db, true); - } - else if (!is_array($lang_file)) - { - $this->set_lang($this->lang, $this->help, $lang_file, $use_db, $use_help); - } - else - { - $this->add_lang($lang_file, $use_db, $use_help); - } - } - unset($lang_set); - } - else if ($lang_set) - { - $this->set_lang($this->lang, $this->help, $lang_set, $use_db, $use_help); - } - } - - /** - * Set language entry (called by {@link add_lang() add_lang}) - * - * @param array &$lang A reference to the language array phpbb::$user->lang - * @param array &$help A reference to the language help array phpbb::$user->help - * @param string $lang_file Language filename - * @param bool $use_db True if the database is used for obtaining the information - * @param bool $use_help True if we fetch help entries instead of language entries - * @access private - */ - private function set_lang(&$lang, &$help, $lang_file, $use_db = false, $use_help = false) - { - // Make sure the language name is set (if the user setup did not happen it is not set) - if (!$this->lang_name) - { - $this->lang_name = basename(phpbb::$config['default_lang']); - } - - // $lang == $this->lang - // $help == $this->help - // - add appropriate variables here, name them as they are used within the language file... - if (!$use_db) - { - if ($use_help && strpos($lang_file, '/') !== false) - { - $language_filename = $this->lang_path . $this->lang_name . '/' . substr($lang_file, 0, stripos($lang_file, '/') + 1) . 'help_' . substr($lang_file, stripos($lang_file, '/') + 1) . '.' . PHP_EXT; - } - else - { - $language_filename = $this->lang_path . $this->lang_name . '/' . (($use_help) ? 'help_' : '') . $lang_file . '.' . PHP_EXT; - } - - if (!file_exists($language_filename)) - { - if ($this->lang_name == 'en') - { - // The user's selected language is missing the file, the board default's language is missing the file, and the file doesn't exist in /en. - $language_filename = str_replace($this->lang_path . 'en', $this->lang_path . $this->data['user_lang'], $language_filename); - trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR); - } - else if ($this->lang_name == basename(phpbb::$config['default_lang'])) - { - // Fall back to the English Language - $this->lang_name = 'en'; - $this->set_lang($lang, $help, $lang_file, $use_db, $use_help); - } - else if (file_exists($this->lang_path . $this->data['user_lang'] . '/common.' . PHP_EXT)) - { - // Fall back to the board default language - $this->lang_name = basename(phpbb::$config['default_lang']); - $this->set_lang($lang, $help, $lang_file, $use_db, $use_help); - } - - // Reset the lang name - $this->lang_name = (file_exists($this->lang_path . $this->data['user_lang'] . '/common.' . PHP_EXT)) ? $this->data['user_lang'] : basename(phpbb::$config['default_lang']); - return; - } - - if ((include $language_filename) === false) - { - trigger_error('Language file ' . $language_filename . ' couldn\'t be opened.', E_USER_ERROR); - } - } - else if ($use_db) - { - // Get Database Language Strings - // Put them into $lang if nothing is prefixed, put them into $help if help: is prefixed - // For example: help:faq, posting - } - } - - /** - * Format user date - * - * @param int $gmepoch Unix timestamp to format - * @param string $format Date format in date() notation. - * The character | used to indicate relative dates, for example |d m Y|, h:i is translated to Today, h:i. - * @param bool $forcedate Force non-relative date format. - * - * @staticvar int $midnight Midnight time offset - * @staticvar array $date_cache Array to cache commonly needed structures within this function - * - * @return mixed translated date - * @access public - */ - public function format_date($gmepoch, $format = false, $forcedate = false) - { - static $midnight; - static $date_cache; - - $format = (!$format) ? $this->date_format : $format; - $now = time(); - $delta = $now - $gmepoch; - - if (!isset($date_cache[$format])) - { - // Is the user requesting a friendly date format (i.e. 'Today 12:42')? - $date_cache[$format] = array( - 'is_short' => strpos($format, '|'), - 'format_short' => substr($format, 0, strpos($format, '|')) . '||' . substr(strrchr($format, '|'), 1), - 'format_long' => str_replace('|', '', $format), - 'lang' => $this->lang['datetime'], - ); - - // Short representation of month in format? Some languages use different terms for the long and short format of May - if ((strpos($format, '\M') === false && strpos($format, 'M') !== false) || (strpos($format, '\r') === false && strpos($format, 'r') !== false)) - { - $date_cache[$format]['lang']['May'] = $this->lang['datetime']['May_short']; - } - } - - // Zone offset - $zone_offset = $this->timezone + $this->dst; - - // Show date <= 1 hour ago as 'xx min ago' - // A small tolerence is given for times in the future and times in the future but in the same minute are displayed as '< than a minute ago' - if ($delta <= 3600 && ($delta >= -5 || (($now / 60) % 60) == (($gmepoch / 60) % 60)) && $date_cache[$format]['is_short'] !== false && !$forcedate && isset($this->lang['datetime']['AGO'])) - { - return $this->lang(array('datetime', 'AGO'), max(0, (int) floor($delta / 60))); - } - - if (!$midnight) - { - list($d, $m, $y) = explode(' ', gmdate('j n Y', time() + $zone_offset)); - $midnight = gmmktime(0, 0, 0, $m, $d, $y) - $zone_offset; - } - - if ($date_cache[$format]['is_short'] !== false && !$forcedate && !($gmepoch < $midnight - 86400 || $gmepoch > $midnight + 172800)) - { - $day = false; - - if ($gmepoch > $midnight + 86400) - { - $day = 'TOMORROW'; - } - else if ($gmepoch > $midnight) - { - $day = 'TODAY'; - } - else if ($gmepoch > $midnight - 86400) - { - $day = 'YESTERDAY'; - } - - if ($day !== false) - { - return str_replace('||', $this->lang['datetime'][$day], strtr(@gmdate($date_cache[$format]['format_short'], $gmepoch + $zone_offset), $date_cache[$format]['lang'])); - } - } - - return strtr(@gmdate($date_cache[$format]['format_long'], $gmepoch + $zone_offset), $date_cache[$format]['lang']); - } - - /** - * Get language id currently used by the user - * - * @return int language id - * @access public - */ - public function get_iso_lang_id() - { - if (!empty($this->lang_id)) - { - return $this->lang_id; - } - - if (!$this->lang_name) - { - $this->lang_name = phpbb::$config['default_lang']; - } - - $sql = 'SELECT lang_id - FROM ' . LANG_TABLE . " - WHERE lang_iso = '" . phpbb::$db->sql_escape($this->lang_name) . "'"; - $result = phpbb::$db->sql_query($sql); - $this->lang_id = (int) phpbb::$db->sql_fetchfield('lang_id'); - phpbb::$db->sql_freeresult($result); - - return $this->lang_id; - } - - /** - * Get users profile fields - * - * @param int $user_id User id. If not specified the current users profile fields are grabbed. - * - * @return array Profile fields. If the current user then they are also stored as property $profile_fields. - * @access public - */ - public function get_profile_fields($user_id = false) - { - $user_id = ($user_id === false) ? $this->data['user_id'] : $user_id; - - if (isset($this->profile_fields) && $user_id === $this->data['user_id']) - { - return $this->profile_fields; - } - - $sql = 'SELECT * - FROM ' . PROFILE_FIELDS_DATA_TABLE . " - WHERE user_id = $user_id"; - $result = phpbb::$db->sql_query_limit($sql, 1); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ($user_id === $this->data['user_id']) - { - $this->profile_fields = (!$row) ? array() : $row; - } - - return $row; - } - - /** - * Specify/Get image from style imageset - * - * @param string $img The imageset image key name - * @param string $alt An optional alternative image attribute. - * If a corresponding language key exist it will be used: phpbb::$user->lang[$alt] - * @param string $type The preferred type to return. Allowed types are: full_tag, src, width, height - * @param int $width Set image width - * - * @return mixed returns the preferred type from $type - * @access public - */ - public function img($img, $alt = '', $type = 'full_tag', $width = false) - { - static $imgs; - - $img_data = &$imgs[$img]; - - if (empty($img_data)) - { - if (!isset($this->img_array[$img])) - { - // Do not fill the image to let designers decide what to do if the image is empty - $img_data = ''; - return $img_data; - } - - $img_data['src'] = PHPBB_ROOT_PATH . 'styles/' . rawurlencode($this->theme['imageset_path']) . '/imageset/' . ($this->img_array[$img]['image_lang'] ? $this->img_array[$img]['image_lang'] .'/' : '') . $this->img_array[$img]['image_filename']; - $img_data['width'] = $this->img_array[$img]['image_width']; - $img_data['height'] = $this->img_array[$img]['image_height']; - } - - $alt = (!empty($this->lang[$alt])) ? $this->lang[$alt] : $alt; - - switch ($type) - { - case 'src': - return $img_data['src']; - break; - - case 'width': - return ($width === false) ? $img_data['width'] : $width; - break; - - case 'height': - return $img_data['height']; - break; - - default: - $use_width = ($width === false) ? $img_data['width'] : $width; - - return '<img src="' . $img_data['src'] . '"' . (($use_width) ? ' width="' . $use_width . '"' : '') . (($img_data['height']) ? ' height="' . $img_data['height'] . '"' : '') . ' alt="' . $alt . '" title="' . $alt . '" />'; - break; - } - } - - /** - * Get option bit field from user options. - * - * @param string $key The option key from {@link $keyoptions keyoptions} - * @param int $data Optional user options bitfield. - * If not specified then {@link $data $data['user_options']} is used. - * - * @return bool Corresponding option value returned. Is the option enabled or disabled. - * @access public - */ - public function optionget($key, $data = false) - { - if ($data !== false) - { - return $data & 1 << $this->keyoptions[$key]; - } - - if (!isset($this->keyvalues[$key])) - { - $this->keyvalues[$key] = $this->data['user_options'] & 1 << $this->keyoptions[$key]; - } - - return $this->keyvalues[$key]; - } - - /** - * Set option bit field for user options. - * - * @param string $key The option key from {@link $keyoptions keyoptions} - * @param bool $value True to enable the option, false to disable it - * @param int $data Optional user options bitfield. - * If not specified then {@link $data $data['user_options']} is used. - * - * @return bool The new user options bitfield is returned if $data is specified. - * Else: false is returned if user options not changed, true if changed. - * @access public - */ - public function optionset($key, $value, $data = false) - { - $var = ($data) ? $data : $this->data['user_options']; - - if ($value && !($var & 1 << $this->keyoptions[$key])) - { - $var += 1 << $this->keyoptions[$key]; - } - else if (!$value && ($var & 1 << $this->keyoptions[$key])) - { - $var -= 1 << $this->keyoptions[$key]; - } - else - { - return ($data) ? $var : false; - } - - if (!$data) - { - $this->data['user_options'] = $this->keyvalues[$key] = $var; - return true; - } - - return $var; - } - - /** - * User login. Log the user in. - * - * @param string $username The specified user name - * @param string $password The specified password - * @param bool $autologin Enable/disable persistent login - * @param bool $viewonline If false then the user will be logged in as hidden - * @param bool $admin If true the user requests an admin login - * - * @return array Login result array. This array returns results to the login script to show errors, notices, confirmations. - * @access public - */ - public function login($username, $password, $autologin = false, $viewonline = 1, $admin = 0) - { - if ($this->auth === false || !method_exists($this->auth, 'login')) - { - trigger_error('Authentication method not found', E_USER_ERROR); - } - - $login = $this->auth->login($username, $password); - - // If the auth module wants us to create an empty profile do so and then treat the status as LOGIN_SUCCESS - if ($login['status'] == LOGIN_SUCCESS_CREATE_PROFILE) - { - phpbb::$api->user->add($login['user_row'], (isset($login['cp_data'])) ? $login['cp_data'] : false); - - $sql = 'SELECT user_id, username, user_password, user_passchg, user_email, user_type - FROM ' . USERS_TABLE . " - WHERE username_clean = '" . phpbb::$db->sql_escape(utf8_clean_string($username)) . "'"; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if (!$row) - { - return array( - 'status' => LOGIN_ERROR_EXTERNAL_AUTH, - 'error_msg' => 'AUTH_NO_PROFILE_CREATED', - 'user_row' => array('user_id' => ANONYMOUS), - ); - } - - $login = array( - 'status' => LOGIN_SUCCESS, - 'error_msg' => false, - 'user_row' => $row, - ); - } - - // If login succeeded, we will log the user in... else we pass the login array through... - if ($login['status'] == LOGIN_SUCCESS) - { - // We create a new session. The session creation makes sure the old session is killed if there was one. - $result = $this->session_create($login['user_row']['user_id'], $admin, $autologin, $viewonline); - - // Successful session creation - if ($result === true) - { - return array( - 'status' => LOGIN_SUCCESS, - 'error_msg' => false, - 'user_row' => $login['user_row'], - ); - } - - return array( - 'status' => LOGIN_BREAK, - 'error_msg' => $result, - 'user_row' => $login['user_row'], - ); - } - - return $login; - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/constants.php b/phpBB/includes/constants.php deleted file mode 100644 index 8fc06cb352..0000000000 --- a/phpBB/includes/constants.php +++ /dev/null @@ -1,240 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* valid external constants: -* PHPBB_MSG_HANDLER -* PHPBB_DB_NEW_LINK -* PHPBB_ROOT_PATH -* PHPBB_ADMIN_PATH -*/ - -// phpBB Version -define('PHPBB_VERSION', '3.1.0-dev1'); - -// QA-related -// define('PHPBB_QA', 1); - -// User related -define('ANONYMOUS', 1); - -define('USER_ACTIVATION_NONE', 0); -define('USER_ACTIVATION_SELF', 1); -define('USER_ACTIVATION_ADMIN', 2); -define('USER_ACTIVATION_DISABLE', 3); - -define('AVATAR_UPLOAD', 1); -define('AVATAR_REMOTE', 2); -define('AVATAR_GALLERY', 3); - -define('INACTIVE_REGISTER', 1); -define('INACTIVE_PROFILE', 2); -define('INACTIVE_MANUAL', 3); -define('INACTIVE_REMIND', 4); - -// Login error codes -define('LOGIN_CONTINUE', 1); -define('LOGIN_BREAK', 2); -define('LOGIN_SUCCESS', 3); -define('LOGIN_SUCCESS_CREATE_PROFILE', 20); -define('LOGIN_ERROR_USERNAME', 10); -define('LOGIN_ERROR_PASSWORD', 11); -define('LOGIN_ERROR_ACTIVE', 12); -define('LOGIN_ERROR_ATTEMPTS', 13); -define('LOGIN_ERROR_EXTERNAL_AUTH', 14); -define('LOGIN_ERROR_PASSWORD_CONVERT', 15); - -// Group settings -define('GROUP_OPEN', 0); -define('GROUP_CLOSED', 1); -define('GROUP_HIDDEN', 2); -define('GROUP_SPECIAL', 3); -define('GROUP_FREE', 4); - -// Forum/Topic states -define('FORUM_CAT', 0); -define('FORUM_POST', 1); -define('FORUM_LINK', 2); -define('ITEM_UNLOCKED', 0); -define('ITEM_LOCKED', 1); -define('ITEM_MOVED', 2); - -// Forum Flags -define('FORUM_FLAG_LINK_TRACK', 1); -define('FORUM_FLAG_PRUNE_POLL', 2); -define('FORUM_FLAG_PRUNE_ANNOUNCE', 4); -define('FORUM_FLAG_PRUNE_STICKY', 8); -define('FORUM_FLAG_ACTIVE_TOPICS', 16); -define('FORUM_FLAG_POST_REVIEW', 32); - -// Optional text flags -define('OPTION_FLAG_BBCODE', 1); -define('OPTION_FLAG_SMILIES', 2); -define('OPTION_FLAG_LINKS', 4); - -// Topic types -define('POST_NORMAL', 0); -define('POST_STICKY', 1); -define('POST_ANNOUNCE', 2); -define('POST_GLOBAL', 3); - -// Lastread types -define('TRACK_NORMAL', 0); -define('TRACK_POSTED', 1); - -// Notify methods -define('NOTIFY_EMAIL', 0); -define('NOTIFY_IM', 1); -define('NOTIFY_BOTH', 2); - -// Email Priority Settings -define('MAIL_LOW_PRIORITY', 4); -define('MAIL_NORMAL_PRIORITY', 3); -define('MAIL_HIGH_PRIORITY', 2); - -// Log types -define('LOG_ADMIN', 0); -define('LOG_MOD', 1); -define('LOG_CRITICAL', 2); -define('LOG_USERS', 3); - -// Private messaging - Do NOT change these values -define('PRIVMSGS_HOLD_BOX', -4); -define('PRIVMSGS_NO_BOX', -3); -define('PRIVMSGS_OUTBOX', -2); -define('PRIVMSGS_SENTBOX', -1); -define('PRIVMSGS_INBOX', 0); - -// Full Folder Actions -define('FULL_FOLDER_NONE', -3); -define('FULL_FOLDER_DELETE', -2); -define('FULL_FOLDER_HOLD', -1); - -// Download Modes - Attachments -define('INLINE_LINK', 1); -// This mode is only used internally to allow modders extending the attachment functionality -define('PHYSICAL_LINK', 2); - -// Confirm types -define('CONFIRM_REG', 1); -define('CONFIRM_LOGIN', 2); -define('CONFIRM_POST', 3); - -// Categories - Attachments -define('ATTACHMENT_CATEGORY_NONE', 0); -define('ATTACHMENT_CATEGORY_IMAGE', 1); // Inline Images -define('ATTACHMENT_CATEGORY_WM', 2); // Windows Media Files - Streaming -define('ATTACHMENT_CATEGORY_RM', 3); // Real Media Files - Streaming -define('ATTACHMENT_CATEGORY_THUMB', 4); // Not used within the database, only while displaying posts -define('ATTACHMENT_CATEGORY_FLASH', 5); // Flash/SWF files -define('ATTACHMENT_CATEGORY_QUICKTIME', 6); // Quicktime/Mov files - -// BBCode UID length -define('BBCODE_UID_LEN', 8); - -// Number of core BBCodes -define('NUM_CORE_BBCODES', 12); - -// Magic url types -define('MAGIC_URL_EMAIL', 1); -define('MAGIC_URL_FULL', 2); -define('MAGIC_URL_LOCAL', 3); -define('MAGIC_URL_WWW', 4); - -// Profile Field Types -define('FIELD_INT', 1); -define('FIELD_STRING', 2); -define('FIELD_TEXT', 3); -define('FIELD_BOOL', 4); -define('FIELD_DROPDOWN', 5); -define('FIELD_DATE', 6); - -// referer validation -define('REFERER_VALIDATE_NONE', 0); -define('REFERER_VALIDATE_HOST', 1); -define('REFERER_VALIDATE_PATH', 2); - -// Additional constants -define('VOTE_CONVERTED', 127); - -// Table names -define('ACL_GROUPS_TABLE', phpbb::$base_config['table_prefix'] . 'acl_groups'); -define('ACL_OPTIONS_TABLE', phpbb::$base_config['table_prefix'] . 'acl_options'); -define('ACL_ROLES_DATA_TABLE', phpbb::$base_config['table_prefix'] . 'acl_roles_data'); -define('ACL_ROLES_TABLE', phpbb::$base_config['table_prefix'] . 'acl_roles'); -define('ACL_USERS_TABLE', phpbb::$base_config['table_prefix'] . 'acl_users'); -define('ATTACHMENTS_TABLE', phpbb::$base_config['table_prefix'] . 'attachments'); -define('BANLIST_TABLE', phpbb::$base_config['table_prefix'] . 'banlist'); -define('BBCODES_TABLE', phpbb::$base_config['table_prefix'] . 'bbcodes'); -define('BOOKMARKS_TABLE', phpbb::$base_config['table_prefix'] . 'bookmarks'); -define('BOTS_TABLE', phpbb::$base_config['table_prefix'] . 'bots'); -define('CONFIG_TABLE', phpbb::$base_config['table_prefix'] . 'config'); -define('CONFIRM_TABLE', phpbb::$base_config['table_prefix'] . 'confirm'); -define('DISALLOW_TABLE', phpbb::$base_config['table_prefix'] . 'disallow'); -define('DRAFTS_TABLE', phpbb::$base_config['table_prefix'] . 'drafts'); -define('EXTENSIONS_TABLE', phpbb::$base_config['table_prefix'] . 'extensions'); -define('EXTENSION_GROUPS_TABLE', phpbb::$base_config['table_prefix'] . 'extension_groups'); -define('FORUMS_TABLE', phpbb::$base_config['table_prefix'] . 'forums'); -define('FORUMS_ACCESS_TABLE', phpbb::$base_config['table_prefix'] . 'forums_access'); -define('FORUMS_TRACK_TABLE', phpbb::$base_config['table_prefix'] . 'forums_track'); -define('FORUMS_WATCH_TABLE', phpbb::$base_config['table_prefix'] . 'forums_watch'); -define('GROUPS_TABLE', phpbb::$base_config['table_prefix'] . 'groups'); -define('ICONS_TABLE', phpbb::$base_config['table_prefix'] . 'icons'); -define('LANG_TABLE', phpbb::$base_config['table_prefix'] . 'lang'); -define('LOG_TABLE', phpbb::$base_config['table_prefix'] . 'log'); -define('MODERATOR_CACHE_TABLE', phpbb::$base_config['table_prefix'] . 'moderator_cache'); -define('MODULES_TABLE', phpbb::$base_config['table_prefix'] . 'modules'); -define('POLL_OPTIONS_TABLE', phpbb::$base_config['table_prefix'] . 'poll_options'); -define('POLL_VOTES_TABLE', phpbb::$base_config['table_prefix'] . 'poll_votes'); -define('POSTS_TABLE', phpbb::$base_config['table_prefix'] . 'posts'); -define('PRIVMSGS_TABLE', phpbb::$base_config['table_prefix'] . 'privmsgs'); -define('PRIVMSGS_FOLDER_TABLE', phpbb::$base_config['table_prefix'] . 'privmsgs_folder'); -define('PRIVMSGS_RULES_TABLE', phpbb::$base_config['table_prefix'] . 'privmsgs_rules'); -define('PRIVMSGS_TO_TABLE', phpbb::$base_config['table_prefix'] . 'privmsgs_to'); -define('PROFILE_FIELDS_TABLE', phpbb::$base_config['table_prefix'] . 'profile_fields'); -define('PROFILE_FIELDS_DATA_TABLE', phpbb::$base_config['table_prefix'] . 'profile_fields_data'); -define('PROFILE_FIELDS_LANG_TABLE', phpbb::$base_config['table_prefix'] . 'profile_fields_lang'); -define('PROFILE_LANG_TABLE', phpbb::$base_config['table_prefix'] . 'profile_lang'); -define('RANKS_TABLE', phpbb::$base_config['table_prefix'] . 'ranks'); -define('REPORTS_TABLE', phpbb::$base_config['table_prefix'] . 'reports'); -define('REPORTS_REASONS_TABLE', phpbb::$base_config['table_prefix'] . 'reports_reasons'); -define('SEARCH_RESULTS_TABLE', phpbb::$base_config['table_prefix'] . 'search_results'); -define('SEARCH_WORDLIST_TABLE', phpbb::$base_config['table_prefix'] . 'search_wordlist'); -define('SEARCH_WORDMATCH_TABLE', phpbb::$base_config['table_prefix'] . 'search_wordmatch'); -define('SESSIONS_TABLE', phpbb::$base_config['table_prefix'] . 'sessions'); -define('SESSIONS_KEYS_TABLE', phpbb::$base_config['table_prefix'] . 'sessions_keys'); -define('SITELIST_TABLE', phpbb::$base_config['table_prefix'] . 'sitelist'); -define('SMILIES_TABLE', phpbb::$base_config['table_prefix'] . 'smilies'); -define('STYLES_TABLE', phpbb::$base_config['table_prefix'] . 'styles'); -define('STYLES_TEMPLATE_TABLE', phpbb::$base_config['table_prefix'] . 'styles_template'); -define('STYLES_THEME_TABLE', phpbb::$base_config['table_prefix'] . 'styles_theme'); -define('STYLES_IMAGESET_TABLE', phpbb::$base_config['table_prefix'] . 'styles_imageset'); -define('STYLES_IMAGESET_DATA_TABLE',phpbb::$base_config['table_prefix'] . 'styles_imageset_data'); -define('TOPICS_TABLE', phpbb::$base_config['table_prefix'] . 'topics'); -define('TOPICS_POSTED_TABLE', phpbb::$base_config['table_prefix'] . 'topics_posted'); -define('TOPICS_TRACK_TABLE', phpbb::$base_config['table_prefix'] . 'topics_track'); -define('TOPICS_WATCH_TABLE', phpbb::$base_config['table_prefix'] . 'topics_watch'); -define('USER_GROUP_TABLE', phpbb::$base_config['table_prefix'] . 'user_group'); -define('USERS_TABLE', phpbb::$base_config['table_prefix'] . 'users'); -define('WARNINGS_TABLE', phpbb::$base_config['table_prefix'] . 'warnings'); -define('WORDS_TABLE', phpbb::$base_config['table_prefix'] . 'words'); -define('ZEBRA_TABLE', phpbb::$base_config['table_prefix'] . 'zebra'); - -// Additional tables - -?>
\ No newline at end of file diff --git a/phpBB/includes/core/bootstrap.php b/phpBB/includes/core/bootstrap.php deleted file mode 100644 index f44b48c7db..0000000000 --- a/phpBB/includes/core/bootstrap.php +++ /dev/null @@ -1,100 +0,0 @@ -<?php -/** -* -* @package core -* @version $Id$ -* @copyright (c) 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -* Within this file only the framework with all components but no phpBB-specific things will be loaded -*/ - -/** -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -$starttime = explode(' ', microtime()); -$starttime = $starttime[1] + $starttime[0]; - -// Report all errors, except notices -error_reporting(E_ALL | E_STRICT); // ^ E_NOTICE -date_default_timezone_set('UTC'); - -// Initialize some standard variables, constants and classes we need -require_once PHPBB_ROOT_PATH . 'includes/core/core.' . PHP_EXT; -require_once PHPBB_ROOT_PATH . 'plugins/bootstrap.' . PHP_EXT; - -// Define STRIP if it is not already defined -if (!defined('STRIP')) -{ - // If we are on PHP >= 6.0.0 we do not need some code - if (version_compare(PHP_VERSION, '6.0.0-dev', '>=')) - { - /** - * @ignore - */ - define('STRIP', false); - } - else - { - @set_magic_quotes_runtime(0); - - // We do not allow register globals set - if (@ini_get('register_globals') == '1' || strtolower(@ini_get('register_globals')) == 'on' || !function_exists('ini_get')) - { - die('phpBB will not work with register globals turned on. Please turn register globals off.'); - } - - define('STRIP', (@get_magic_quotes_gpc()) ? true : false); - } -} - -// we check for the cron script and change the root path -if (defined('IN_CRON')) -{ - @define('PHPBB_ROOT_PATH', dirname(__FILE__) . DIRECTORY_SEPARATOR); -} - -// Set some default configuration parameter if the config file does not exist -if (!file_exists(PHPBB_ROOT_PATH . 'config.' . PHP_EXT)) -{ - // phpbb::$base_config['config_set'] = false - // This allows common.php or an installation script to do specific actions if the configuration is missing -} -else -{ - require PHPBB_ROOT_PATH . 'config.' . PHP_EXT; -} - -// Register autoload function -spl_autoload_register('__phpbb_autoload'); - -// Set error handler before a real one is there -set_error_handler(array('phpbb', 'error_handler')); - -// Add constants -include_once PHPBB_ROOT_PATH . 'includes/constants.' . PHP_EXT; - -// Add global functions -// @todo remove functions_content, trim down functions.php -require_once PHPBB_ROOT_PATH . 'includes/functions.' . PHP_EXT; -require_once PHPBB_ROOT_PATH . 'includes/functions_content.' . PHP_EXT; - -// Add UTF8 tools -require_once PHPBB_ROOT_PATH . 'includes/utf/utf_tools.' . PHP_EXT; - -// Add pre-defined system core files -require_once PHPBB_ROOT_PATH . 'includes/core/request.' . PHP_EXT; - -phpbb::register('security', false, 'core/security'); -phpbb::register('url', false, 'core/url'); -phpbb::register('system', false, 'core/system'); -phpbb::register('server-vars', 'phpbb_system_info', 'core/system_info'); - -// Make plugins structure available -phpbb::register('plugins'); - -?>
\ No newline at end of file diff --git a/phpBB/includes/core/core.php b/phpBB/includes/core/core.php deleted file mode 100644 index 2b2c4bea13..0000000000 --- a/phpBB/includes/core/core.php +++ /dev/null @@ -1,440 +0,0 @@ -<?php -/** -* -* @package core -* @version $Id$ -* @copyright (c) 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit(); -} - -/** -* phpBB abstract class -* -* @package core -* @author acydburn -*/ -abstract class phpbb -{ - /** - * The phpBB template object - */ - public static $template = NULL; - - /** - * The phpBB user object - */ - public static $user = NULL; - - /** - * The phpBB database object - */ - public static $db = NULL; - - /** - * The phpBB cache system object - */ - public static $acm = NULL; - - /** - * The phpBB permission object - */ - public static $acl = NULL; - - /** - * The phpBB plugins object - */ - public static $plugins = NULL; - - /** - * The phpBB core url object - * Responsible for handling URL-related tasks as well as redirects, etc. - */ - public static $url = NULL; - - /** - * The phpBB core security object. - * Responsible for handling security-related tasks, for example password handling, random number generation... - */ - public static $security = NULL; - - /** - * The phpBB core system object - * Responsible for handling file/server tasks. - */ - public static $system = NULL; - - /** - * The phpBB API object - */ - public static $api = NULL; - - /** - * @var array The phpBB configuration array - */ - public static $config = array(); - - /** - * @var array The base configuration array - */ - public static $base_config = array( - 'table_prefix' => 'phpbb_', - 'admin_folder' => 'adm', - 'acm_type' => 'file', - - 'config_set' => false, - 'extensions_set' => false, - - 'memory_usage' => 0, - - 'debug' => false, - 'debug_extra' => false, - 'installed' => false, - ); - - /** - * @var array Last notice occurred in message handler - */ - public static $last_notice = array( - 'file' => '', - 'line' => 0, - 'message' => '', - 'errno' => E_NOTICE, - ); - - /**#@+ - * Permission constant - */ - const ACL_NEVER = 0; - const ACL_YES = 1; - const ACL_NO = -1; - /**#@-*/ - - /**#@+ - * Global constant for {@link phpbb::$system->chmod()} - */ - const CHMOD_ALL = 7; - const CHMOD_READ = 4; - const CHMOD_WRITE = 2; - const CHMOD_EXECUTE = 1; - /**#@-*/ - - /**#@+ - * Constant defining plugin mode for objects - */ - const METHOD_ADD = 1; - const METHOD_OVERRIDE = 2; - const METHOD_INJECT = 4; - /**#@-*/ - - /**#@+ - * Constant defining plugin mode for functions - */ - const FUNCTION_OVERRIDE = 1; - const FUNCTION_INJECT = 2; - /**#@-*/ - - /**#@+ - * Constant to define user level. See {@link phpbb::$user phpbb::$user} - */ - const USER_NORMAL = 0; - const USER_INACTIVE = 1; - const USER_IGNORE = 2; - const USER_FOUNDER = 3; - /**#@-*/ - - /** - * @var array a static array holding custom objects - */ - public static $instances = NULL; - - /** - * We do not want this class instantiable - */ - private function ___construct() { } - - /** - * A failover error handler to handle errors before we assign our own error handler - * - * @access public - */ - public static function error_handler($errno, $errstr, $errfile, $errline) - { - throw new ErrorException($errstr, 0, $errno, $errfile, $errline); - } - - /** - * Set base configuration - called from config.php file - */ - public static function set_config($config) - { - phpbb::$base_config = array_merge(phpbb::$base_config, $config); - phpbb::$base_config['config_set'] = true; - - if (phpbb::$base_config['debug_extra'] && function_exists('memory_get_usage')) - { - phpbb::$base_config['memory_usage'] = memory_get_usage(); - } - - // Load Extensions - if (!empty(phpbb::$base_config['extensions']) && !phpbb::$base_config['extensions_set']) - { - $load_extensions = explode(',', phpbb::$base_config['extensions']); - - foreach ($load_extensions as $extension) - { - @dl(trim($extension)); - } - - phpbb::$base_config['extensions_set'] = true; - } - } - - /** - * Get instance of static property - * - * @param string $variable The name of the instance to retrieve. - * - * @return mixed The property (object/array/...) registered with this name - * @access public - */ - public static function get_instance($variable) - { - if (!self::registered($variable)) - { - return self::register($variable); - } - - // Please do not try to change it to (expr) ? (true) : (false) - it will not work. ;) - if (property_exists('phpbb', $variable)) - { - return self::$$variable; - } - else - { - return self::$instances[$variable]; - } - } - - /** - * Check if the variable is already assigned - * - * @param string $variable The name of the instance to check - * - * @return bool True if the instance is registered, false if not. - * @access public - */ - public static function registered($variable) - { - if (property_exists('phpbb', $variable)) - { - return (self::$$variable !== NULL) ? true : false; - } - - return (isset(self::$instances[$variable]) && self::$instances[$variable] !== NULL) ? true : false; - } - - /** - * Simpler method to access assigned instances. - * (Overloading is not possible here due to the object being static and our use of PHP 5.2.x+.) - * - * @param string $variable The instance name to retrieve - * - * @return mixed The instance - * @access public - */ - public static function get($variable) - { - // No error checking done here... returned right away - return self::$instances[$variable]; - } - - /** - * Register new class/object. - * Any additional parameter will be forwarded to the class instantiation. - * - * @param string $variable The resulting instance name. - * If a property with the given name exists, it will be assigned. - * Else it will be put in the {@link $instances intances} array - * @param string $class Define a custom class name. - * This is useful if the class used does not abide to the rules (phpbb_{$class}). - * @param string|array $includes Define additional files/includes required for this class to be correctly set up. Files are expected to be in /includes/. - * @param mixed $arguments,... Any number of additional arguments passed to the constructor of the object to create - * - * @return mixed The instance of the created object - * @access public - */ - public static function register($variable, $class = false, $includes = false) - { - if (self::registered($variable)) - { - return self::get_instance($variable); - } - - $arguments = (func_num_args() > 3) ? array_slice(func_get_args(), 3) : array(); - $class = ($class === false) ? 'phpbb_' . $variable : $class; - - if ($includes !== false) - { - if (!is_array($includes)) - { - $includes = array($includes); - } - - foreach ($includes as $file) - { - require_once PHPBB_ROOT_PATH . 'includes/' . $file . '.' . PHP_EXT; - } - } - - $reflection = new ReflectionClass($class); - - if (!$reflection->isInstantiable()) - { - throw new Exception('Assigned classes need to be instantiated.'); - } - - if (!property_exists('phpbb', $variable)) - { - self::$instances[$variable] = (sizeof($arguments)) ? call_user_func_array(array($reflection, 'newInstance'), $arguments) : $reflection->newInstance(); - } - else - { - self::$$variable = (sizeof($arguments)) ? call_user_func_array(array($reflection, 'newInstance'), $arguments) : $reflection->newInstance(); - } - - return self::get_instance($variable); - } - - /** - * Instead of registering we also can assign a variable. This is helpful if we have an application builder or use a factory. - * - * @param string $variable The resulting instance name. - * If a property with the given name exists, it will be assigned. - * Else it will be put in the {@link $instances intances} array - * @param mixed $object The variable to assign to the instance - * - * @return mixed The instance - * @access public - */ - public static function assign($variable, $object) - { - if (self::registered($variable)) - { - return self::get_instance($variable); - } - - if (!property_exists('phpbb', $variable)) - { - self::$instances[$variable] = $object; - } - else - { - self::$$variable = $object; - } - - return self::get_instance($variable); - } - - /** - * Unset/unregister a specific object. - * - * @param string $variable The name of the instance to unset - * @access public - */ - public static function unregister($variable) - { - if (!self::registered($variable)) - { - return; - } - - if (!property_exists('phpbb', $variable)) - { - unset(self::$instances[$variable]); - } - else - { - self::$$variable = NULL; - } - } - - /** - * Function to return to a clean state, unregistering everything. This is helpful for unit tests if you want to return to a "clean state" - * - * @access public - */ - public static function reset() - { - $class_vars = array_keys(get_class_vars('phpbb')); - $class_vars = array_merge(array_keys(self::$instances), $class_vars); - - foreach ($class_vars as $variable) - { - self::unregister($variable); - } - } -} - -/** -* phpBB SPL Autoload Function. A phpbb_ prefix will be stripped from the class name. -* -* The files this function tries to include are: -* includes/{$class_name}/bootstrap.php -* includes/{$class_name}/index.php -* Additionally, every _ within $class_name is replaced by / for the following directories: -* includes/{$class_name}.php -* includes/classes/{$class_name}.php -* -* @param string $class_name The class name. An existing phpbb_ prefix will be removed. -*/ -function __phpbb_autoload($class_name) -{ - if (strpos($class_name, 'phpbb_') === 0) - { - $class_name = substr($class_name, 6); - } - - $class_name = basename($class_name); - - $filenames = array( - 'includes/' . $class_name . '/bootstrap', - 'includes/' . $class_name . '/index', - 'includes/' . $class_name, - 'includes/classes/' . $class_name, - ); - - if (strpos($class_name, '_') !== false) - { - $class_name = str_replace('_', '/', $class_name); - - $filenames = array_merge($filenames, array( - 'includes/' . $class_name, - 'includes/classes/' . $class_name, - )); - } - - foreach ($filenames as $filename) - { - if (file_exists(PHPBB_ROOT_PATH . $filename . '.' . PHP_EXT)) - { - include PHPBB_ROOT_PATH . $filename . '.' . PHP_EXT; - return; - } - } -} - -/* -class phpbb_exception extends Exception -{ -} -*/ -?>
\ No newline at end of file diff --git a/phpBB/includes/core/request.php b/phpBB/includes/core/request.php deleted file mode 100644 index 7f3f158dc0..0000000000 --- a/phpBB/includes/core/request.php +++ /dev/null @@ -1,562 +0,0 @@ -<?php -/** -* -* @package core -* @version $Id$ -* @copyright (c) 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Replacement for a superglobal (like $_GET or $_POST) which calls -* trigger_error on any operation, overloads the [] operator using SPL. -* -* @package core -* @author naderman -*/ -class deactivated_super_global implements ArrayAccess, Countable, IteratorAggregate -{ - /** - * @var string Holds the error message - */ - private $message; - - /** - * Constructor generates an error message fitting the super global to be used within the other functions. - * - * @param string $name Name of the super global this is a replacement for - e.g. '_GET' - */ - public function __construct($name) - { - $this->message = 'Illegal use of $' . $name . '. You must use the request class or request_var() to access input data. Found in %s on line %d. This error message was generated'; - } - - /** - * Calls trigger_error with the file and line number the super global was used in - * - * @access private - */ - private function error() - { - $file = ''; - $line = 0; - - $backtrace = debug_backtrace(); - if (isset($backtrace[1])) - { - $file = $backtrace[1]['file']; - $line = $backtrace[1]['line']; - } - trigger_error(sprintf($this->message, $file, $line), E_USER_ERROR); - } - - /**#@+ - * Part of the ArrayAccess implementation, will always result in a FATAL error - * - * @access public - */ - public function offsetExists($offset) - { - $this->error(); - } - - public function offsetGet($offset) - { - $this->error(); - } - - public function offsetSet($offset, $value) - { - $this->error(); - } - - public function offsetUnset($offset) - { - $this->error(); - } - /**#@-*/ - - /** - * Part of the Countable implementation, will always result in a FATAL error - * - * @access public - */ - public function count() - { - $this->error(); - } - - /** - * Part of the Traversable/IteratorAggregate implementation, will always result in a FATAL error - * - * @access public - */ - public function getIterator() - { - $this->error(); - } -} - -/** -* All application input is accessed through this class. -* -* It provides a method to disable access to input data through super globals. -* This should force MOD authors to read about data validation. -* -* @package core -* @author naderman -*/ -class phpbb_request -{ - /**#@+ - * Constant defining the super global - */ - const POST = 0; - const GET = 1; - const REQUEST = 2; - const COOKIE = 3; - /**#@-*/ - - /** - * @var - */ - protected static $initialised = false; - - /** - * @var - */ - protected static $super_globals_disabled = false; - - /** - * @var array The names of super global variables that this class should protect if super globals are disabled - */ - protected static $super_globals = array(phpbb_request::POST => '_POST', phpbb_request::GET => '_GET', phpbb_request::REQUEST => '_REQUEST', phpbb_request::COOKIE => '_COOKIE'); - - /** - * @var array An associative array that has the value of super global constants as keys and holds their data as values. - */ - protected static $input; - - /** - * Initialises the request class, that means it stores all input data in {@link $input self::$input} - * - * @access public - */ - public static function init() - { - if (!self::$initialised) - { - foreach (self::$super_globals as $const => $super_global) - { - if ($const == phpbb_request::REQUEST) - { - continue; - } - - self::$input[$const] = isset($GLOBALS[$super_global]) ? $GLOBALS[$super_global] : array(); - } - - // @todo far away from ideal... just a quick hack to let request_var() work again. The problem is that $GLOBALS['_REQUEST'] no longer exist. - self::$input[phpbb_request::REQUEST] = array_merge(self::$input[phpbb_request::POST], self::$input[phpbb_request::GET]); - - self::$initialised = true; - } - } - - /** - * Resets the request class. - * This will simply forget about all input data and read it again from the - * super globals, if super globals were disabled, all data will be gone. - * - * @access public - */ - public static function reset() - { - self::$input = array(); - self::$initialised = false; - self::$super_globals_disabled = false; - } - - /** - * Getter for $super_globals_disabled - * - * @return bool Whether super globals are disabled or not. - * @access public - */ - public static function super_globals_disabled() - { - return self::$super_globals_disabled; - } - - /** - * Disables access of super globals specified in $super_globals. - * This is achieved by overwriting the super globals with instances of {@link deactivated_super_global deactivated_super_global} - * - * @access public - */ - public static function disable_super_globals() - { - if (!self::$initialised) - { - self::init(); - } - - foreach (self::$super_globals as $const => $super_global) - { - unset($GLOBALS[$super_global]); - $GLOBALS[$super_global] = new deactivated_super_global($super_global); - } - - self::$super_globals_disabled = true; - } - - /** - * Enables access of super globals specified in $super_globals if they were disabled by {@link disable_super_globals disable_super_globals}. - * This is achieved by making the super globals point to the data stored within this class in {@link $input input}. - * - * @access public - */ - public static function enable_super_globals() - { - if (!self::$initialised) - { - self::init(); - } - - if (self::$super_globals_disabled) - { - foreach (self::$super_globals as $const => $super_global) - { - $GLOBALS[$super_global] = self::$input[$const]; - } - - self::$super_globals_disabled = false; - } - } - - /** - * Recursively applies addslashes to a variable. - * - * @param mixed &$var Variable passed by reference to which slashes will be added. - * @access protected - */ - protected static function addslashes_recursively(&$var) - { - if (is_string($var)) - { - $var = addslashes($var); - } - else if (is_array($var)) - { - $var_copy = $var; - foreach ($var_copy as $key => $value) - { - if (is_string($key)) - { - $key = addslashes($key); - } - self::addslashes_recursively($var[$key]); - } - } - } - - /** - * This function allows overwriting or setting a value in one of the super global arrays. - * - * Changes which are performed on the super globals directly will not have any effect on the results of - * other methods this class provides. Using this function should be avoided if possible! It will - * consume twice the the amount of memory of the value - * - * @param string $var_name The name of the variable that shall be overwritten - * @param mixed $value The value which the variable shall contain. - * If this is null the variable will be unset. - * @param phpbb_request::POST|phpbb_request::GET|phpbb_request::REQUEST|phpbb_request::COOKIE $super_global Specifies which super global shall be changed - * - * @access public - */ - public static function overwrite($var_name, $value, $super_global = phpbb_request::REQUEST) - { - if (!self::$initialised) - { - self::init(); - } - - if (!isset(self::$super_globals[$super_global])) - { - return; - } - - if (STRIP) - { - self::addslashes_recursively($value); - } - - // setting to null means unsetting - if ($value === null) - { - unset(self::$input[$super_global][$var_name]); - if (!self::super_globals_disabled()) - { - unset($GLOBALS[self::$super_globals[$super_global]][$var_name]); - } - } - else - { - self::$input[$super_global][$var_name] = $value; - if (!self::super_globals_disabled()) - { - $GLOBALS[self::$super_globals[$super_global]][$var_name] = $value; - } - } - - if (!self::super_globals_disabled()) - { - unset($GLOBALS[self::$super_globals[$super_global]][$var_name]); - $GLOBALS[self::$super_globals[$super_global]][$var_name] = $value; - } - } - - /** - * Set variable $result. Used by {@link request_var() the request_var function} - * - * @param mixed &$result The variable to fill - * @param mixed $var The contents to fill with - * @param mixed $type The variable type. Will be used with {@link settype()} - * @param bool $multibyte Indicates whether string values may contain UTF-8 characters. - * Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks. - * - * @access public - */ - public static function set_var(&$result, $var, $type, $multibyte = false) - { - settype($var, $type); - $result = $var; - - if ($type == 'string') - { - $result = trim(utf8_htmlspecialchars(str_replace(array("\r\n", "\r", "\0"), array("\n", "\n", ''), $result))); - - if (!empty($result)) - { - // Make sure multibyte characters are wellformed - if ($multibyte) - { - if (!preg_match('/^./u', $result)) - { - $result = ''; - } - } - else - { - // no multibyte, allow only ASCII (0-127) - $result = preg_replace('/[\x80-\xFF]/', '?', $result); - } - } - - $result = (STRIP) ? stripslashes($result) : $result; - } - } - - /** - * Recursively sets a variable to a given type using {@link set_var() set_var} - * This function is only used from within {@link phpbb_request::variable phpbb_request::variable}. - * - * @param string $var The value which shall be sanitised (passed by reference). - * @param mixed $default Specifies the type $var shall have. - * If it is an array and $var is not one, then an empty array is returned. - * Otherwise var is cast to the same type, and if $default is an array all keys and values are cast recursively using this function too. - * @param bool $multibyte Indicates whether string values may contain UTF-8 characters. - * Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks. - * - * @access protected - */ - protected static function recursive_set_var(&$var, $default, $multibyte) - { - if (is_array($var) !== is_array($default)) - { - $var = (is_array($default)) ? array() : $default; - return; - } - - if (!is_array($default)) - { - $type = gettype($default); - self::set_var($var, $var, $type, $multibyte); - } - else - { - // make sure there is at least one key/value pair to use get the - // types from - if (!sizeof($default)) - { - $var = array(); - return; - } - - list($default_key, $default_value) = each($default); - $value_type = gettype($default_value); - $key_type = gettype($default_key); - - $_var = $var; - $var = array(); - - foreach ($_var as $k => $v) - { - self::set_var($k, $k, $key_type, $multibyte); - - self::recursive_set_var($v, $default_value, $multibyte); - self::set_var($var[$k], $v, $value_type, $multibyte); - } - } - } - - /** - * Central type safe input handling function. - * All variables in GET or POST requests should be retrieved through this function to maximise security. - * - * @param string|array $var_name The form variable's name from which data shall be retrieved. - * If the value is an array this may be an array of indizes which will give - * direct access to a value at any depth. E.g. if the value of "var" is array(1 => "a") - * then specifying array("var", 1) as the name will return "a". - * @param mixed $default A default value that is returned if the variable was not set. - * This function will always return a value of the same type as the default. - * @param bool $multibyte If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters - * Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks - * @param phpbb_request::POST|phpbb_request::GET|phpbb_request::REQUEST|phpbb_request::COOKIE $super_global Specifies which super global should be used - * - * @return mixed The value of $_REQUEST[$var_name] run through {@link set_var set_var} to ensure that the type is the - * the same as that of $default. If the variable is not set $default is returned. - * @access public - */ - public static function variable($var_name, $default, $multibyte = false, $super_global = phpbb_request::REQUEST) - { - $path = false; - - if (!self::$initialised) - { - self::init(); - } - - // deep direct access to multi dimensional arrays - if (is_array($var_name)) - { - $path = $var_name; - // make sure at least the variable name is specified - if (!sizeof($path)) - { - return (is_array($default)) ? array() : $default; - } - // the variable name is the first element on the path - $var_name = array_shift($path); - } - - if (!isset(self::$input[$super_global][$var_name])) - { - return (is_array($default)) ? array() : $default; - } - $var = self::$input[$super_global][$var_name]; - - // make sure cookie does not overwrite get/post - if ($super_global != phpbb_request::COOKIE && isset(self::$input[phpbb_request::COOKIE][$var_name])) - { - if (!isset(self::$input[phpbb_request::GET][$var_name]) && !isset(self::$input[phpbb_request::POST][$var_name])) - { - return (is_array($default)) ? array() : $default; - } - $var = isset(self::$input[phpbb_request::POST][$var_name]) ? self::$input[phpbb_request::POST][$var_name] : self::$input[phpbb_request::GET][$var_name]; - } - - if ($path) - { - // walk through the array structure and find the element we are looking for - foreach ($path as $key) - { - if (is_array($var) && isset($var[$key])) - { - $var = $var[$key]; - } - else - { - return (is_array($default)) ? array() : $default; - } - } - } - - self::recursive_set_var($var, $default, $multibyte); - - return $var; - } - - /** - * Checks whether a certain variable was sent via POST. - * To make sure that a request was sent using POST you should call this function - * on at least one variable. - * - * @param string $name The name of the form variable which should have a - * _p suffix to indicate the check in the code that creates the form too. - * - * @return bool True if the variable was set in a POST request, false otherwise. - * @access public - */ - public static function is_set_post($name) - { - return self::is_set($name, phpbb_request::POST); - } - - /** - * Checks whether a certain variable is set in one of the super global - * arrays. - * - * @param string $var Name of the variable - * @param phpbb_request::POST|phpbb_request::GET|phpbb_request::REQUEST|phpbb_request::COOKIE $super_global - * Specifies the super global which shall be checked - * - * @return bool True if the variable was sent as input - * @access public - */ - public static function is_set($var, $super_global = phpbb_request::REQUEST) - { - if (!self::$initialised) - { - self::init(); - } - - return isset(self::$input[$super_global][$var]); - } - - /** - * Returns all variable names for a given super global - * - * @param phpbb_request::POST|phpbb_request::GET|phpbb_request::REQUEST|phpbb_request::COOKIE $super_global - * The super global from which names shall be taken - * - * @return array All variable names that are set for the super global. - * Pay attention when using these, they are unsanitised! - * @access public - */ - public static function variable_names($super_global = phpbb_request::REQUEST) - { - if (!self::$initialised) - { - self::init(); - } - - if (!isset(self::$input[$super_global])) - { - return array(); - } - - return array_keys(self::$input[$super_global]); - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/core/security.php b/phpBB/includes/core/security.php deleted file mode 100644 index f5aca65e8d..0000000000 --- a/phpBB/includes/core/security.php +++ /dev/null @@ -1,300 +0,0 @@ -<?php -/** -* -* @package core -* @version $Id$ -* @copyright (c) 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit(); -} -/** -* Class for generating random numbers, unique ids, unique keys, seeds, hashes... -* @package core -*/ -class phpbb_security extends phpbb_plugin_support -{ - /** - * @var array required phpBB objects - */ - public $phpbb_required = array(); - - /** - * @var array Optional phpBB objects - */ - public $phpbb_optional = array('config'); - - /** - * @var string Used hash type. The default type is $P$, phpBB uses a different one. - */ - public $hash_type = '$H$'; - - /** - * @var bool Is true if random seed got updated. - */ - private $dss_seeded = false; - - /** - * Constructor - * @access public - */ - public function __construct() {} - - /** - * Generates an alphanumeric random string of given length - * - * @param int $num_chars Number of characters to return - * @return string Random string of $num_chars characters. - * @access public - */ - public function gen_rand_string($num_chars = 8) - { - $rand_str = $this->unique_id(); - $rand_str = str_replace('0', 'Z', strtoupper(base_convert($rand_str, 16, 35))); - - return substr($rand_str, 0, $num_chars); - } - - /** - * Return unique id - * - * @param string $extra Additional entropy - * @return string Unique id - * @access public - */ - public function unique_id($extra = 'c') - { - if (!isset(phpbb::$config['rand_seed'])) - { - $val = md5(md5($extra) . microtime()); - $val = md5(md5($extra) . $val . $extra); - return substr($val, 4, 16); - } - - - $val = phpbb::$config['rand_seed'] . microtime(); - $val = md5($val); - phpbb::$config['rand_seed'] = md5(phpbb::$config['rand_seed'] . $val . $extra); - - if (!$this->dss_seeded && phpbb::$config['rand_seed_last_update'] < time() - rand(1, 10)) - { - set_config('rand_seed', phpbb::$config['rand_seed'], true); - set_config('rand_seed_last_update', time(), true); - - $this->dss_seeded = true; - } - - return substr($val, 4, 16); - } - - /** - * Hash passwords - * - * @version Version 0.1 - * - * Portable PHP password hashing framework. - * - * Written by Solar Designer <solar at openwall.com> in 2004-2006 and placed in - * the public domain. - * - * There's absolutely no warranty. - * - * The homepage URL for this framework is: - * - * http://www.openwall.com/phpass/ - * - * Please be sure to update the Version line if you edit this file in any way. - * It is suggested that you leave the main version number intact, but indicate - * your project name (after the slash) and add your own revision information. - * - * Please do not change the "private" password hashing method implemented in - * here, thereby making your hashes incompatible. However, if you must, please - * change the hash type identifier (the "$P$") to something different. - * - * Obviously, since this code is in the public domain, the above are not - * requirements (there can be none), but merely suggestions. - * - * @param string $password Password to hash - * @return string Hashed password - * @access public - */ - public function hash_password($password) - { - $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; - - $random_state = $this->unique_id(); - $random = ''; - $count = 6; - - if (($fh = @fopen('/dev/urandom', 'rb'))) - { - $random = fread($fh, $count); - fclose($fh); - } - - if (strlen($random) < $count) - { - $random = ''; - - for ($i = 0; $i < $count; $i += 16) - { - $random_state = md5($this->unique_id() . $random_state); - $random .= pack('H*', md5($random_state)); - } - $random = substr($random, 0, $count); - } - - $hash = $this->_hash_crypt_private($password, $this->_hash_gensalt_private($random, $itoa64), $itoa64); - $result = (strlen($hash) == 34) ? $hash : md5($password); - - return $result; - } - - /** - * Check for correct password - * - * If the hash length is != 34, then a md5($password) === $hash comparison is done. The correct hash length is 34. - * - * @param string $password The password in plain text - * @param string $hash The stored password hash - * - * @return bool Returns true if the password is correct, false if not. - * @access public - */ - public function check_password($password, $hash) - { - $itoa64 = './0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz'; - if (strlen($hash) == 34) - { - $result = ($this->_hash_crypt_private($password, $hash, $itoa64) === $hash) ? true : false; - } - else - { - $result = (md5($password) === $hash) ? true : false; - } - - return $result; - } - - /** - * Generate salt for hash generation - * @access private - */ - private function _hash_gensalt_private($input, &$itoa64, $iteration_count_log2 = 6) - { - if ($iteration_count_log2 < 4 || $iteration_count_log2 > 31) - { - $iteration_count_log2 = 8; - } - - $output = $this->hash_type; - $output .= $itoa64[min($iteration_count_log2 + 5, 30)]; - $output .= $this->_hash_encode64($input, 6, $itoa64); - - return $output; - } - - /** - * Encode hash - * @access private - */ - private function _hash_encode64($input, $count, &$itoa64) - { - $output = ''; - $i = 0; - - do - { - $value = ord($input[$i++]); - $output .= $itoa64[$value & 0x3f]; - - if ($i < $count) - { - $value |= ord($input[$i]) << 8; - } - - $output .= $itoa64[($value >> 6) & 0x3f]; - - if ($i++ >= $count) - { - break; - } - - if ($i < $count) - { - $value |= ord($input[$i]) << 16; - } - - $output .= $itoa64[($value >> 12) & 0x3f]; - - if ($i++ >= $count) - { - break; - } - - $output .= $itoa64[($value >> 18) & 0x3f]; - } - while ($i < $count); - - return $output; - } - - /** - * The crypt function/replacement - * @access private - */ - private function _hash_crypt_private($password, $setting, &$itoa64) - { - $output = '*'; - - // Check for correct hash - if (substr($setting, 0, 3) != $this->hash_type) - { - return $output; - } - - $count_log2 = strpos($itoa64, $setting[3]); - - if ($count_log2 < 7 || $count_log2 > 30) - { - return $output; - } - - $count = 1 << $count_log2; - $salt = substr($setting, 4, 8); - - if (strlen($salt) != 8) - { - return $output; - } - - /** - * We're kind of forced to use MD5 here since it's the only - * cryptographic primitive available in all versions of PHP - * currently in use. To implement our own low-level crypto - * in PHP would result in much worse performance and - * consequently in lower iteration counts and hashes that are - * quicker to crack (by non-PHP code). - */ - $hash = md5($salt . $password, true); - do - { - $hash = md5($hash . $password, true); - } - while (--$count); - - $output = substr($setting, 0, 12); - $output .= $this->_hash_encode64($hash, 16, $itoa64); - - return $output; - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/core/system.php b/phpBB/includes/core/system.php deleted file mode 100644 index 5bb42e9ed4..0000000000 --- a/phpBB/includes/core/system.php +++ /dev/null @@ -1,213 +0,0 @@ -<?php -/** -* -* @package core -* @version $Id$ -* @copyright (c) 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit(); -} - -/** -* System-specific methods. For example chmod(), unlink()... -* -* @package core -*/ -class phpbb_system extends phpbb_plugin_support -{ - /** - * @var array required phpBB objects - */ - public $phpbb_required = array(); - - /** - * @var array Optional phpBB objects - */ - public $phpbb_optional = array(); - - /** - * @var array Holding some information for chmod() - */ - private $chmod_info = array(); - - /** - * Method for chmodding directories and files for internal use. - * - * This function determines owner and group whom the file belongs to and user and group of PHP and then set safest possible file permissions. - * The function determines owner and group from common.php file and sets the same to the provided file. - * The function uses bit fields to build the permissions. - * The function sets the appropiate execute bit on directories. - * - * Supported constants representing bit fields are: - * - * phpbb::CHMOD_ALL - all permissions (7) - * phpbb::CHMOD_READ - read permission (4) - * phpbb::CHMOD_WRITE - write permission (2) - * phpbb::CHMOD_EXECUTE - execute permission (1) - * - * NOTE: The function uses POSIX extension and fileowner()/filegroup() functions. If any of them is disabled, this function tries to build proper permissions, by calling is_readable() and is_writable() functions. - * - * @param string $filename The file/directory to be chmodded - * @param int $perms Permissions to set - * - * @return bool true on success, otherwise false - * @author faw, phpBB Group - * @access public - */ - public function chmod($filename, $perms = phpbb::CHMOD_READ) - { - // Return if the file no longer exists. - if (!file_exists($filename)) - { - return false; - } - - // Determine some common vars - if (empty($this->chmod_info)) - { - if (!function_exists('fileowner') || !function_exists('filegroup')) - { - // No need to further determine owner/group - it is unknown - $this->chmod_info['process'] = false; - } - else - { - // Determine owner/group of common.php file and the filename we want to change here - $common_php_owner = fileowner(PHPBB_ROOT_PATH . 'common.' . PHP_EXT); - $common_php_group = filegroup(PHPBB_ROOT_PATH . 'common.' . PHP_EXT); - - // And the owner and the groups PHP is running under. - $php_uid = (function_exists('posix_getuid')) ? @posix_getuid() : false; - $php_gids = (function_exists('posix_getgroups')) ? @posix_getgroups() : false; - - if (!$php_uid || empty($php_gids) || !$common_php_owner || !$common_php_group) - { - $this->chmod_info['process'] = false; - } - else - { - $this->chmod_info = array( - 'process' => true, - 'common_owner' => $common_php_owner, - 'common_group' => $common_php_group, - 'php_uid' => $php_uid, - 'php_gids' => $php_gids, - ); - } - } - } - - if ($this->chmod_info['process']) - { - $file_uid = fileowner($filename); - $file_gid = filegroup($filename); - - // Change owner - if (@chown($filename, $this->chmod_info['common_owner'])) - { - clearstatcache(); - $file_uid = fileowner($filename); - } - - // Change group - if (@chgrp($filename, $this->chmod_info['common_group'])) - { - clearstatcache(); - $file_gid = filegroup($filename); - } - - // If the file_uid/gid now match the one from common.php we can process further, else we are not able to change something - if ($file_uid != $this->chmod_info['common_owner'] || $file_gid != $this->chmod_info['common_group']) - { - $this->chmod_info['process'] = false; - } - } - - // Still able to process? - if ($this->chmod_info['process']) - { - if ($file_uid == $this->chmod_info['php_uid']) - { - $php = 'owner'; - } - else if (in_array($file_gid, $this->chmod_info['php_gids'])) - { - $php = 'group'; - } - else - { - // Since we are setting the everyone bit anyway, no need to do expensive operations - $this->chmod_info['process'] = false; - } - } - - // We are not able to determine or change something - if (!$this->chmod_info['process']) - { - $php = 'other'; - } - - // Owner always has read/write permission - $owner = phpbb::CHMOD_READ | phpbb::CHMOD_WRITE; - if (is_dir($filename)) - { - $owner |= phpbb::CHMOD_EXECUTE; - - // Only add execute bit to the permission if the dir needs to be readable - if ($perms & phpbb::CHMOD_READ) - { - $perms |= phpbb::CHMOD_EXECUTE; - } - } - - switch ($php) - { - case 'owner': - $result = @chmod($filename, ($owner << 6) + (0 << 3) + (0 << 0)); - - clearstatcache(); - - if (!is_null($php) || (is_readable($filename) && is_writable($filename))) - { - break; - } - - case 'group': - $result = @chmod($filename, ($owner << 6) + ($perms << 3) + (0 << 0)); - - clearstatcache(); - - if (!is_null($php) || ((!($perms & phpbb::CHMOD_READ) || is_readable($filename)) && (!($perms & phpbb::CHMOD_WRITE) || is_writable($filename)))) - { - break; - } - - case 'other': - $result = @chmod($filename, ($owner << 6) + ($perms << 3) + ($perms << 0)); - - clearstatcache(); - - if (!is_null($php) || ((!($perms & phpbb::CHMOD_READ) || is_readable($filename)) && (!($perms & phpbb::CHMOD_WRITE) || is_writable($filename)))) - { - break; - } - - default: - return false; - break; - } - - return $result; - } - -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/core/system_info.php b/phpBB/includes/core/system_info.php deleted file mode 100644 index 56a5d3bcd0..0000000000 --- a/phpBB/includes/core/system_info.php +++ /dev/null @@ -1,376 +0,0 @@ -<?php -/** -* -* @package core -* @version $Id$ -* @copyright (c) 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit(); -} - -/** -* Get system/server information variables. -* -* @package core -*/ -class phpbb_system_info extends phpbb_plugin_support implements ArrayAccess -{ - /** - * @var array required phpBB objects - */ - public $phpbb_required = array('config', 'url'); - - /** - * @var array Optional phpBB objects - */ - public $phpbb_optional = array(); - - /** - * @var array Array for storing/accessing information - */ - private $data = array(); - - /**#@+ - * Part of the ArrayAccess implementation. - * @access public - */ - public function offsetSet($offset, $value) - { - $this->data[$offset] = $value; - } - - public function offsetExists($offset) - { - return isset($this->data[$offset]); - } - - public function offsetUnset($offset) - { - unset($this->data[$offset]); - } - /**#@-*/ - - /** - * Get system information - Part of the ArrayAccess implementation. - * - * System information ought to be received from {@link $data phpbb::$user->system[key]}. - * The key used is mapped to a method with get_ as prefix. - * For example getting phpbb::$user->system['host'] results in calling the method get_host(). - * - * @param string $offset The key to get. - * @return mixed The result - * @access public - */ - public function offsetGet($offset) - { - if (isset($this->data[$offset])) - { - return $this->data[$offset]; - } - - $identifier = 'get_' . strtolower($offset); - - // Not static, because we are not able to use late static bindings - $this->data[$offset] = $this->$identifier(); - return $this->data[$offset]; - } - - /** - * Get valid hostname/port. HTTP_HOST is used, SERVER_NAME if HTTP_HOST not present. - * - * @return string Host (lowercase, not specialchared) - * @access protected - */ - protected function get_host() - { - // Get hostname - $host = (!empty($_SERVER['HTTP_HOST'])) ? $_SERVER['HTTP_HOST'] : ((!empty($_SERVER['SERVER_NAME'])) ? $_SERVER['SERVER_NAME'] : getenv('SERVER_NAME')); - - // Should be a string and lowered - $host = (string) strtolower($host); - - // If host is equal the cookie domain or the server name (if config is set), then we assume it is valid - if ((isset(phpbb::$config['cookie_domain']) && $host === phpbb::$config['cookie_domain']) || (isset(phpbb::$config['server_name']) && $host === phpbb::$config['server_name'])) - { - return $host; - } - - // Is the host actually a IP? If so, we use the IP... (IPv4) - if (long2ip(ip2long($host)) === $host) - { - return $host; - } - - // Now return the hostname (this also removes any port definition). The http:// is prepended to construct a valid URL, hosts never have a scheme assigned - $host = @parse_url('http://' . $host, PHP_URL_HOST); - - // Remove any portions not removed by parse_url (#) - $host = str_replace('#', '', $host); - - // If, by any means, the host is now empty, we will use a "best approach" way to guess one - if (empty($host)) - { - if (!empty(phpbb::$config['server_name'])) - { - $host = phpbb::$config['server_name']; - } - else if (!empty(phpbb::$config['cookie_domain'])) - { - $host = (strpos(phpbb::$config['cookie_domain'], '.') === 0) ? substr(phpbb::$config['cookie_domain'], 1) : phpbb::$config['cookie_domain']; - } - else - { - // Set to OS hostname or localhost - $host = (function_exists('php_uname')) ? strtolower(php_uname('n')) : 'localhost'; - } - } - - // It may be still no valid host, but for sure only a hostname (we may further expand on the cookie domain... if set) - return $host; - } - - /** - * Extract current session page, relative from current root path (PHPBB_ROOT_PATH) - * - * The array returned consist of the following key/value pairs: - * page_name: The current basename'd page name, for example: index.php (urlencoded, htmlspecialchared) - * page_dir: The current directory within the phpBB root, for example: adm - * query_string: The current query string, for example: i=10&b=2 (the parameter 'sid' is never included) - * script_path: The script path from the webroot to the current directory, for example: /phpBB3/adm/ - * The script path is always prefixed with / and ends in /. Specialchared, whitespace replaced with %20. - * root_script_path: The script path from the webroot to the phpBB root, for example: /phpBB3/ - * The root script path is always prefixed with / and ends in /. Specialchared, whitespace replaced with %20. - * page: Current page from phpBB root, for example: adm/index.php?i=10&b=2 - * forum: Current forum id (determined by {@link request_var() request_var('f', 0)}) - * - * @return array Array containing page information. - * @plugin-support return - * @access protected - */ - protected function get_page() - { - $page_array = array(); - - // First of all, get the request uri... - $script_name = (!empty($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : getenv('PHP_SELF'); - $args = (!empty($_SERVER['QUERY_STRING'])) ? explode('&', $_SERVER['QUERY_STRING']) : explode('&', getenv('QUERY_STRING')); - - // If we are unable to get the script name we use REQUEST_URI as a failover and note it within the page array for easier support... - if (!$script_name) - { - $script_name = (!empty($_SERVER['REQUEST_URI'])) ? $_SERVER['REQUEST_URI'] : getenv('REQUEST_URI'); - $script_name = (($pos = strpos($script_name, '?')) !== false) ? substr($script_name, 0, $pos) : $script_name; - $page_array['failover'] = 1; - } - - // Replace backslashes and doubled slashes (could happen on some proxy setups) - $script_name = str_replace(array('\\', '//'), '/', $script_name); - - // Now, remove the sid and let us get a clean query string... - $use_args = array(); - - // Since some browser do not encode correctly we need to do this with some "special" characters... - // " -> %22, ' => %27, < -> %3C, > -> %3E - $find = array('"', "'", '<', '>'); - $replace = array('%22', '%27', '%3C', '%3E'); - - foreach ($args as $argument) - { - if (strpos($argument, 'sid=') === 0) - { - continue; - } - - $use_args[] = str_replace($find, $replace, $argument); - } - unset($args); - - // The following examples given are for an request uri of {path to the phpbb directory}/adm/index.php?i=10&b=2 - - // The current query string - $query_string = trim(implode('&', $use_args)); - - // basenamed page name (for example: index.php) - $page_name = basename($script_name); - $page_name = urlencode(htmlspecialchars($page_name)); - - // current directory within the phpBB root (for example: adm) - $root_dirs = explode('/', str_replace('\\', '/', phpbb::$url->realpath(PHPBB_ROOT_PATH))); - $page_dirs = explode('/', str_replace('\\', '/', phpbb::$url->realpath('./'))); - $intersection = array_intersect_assoc($root_dirs, $page_dirs); - - $root_dirs = array_diff_assoc($root_dirs, $intersection); - $page_dirs = array_diff_assoc($page_dirs, $intersection); - - $page_dir = str_repeat('../', sizeof($root_dirs)) . implode('/', $page_dirs); - - if ($page_dir && substr($page_dir, -1, 1) == '/') - { - $page_dir = substr($page_dir, 0, -1); - } - - // Current page from phpBB root (for example: adm/index.php?i=10&b=2) - $page = (($page_dir) ? $page_dir . '/' : '') . $page_name . (($query_string) ? "?$query_string" : ''); - - // The script path from the webroot to the current directory (for example: /phpBB3/adm/) : always prefixed with / and ends in / - $script_path = trim(str_replace('\\', '/', dirname($script_name))); - - // The script path from the webroot to the phpBB root (for example: /phpBB3/) - $script_dirs = explode('/', $script_path); - array_splice($script_dirs, -sizeof($page_dirs)); - $root_script_path = implode('/', $script_dirs) . (sizeof($root_dirs) ? '/' . implode('/', $root_dirs) : ''); - - // We are on the base level (phpBB root == webroot), lets adjust the variables a bit... - if (!$root_script_path) - { - $root_script_path = ($page_dir) ? str_replace($page_dir, '', $script_path) : $script_path; - } - - $script_path .= (substr($script_path, -1, 1) == '/') ? '' : '/'; - $root_script_path .= (substr($root_script_path, -1, 1) == '/') ? '' : '/'; - - $page_array += array( - 'page_name' => $page_name, - 'page_dir' => $page_dir, - - 'query_string' => $query_string, - 'script_path' => str_replace(' ', '%20', htmlspecialchars($script_path)), - 'root_script_path' => str_replace(' ', '%20', htmlspecialchars($root_script_path)), - - 'page' => $page, - 'forum' => request_var('f', 0), - ); - - return ($this->method_inject(__FUNCTION__, 'return')) ? $this->call_inject(__FUNCTION__, array('return', $page_array)) : $page_array; - } - - /** - * Get user agent string. - * - * @return string User agent, determined from $_SERVER['HTTP_USER_AGENT']. Specialchared. - * @access protected - */ - protected function get_browser() - { - return (!empty($_SERVER['HTTP_USER_AGENT'])) ? htmlspecialchars((string) $_SERVER['HTTP_USER_AGENT']) : ''; - } - - /** - * Get current referer - * - * @return string Referer, determined from $_SERVER['HTTP_REFERER']. Specialchared. - * @access protected - */ - protected function get_referer() - { - return (!empty($_SERVER['HTTP_REFERER'])) ? htmlspecialchars((string) $_SERVER['HTTP_REFERER']) : ''; - } - - /** - * Get server port - * - * @return int Sertver port, determined from $_SERVER/$_ENV['SERVER_PORT']. - * @access protected - */ - protected function get_port() - { - return (!empty($_SERVER['SERVER_PORT'])) ? (int) $_SERVER['SERVER_PORT'] : (int) getenv('SERVER_PORT'); - } - - /** - * Get forwarded-for string. - * If the forwarded for check is enabled in phpBB the ip's are checked for valid data and invalid data being removed. - * - * @return string Forwarded-for string, determined from $_SERVER['HTTP_X_FORWARDED_FOR']. - * @access protected - */ - protected function get_forwarded_for() - { - $forwarded_for = (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) ? (string) $_SERVER['HTTP_X_FORWARDED_FOR'] : ''; - - // if the forwarded for header shall be checked we have to validate its contents - if (phpbb::$config['forwarded_for_check']) - { - $forwarded_for = preg_replace('#, +#', ', ', $forwarded_for); - - // split the list of IPs - $ips = explode(', ', $forwarded_for); - foreach ($ips as $ip) - { - // check IPv4 first, the IPv6 is hopefully only going to be used very seldomly - if (!empty($ip) && !preg_match(get_preg_expression('ipv4'), $ip) && !preg_match(get_preg_expression('ipv6'), $ip)) - { - // contains invalid data, don't use the forwarded for header - return ''; - } - } - } - else - { - return ''; - } - } - - /** - * Get remote ip - * - * @return string Remote IP, determined from $_SERVER['REMOTE_ADDR']. Specialchared. - * @access protected - */ - protected function get_ip() - { - return (!empty($_SERVER['REMOTE_ADDR'])) ? htmlspecialchars($_SERVER['REMOTE_ADDR']) : ''; - } - - /** - * Get server load. - * - * Server load is retrieved if load limitation is enabled in phpBB and server supports {@link sys_getloadavg() sys_getloadavg} - * or file /proc/loadavg exists on the server. - * - * @return double Server load. - * @access protected - */ - protected function get_load() - { - $load = false; - - // Load limit check (if applicable) - if (phpbb::$config['limit_load'] || phpbb::$config['limit_search_load']) - { - if ((function_exists('sys_getloadavg') && $load = sys_getloadavg()) || ($load = explode(' ', @file_get_contents('/proc/loadavg')))) - { - $load = array_slice($load, 0, 1); - $load = floatval($load[0]); - } - else - { - set_config('limit_load', '0'); - set_config('limit_search_load', '0'); - } - } - - return $load; - } - - /** - * Get current request method. - * - * @return string Request method, determined from $_SERVER['REQUEST_METHOD']. Specialchared, lowercase. - * @access protected - */ - protected function get_request_method() - { - return (isset($_SERVER['REQUEST_METHOD'])) ? strtolower(htmlspecialchars((string) $_SERVER['REQUEST_METHOD'])) : ''; - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/core/url.php b/phpBB/includes/core/url.php deleted file mode 100644 index c182998b87..0000000000 --- a/phpBB/includes/core/url.php +++ /dev/null @@ -1,740 +0,0 @@ -<?php -/** -* -* @package core -* @version $Id$ -* @copyright (c) 2008 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit(); -} - -/** -* Class responsible for URL handling, URL building, redirects, meta refreshs and session id handling. -* Basically everything url/sid-related. -* -* @package core -*/ -class phpbb_url extends phpbb_plugin_support -{ - /** - * @var array required phpBB objects - */ - public $phpbb_required = array('user', 'config'); - - /** - * @var array Optional phpBB objects - */ - public $phpbb_optional = array('template'); - - public function __construct() {} - - /** - * Checks if a path ($path) is absolute or relative - * - * @param string $path Path to check absoluteness of - * @return bool True if path is absolute - * @access public - */ - public function is_absolute($path) - { - return ($path[0] == '/' || (DIRECTORY_SEPARATOR == '\\' && preg_match('#^[a-z]:/#i', $path))) ? true : false; - } - - /** - * Mimic PHP realpath implementation - * - * @author Chris Smith <chris@project-minerva.org> - * @copyright 2006 Project Minerva Team - * @param string $path The path which we should attempt to resolve. - * @return mixed realpath - * @access private - */ - private function own_realpath($path) - { - // Switch to use UNIX slashes - $path = str_replace(DIRECTORY_SEPARATOR, '/', $path); - $path_prefix = ''; - - // Determine what sort of path we have - if ($this->is_absolute($path)) - { - $absolute = true; - - if ($path[0] == '/') - { - // Absolute path, *NIX style - $path_prefix = ''; - } - else - { - // Absolute path, Windows style - // Remove the drive letter and colon - $path_prefix = $path[0] . ':'; - $path = substr($path, 2); - } - } - else - { - // Relative Path - // Prepend the current working directory - if (function_exists('getcwd')) - { - // This is the best method, hopefully it is enabled! - $path = str_replace(DIRECTORY_SEPARATOR, '/', getcwd()) . '/' . $path; - $absolute = true; - if (preg_match('#^[a-z]:#i', $path)) - { - $path_prefix = $path[0] . ':'; - $path = substr($path, 2); - } - else - { - $path_prefix = ''; - } - } - else if (!empty($_SERVER['SCRIPT_FILENAME'])) - { - // Warning: If chdir() has been used this will lie! - // Warning: This has some problems sometime (CLI can create them easily) - $path = str_replace(DIRECTORY_SEPARATOR, '/', dirname($_SERVER['SCRIPT_FILENAME'])) . '/' . $path; - $absolute = true; - $path_prefix = ''; - } - else - { - // We have no way of getting the absolute path, just run on using relative ones. - $absolute = false; - $path_prefix = '.'; - } - } - - // Remove any repeated slashes - $path = preg_replace('#/{2,}#', '/', $path); - - // Remove the slashes from the start and end of the path - $path = trim($path, '/'); - - // Break the string into little bits for us to nibble on - $bits = explode('/', $path); - - // Remove any . in the path, renumber array for the loop below - $bits = array_values(array_diff($bits, array('.'))); - - // Lets get looping, run over and resolve any .. (up directory) - for ($i = 0, $max = sizeof($bits); $i < $max; $i++) - { - // @todo Optimise - if ($bits[$i] == '..' ) - { - if (isset($bits[$i - 1])) - { - if ($bits[$i - 1] != '..') - { - // We found a .. and we are able to traverse upwards, lets do it! - unset($bits[$i]); - unset($bits[$i - 1]); - $i -= 2; - $max -= 2; - $bits = array_values($bits); - } - } - else if ($absolute) // ie. !isset($bits[$i - 1]) && $absolute - { - // We have an absolute path trying to descend above the root of the filesystem - // ... Error! - return false; - } - } - } - - // Prepend the path prefix - array_unshift($bits, $path_prefix); - - $resolved = ''; - - $max = sizeof($bits) - 1; - - // Check if we are able to resolve symlinks, Windows cannot. - $symlink_resolve = (function_exists('readlink')) ? true : false; - - foreach ($bits as $i => $bit) - { - if (@is_dir("$resolved/$bit") || ($i == $max && @is_file("$resolved/$bit"))) - { - // Path Exists - if ($symlink_resolve && is_link("$resolved/$bit") && ($link = readlink("$resolved/$bit"))) - { - // Resolved a symlink. - $resolved = $link . (($i == $max) ? '' : '/'); - continue; - } - } - else - { - // Something doesn't exist here! - // This is correct realpath() behaviour but sadly open_basedir and safe_mode make this problematic - // return false; - } - $resolved .= $bit . (($i == $max) ? '' : '/'); - } - - // @todo If the file exists fine and open_basedir only has one path we should be able to prepend it - // because we must be inside that basedir, the question is where... - // @internal The slash in is_dir() gets around an open_basedir restriction - if (!@file_exists($resolved) || (!is_dir($resolved . '/') && !is_file($resolved))) - { - return false; - } - - // Put the slashes back to the native operating systems slashes - $resolved = str_replace('/', DIRECTORY_SEPARATOR, $resolved); - - // Check for DIRECTORY_SEPARATOR at the end (and remove it!) - if (substr($resolved, -1) == DIRECTORY_SEPARATOR) - { - return substr($resolved, 0, -1); - } - - // We got here, in the end! - return $resolved; - } - - /** - * A wrapper for realpath - * - * @param string $path The path which we should attempt to resolve. - * @staticvar string $_phpbb_realpath_exist This is set to false if the PHP function realpath() is not accessible or returns incorrect results - * - * @return string Real path - * @access public - */ - public function realpath($path) - { - static $_phpbb_realpath_exist; - - if (!isset($_phpbb_realpath_exist)) - { - $_phpbb_realpath_exist = (!function_exists('realpath')) ? false : true; - } - - if (!$_phpbb_realpath_exist) - { - return $this->own_realpath($path); - } - - $realpath = realpath($path); - - // Strangely there are provider not disabling realpath but returning strange values. :o - // We at least try to cope with them. - if ($realpath === $path || $realpath === false) - { - $_phpbb_realpath_exist = false; - return $this->own_realpath($path); - } - - // Check for DIRECTORY_SEPARATOR at the end (and remove it!) - if (substr($realpath, -1) == DIRECTORY_SEPARATOR) - { - $realpath = substr($realpath, 0, -1); - } - - return $realpath; - } - - /** - * URL wrapper - * All urls are run through this... either after {@link append_sid() append_sid} or directly - * - * @param string $url URL to process - * @return string URL - * @access public - */ - public function get($url) - { - return $url; - } - - /** - * Append session id to url. - * - * Examples: - * <code> - * append_sid(PHPBB_ROOT_PATH . 'viewtopic.' . PHP_EXT . '?t=1&f=2'); // VALID - * append_sid(PHPBB_ROOT_PATH . 'viewtopic.' . PHP_EXT, 't=1&f=2'); // VALID - * append_sid('viewtopic', 't=1&f=2'); // short notation of the above example - VALID - * append_sid('viewtopic', 't=1&f=2', false); // Instead of & use & - * append_sid('viewtopic', array('t' => 1, 'f' => 2)); // Instead of parameter in string notation, use an array - * </code> - * - * @param string $url The url the session id needs to be appended to (without parameter) - * @param string|array $params String or array of additional url parameter. - * @param bool $is_amp Is url using & (true) or & (false) - * @param string $session_id Possibility to use a custom session id instead of the global one. This also forces the use of a session id. - * - * @plugin-support default, return - * @return string URL - * @access public - */ - public function append_sid($url, $params = false, $is_amp = true, $session_id = false) - { - static $parsed_urls = array(); - - // The following code is used to make sure such calls like append_sid('viewtopic') (ommitting phpbb_root_path and php_ext) work as intended - if (isset($parsed_urls[$url])) - { - // Set an url like 'viewtopic' to PHPBB_ROOT_PATH . 'viewtopic.' . PHP_EXT - $url = $parsed_urls[$url]; - } - else - { - // If we detect an url without root path and extension, and also not a relative or absolute path, we add it and put it to the parsed urls - if (strpos($url, '.' . PHP_EXT) === false && $url[0] != '.' && $url[0] != '/') - { - $parsed_urls[$url] = $url = PHPBB_ROOT_PATH . $url . '.' . PHP_EXT; - } - } - - if (empty($params)) - { - $params = false; - } - - $params_is_array = is_array($params); - - // Get anchor - $anchor = ''; - if (strpos($url, '#') !== false) - { - list($url, $anchor) = explode('#', $url, 2); - $anchor = '#' . $anchor; - } - else if (!$params_is_array && strpos($params, '#') !== false) - { - list($params, $anchor) = explode('#', $params, 2); - $anchor = '#' . $anchor; - } - - // Handle really simple cases quickly - if ($session_id === false && !phpbb::$user->need_sid && empty(phpbb::$user->extra_url) && !$params_is_array && !$anchor) - { - if ($params === false) - { - return $this->get($url); - } - - $url_delim = (strpos($url, '?') === false) ? '?' : (($is_amp) ? '&' : '&'); - return $this->get($url . ($params !== false ? $url_delim . $params : '')); - } - - // Assign sid if session id is not specified - if (phpbb::$user->need_sid && $session_id === false) - { - $session_id = phpbb::$user->session_id; - } - - $amp_delim = ($is_amp) ? '&' : '&'; - $url_delim = (strpos($url, '?') === false) ? '?' : $amp_delim; - - // Appending custom url parameter? - $append_url = (!empty(phpbb::$user->extra_url)) ? implode($amp_delim, phpbb::$user->extra_url) : ''; - - if ($this->method_inject(__FUNCTION__)) $this->call_inject(__FUNCTION__, array('default', &$url, &$params, &$session_id, &$append_url, &$anchor, &$amp_delim, &$url_delim)); - - if ($this->method_inject(__FUNCTION__, 'return')) - { - $url = $this->call_inject(__FUNCTION__, array('return', $url, $params, $session_id, $append_url, $anchor, $amp_delim, $url_delim)); - return $this->get($url); - } - - // Use the short variant if possible ;) - if ($params === false) - { - // Append session id - if (!$session_id) - { - return $this->get($url . (($append_url) ? $url_delim . $append_url : '') . $anchor); - } - else - { - return $this->get($url . (($append_url) ? $url_delim . $append_url . $amp_delim : $url_delim) . 'sid=' . $session_id . $anchor); - } - } - - // Build string if parameters are specified as array - if ($params_is_array) - { - $output = array(); - - foreach ($params as $key => $item) - { - if ($item === NULL) - { - continue; - } - - if ($key == '#') - { - $anchor = '#' . $item; - continue; - } - - $output[] = $key . '=' . $item; - } - - $params = implode($amp_delim, $output); - } - - // Append session id and parameter - return $this->get($url . (($append_url) ? $url_delim . $append_url : '') . (($params) ? (($append_url) ? $amp_delim : $url_delim) . $params : '') . ((!$session_id) ? '' : $amp_delim . 'sid=' . $session_id) . $anchor); - } - - /** - * Generate board url (example: http://www.example.com/phpBB) - * - * @param bool $without_script_path If set to true the script path gets not appended (example: http://www.example.com instead of http://www.example.com/phpBB) - * @return string Board URL - * @access public - */ - public function generate_board_url($without_script_path = false) - { - $server_name = phpbb::$user->system['host']; - $server_port = phpbb::$user->system['port']; - - // Forcing server vars is the only way to specify/override the protocol - if (phpbb::$config['force_server_vars'] || !$server_name) - { - $server_protocol = (phpbb::$config['server_protocol']) ? phpbb::$config['server_protocol'] : ((phpbb::$config['cookie_secure']) ? 'https://' : 'http://'); - $server_name = phpbb::$config['server_name']; - $server_port = (int) phpbb::$config['server_port']; - $script_path = phpbb::$config['script_path']; - - $url = $server_protocol . $server_name; - $cookie_secure = phpbb::$config['cookie_secure']; - } - else - { - // Do not rely on cookie_secure, users seem to think that it means a secured cookie instead of an encrypted connection - $cookie_secure = (isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] == 'on') ? 1 : 0; - $url = (($cookie_secure) ? 'https://' : 'http://') . $server_name; - - $script_path = phpbb::$user->page['root_script_path']; - } - - if ($server_port && (($cookie_secure && $server_port <> 443) || (!$cookie_secure && $server_port <> 80))) - { - // HTTP HOST can carry a port number (we fetch $user->system['host'], but for old versions this may be true) - if (strpos($server_name, ':') === false) - { - $url .= ':' . $server_port; - } - } - - if (!$without_script_path) - { - $url .= $script_path; - } - - // Strip / from the end - if (substr($url, -1, 1) == '/') - { - $url = substr($url, 0, -1); - } - - return $url; - } - - /** - * Redirects the user to another page then exits the script nicely - * This function is intended for urls within the board. It's not meant to redirect to cross-domains. - * - * @param string $url The url to redirect to - * @param bool $return If true, do not redirect but return the sanitized URL. - * @param bool $disable_cd_check If true, redirect() will support redirects to an external domain. - * If false, the redirect points to the boards url if it does not match the current domain. - * - * @return mixed Sanitized URL if $return is true - * @access public - */ - public function redirect($url, $return = false, $disable_cd_check = false) - { - if (empty(phpbb::$user->lang)) - { - phpbb::$user->add_lang('common'); - } - - if (!$return) - { - garbage_collection(); - } - - // Make sure no &'s are in, this will break the redirect - $url = str_replace('&', '&', $url); - - // Determine which type of redirect we need to handle... - $url_parts = parse_url($url); - - if ($url_parts === false) - { - // Malformed url, redirect to current page... - $url = $this->generate_board_url() . '/' . phpbb::$user->page['page']; - } - else if (!empty($url_parts['scheme']) && !empty($url_parts['host'])) - { - // Attention: only able to redirect within the same domain if $disable_cd_check is false (yourdomain.com -> www.yourdomain.com will not work) - if (!$disable_cd_check && $url_parts['host'] !== phpbb::$user->system['host']) - { - $url = $this->generate_board_url(); - } - } - else if ($url[0] == '/') - { - // Absolute uri, prepend direct url... - $url = $this->generate_board_url(true) . $url; - } - else - { - // Relative uri - $pathinfo = pathinfo($url); - - // Is the uri pointing to the current directory? - if ($pathinfo['dirname'] == '.') - { - $url = str_replace('./', '', $url); - - // Strip / from the beginning - if ($url && substr($url, 0, 1) == '/') - { - $url = substr($url, 1); - } - - if (phpbb::$user->page['page_dir']) - { - $url = $this->generate_board_url() . '/' . phpbb::$user->page['page_dir'] . '/' . $url; - } - else - { - $url = $this->generate_board_url() . '/' . $url; - } - } - else - { - // Used ./ before, but PHPBB_ROOT_PATH is working better with urls within another root path - $root_dirs = explode('/', str_replace('\\', '/', $this->realpath(PHPBB_ROOT_PATH))); - $page_dirs = explode('/', str_replace('\\', '/', $this->realpath($pathinfo['dirname']))); - $intersection = array_intersect_assoc($root_dirs, $page_dirs); - - $root_dirs = array_diff_assoc($root_dirs, $intersection); - $page_dirs = array_diff_assoc($page_dirs, $intersection); - - $dir = str_repeat('../', sizeof($root_dirs)) . implode('/', $page_dirs); - - // Strip / from the end - if ($dir && substr($dir, -1, 1) == '/') - { - $dir = substr($dir, 0, -1); - } - - // Strip / from the beginning - if ($dir && substr($dir, 0, 1) == '/') - { - $dir = substr($dir, 1); - } - - $url = str_replace($pathinfo['dirname'] . '/', '', $url); - - // Strip / from the beginning - if (substr($url, 0, 1) == '/') - { - $url = substr($url, 1); - } - - $url = (!empty($dir) ? $dir . '/' : '') . $url; - $url = $this->generate_board_url() . '/' . $url; - } - } - - // Make sure no linebreaks are there... to prevent http response splitting for PHP < 4.4.2 - if (strpos(urldecode($url), "\n") !== false || strpos(urldecode($url), "\r") !== false || strpos($url, ';') !== false) - { - trigger_error('Tried to redirect to potentially insecure url.', E_USER_ERROR); - } - - // Now, also check the protocol and for a valid url the last time... - $allowed_protocols = array('http', 'https', 'ftp', 'ftps'); - $url_parts = parse_url($url); - - if ($url_parts === false || empty($url_parts['scheme']) || !in_array($url_parts['scheme'], $allowed_protocols)) - { - trigger_error('Tried to redirect to potentially insecure url.', E_USER_ERROR); - } - - if ($return) - { - return $url; - } - - // Redirect via an HTML form for PITA webservers - if (@preg_match('#Microsoft|WebSTAR|Xitami#', getenv('SERVER_SOFTWARE'))) - { - header('Refresh: 0; URL=' . $url); - - echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'; - echo '<html xmlns="http://www.w3.org/1999/xhtml" dir="' . phpbb::$user->lang['DIRECTION'] . '" lang="' . phpbb::$user->lang['USER_LANG'] . '" xml:lang="' . phpbb::$user->lang['USER_LANG'] . '">'; - echo '<head>'; - echo '<meta http-equiv="content-type" content="text/html; charset=utf-8" />'; - echo '<meta http-equiv="refresh" content="0; url=' . str_replace('&', '&', $url) . '" />'; - echo '<title>' . phpbb::$user->lang['REDIRECT'] . '</title>'; - echo '</head>'; - echo '<body>'; - echo '<div style="text-align: center;">' . phpbb::$user->lang('URL_REDIRECT', '<a href="' . str_replace('&', '&', $url) . '">', '</a>') . '</div>'; - echo '</body>'; - echo '</html>'; - - exit; - } - - // Behave as per HTTP/1.1 spec for others - header('Location: ' . $url); - exit; - } - - /** - * Meta refresh assignment - * - * If the template object is present, the META template variable holds the meta refresh, else a normal redirect is done. - * - * @param int $time The time in seconds when to redirect - * @param string $url The URL to redirect to - * @param bool $disable_cd_check If true, redirect() will support redirects to an external domain. - * If false, the redirect points to the boards url if it does not match the current domain. - * - * @return string Sanitized URL - * @plugin-support return - * @access public - */ - public function meta_refresh($time, $url, $disable_cd_check = false) - { - if (phpbb::registered('template')) - { - $result_url = $this->redirect($url, true, $disable_cd_check); - $result_url = str_replace('&', '&', $result_url); - - // For XHTML compatibility we change back & to & - phpbb::$template->assign_var('META', '<meta http-equiv="refresh" content="' . $time . ';url=' . $result_url . '" />'); - } - else - { - $this->redirect($url, false, $disable_cd_check); - } - - return ($this->method_inject(__FUNCTION__, 'return')) ? $this->call_inject(__FUNCTION__, array('return', $result_url, $time, $url, $disable_cd_check)) : $result_url; - } - - /** - * Re-Apply session id after page reloads - * - * @param string $url URL to re-apply session id to - * @return string URL with re-applied session id - * @access public - */ - public function reapply_sid($url) - { - if ($url === 'index.' . PHP_EXT) - { - return $this->append_sid('index.' . PHP_EXT); - } - else if ($url === PHPBB_ROOT_PATH . 'index.' . PHP_EXT) - { - return $this->append_sid('index'); - } - - // Remove previously added sid - if (strpos($url, '?sid=') !== false) - { - $url = preg_replace('/(\?)sid=[a-z0-9]+(&|&)?/', '\1', $url); - } - else if (strpos($url, '&sid=') !== false) - { - $url = preg_replace('/&sid=[a-z0-9]+(&)?/', '\1', $url); - } - else if (strpos($url, '&sid=') !== false) - { - $url = preg_replace('/&sid=[a-z0-9]+(&)?/', '\1', $url); - } - - return $this->append_sid($url); - } - - /** - * Returns url from the session/current page with an re-appended SID with optionally stripping vars from the url - * - * @param array|string $strip_vars An array containing variables to be stripped from the URL. - * @return string Current page URL with re-applied SID and optionally stripped parameter - * @access public - */ - public function build_url($strip_vars = false) - { - // Append SID - $redirect = $this->append_sid(phpbb::$user->page['page'], false, false); - - // Add delimiter if not there... - if (strpos($redirect, '?') === false) - { - $redirect .= '?'; - } - - // Strip vars... - if ($strip_vars !== false && strpos($redirect, '?') !== false) - { - if (!is_array($strip_vars)) - { - $strip_vars = array($strip_vars); - } - - $query = $_query = array(); - - $args = substr($redirect, strpos($redirect, '?') + 1); - $args = ($args) ? explode('&', $args) : array(); - $redirect = substr($redirect, 0, strpos($redirect, '?')); - - foreach ($args as $argument) - { - $arguments = explode('=', $argument); - $key = $arguments[0]; - unset($arguments[0]); - - $query[$key] = implode('=', $arguments); - } - - // Strip the vars off - foreach ($strip_vars as $strip) - { - if (isset($query[$strip])) - { - unset($query[$strip]); - } - } - - // Glue the remaining parts together... already urlencoded - foreach ($query as $key => $value) - { - $_query[] = $key . '=' . $value; - } - $query = implode('&', $_query); - - $redirect .= ($query) ? '?' . $query : ''; - } - - return PHPBB_ROOT_PATH . str_replace('&', '&', $redirect); - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/db2.php b/phpBB/includes/db/db2.php deleted file mode 100644 index 87210d6534..0000000000 --- a/phpBB/includes/db/db2.php +++ /dev/null @@ -1,455 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2009 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* MSSQL Database Abstraction Layer -* Minimum Requirement: DB2 8.2.2+ -* Minimum extension version: PECL ibm_db2 1.6.0+ -* @package dbal -*/ -class phpbb_dbal_db2 extends phpbb_dbal -{ - /** - * @var string Database type. No distinction between versions or used extensions. - */ - public $dbms_type = 'db2'; - - /** - * @var array Database type map, column layout information - */ - public $dbms_type_map = array( - 'INT:' => 'integer', - 'BINT' => 'float', - 'UINT' => 'integer', - 'UINT:' => 'integer', - 'TINT:' => 'smallint', - 'USINT' => 'smallint', - 'BOOL' => 'smallint', - 'VCHAR' => 'varchar(255)', - 'VCHAR:' => 'varchar(%d)', - 'CHAR:' => 'char(%d)', - 'XSTEXT' => 'clob(65K)', - 'STEXT' => 'varchar(3000)', - 'TEXT' => 'clob(65K)', - 'MTEXT' => 'clob(16M)', - 'XSTEXT_UNI'=> 'varchar(100)', - 'STEXT_UNI' => 'varchar(255)', - 'TEXT_UNI' => 'clob(65K)', - 'MTEXT_UNI' => 'clob(16M)', - 'TIMESTAMP' => 'integer', - 'DECIMAL' => 'float', - 'VCHAR_UNI' => 'varchar(255)', - 'VCHAR_UNI:'=> 'varchar(%d)', - 'VARBINARY' => 'varchar(255)', - ); - - /** - * @var array Database features - */ - public $features = array( - 'multi_insert' => true, - 'count_distinct' => true, - 'multi_table_deletion' => true, - 'truncate' => false, - ); - - /** - * Connect to server. See {@link phpbb_dbal::sql_connect() sql_connect()} for details. - */ - public function sql_connect($server, $user, $password, $database, $port = false, $persistency = false , $new_link = false) - { - $this->persistency = $persistency; - $this->user = $user; - $this->server = $server . (($port) ? ':' . $port : ''); - $this->dbname = $database; - $this->port = $port; - - $this->db_connect_id = ($this->persistency) ? @db2_pconnect($this->dbname, $this->user, $password, array('autocommit' => DB2_AUTOCOMMIT_ON, 'DB2_ATTR_CASE' => DB2_CASE_LOWER)) : @db2_connect($this->dbname, $this->user, $password, array('autocommit' => DB2_AUTOCOMMIT_ON, 'DB2_ATTR_CASE' => DB2_CASE_LOWER)); - - return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); - } - - /** - * Version information about used database. See {@link phpbb_dbal::sql_server_info() sql_server_info()} for details. - */ - public function sql_server_info($raw = false) - { - if (!phpbb::registered('acm') || ($this->sql_server_version = phpbb::$acm->get('#db2_version')) === false) - { - $info = @db2_server_info($this->db_connect_id); - - $this->sql_server_info = is_object($info) ? $info->DBMS_VER : 0; - - if (phpbb::registered('acm')) - { - phpbb::$acm->put('#db2_version', $this->sql_server_version); - } - } - - return ($raw) ? $this->sql_server_version : 'IBM DB2 ' . $this->sql_server_version; - } - - /** - * DB-specific base query method. See {@link phpbb_dbal::_sql_query() _sql_query()} for details. - */ - protected function _sql_query($query) - { - $array = array(); - - // Cope with queries larger than 32K - if (strlen($query) > 32740) - { - if (preg_match('/^(INSERT INTO[^(]++)\\(([^()]+)\\) VALUES[^(]++\\((.*?)\\)$/s', $query, $regs)) - { - if (strlen($regs[3]) > 32740) - { - preg_match_all('/\'(?:[^\']++|\'\')*+\'|[\d-.]+/', $regs[3], $vals, PREG_PATTERN_ORDER); - - $inserts = $vals[0]; - unset($vals); - - foreach ($inserts as $key => $value) - { - // check to see if this thing is greater than the max + 'x2 - if (!empty($value) && $value[0] === "'" && strlen($value) > 32742) - { - $inserts[$key] = '?'; - $array[] = str_replace("''", "'", substr($value, 1, -1)); - } - } - - $query = $regs[1] . '(' . $regs[2] . ') VALUES (' . implode(', ', $inserts) . ')'; - } - } - else if (preg_match_all('/^(UPDATE ([\\w_]++)\\s+SET )([\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+)(?:,\\s*[\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+))*+)\\s+(WHERE.*)$/s', $query, $data, PREG_SET_ORDER)) - { - if (strlen($data[0][3]) > 32740) - { - $update = $data[0][1]; - $where = $data[0][4]; - preg_match_all('/(\\w++) = (\'(?:[^\']++|\'\')*+\'|\\d++)/', $data[0][3], $temp, PREG_SET_ORDER); - unset($data); - - $cols = array(); - foreach ($temp as $value) - { - // check to see if this thing is greater than the max + 'x2 - if (!empty($value[2]) && $value[2][0] === "'" && strlen($value[2]) > 32742) - { - $array[] = str_replace("''", "'", substr($value[2], 1, -1)); - $cols[] = $value[1] . '=?'; - } - else - { - $cols[] = $value[1] . '=' . $value[2]; - } - } - - $query = $update . implode(', ', $cols) . ' ' . $where; - unset($cols); - } - } - } - - if (sizeof($array)) - { - $result = @db2_prepare($this->db_connect_id, $query); - - if (!$result) - { - return false; - } - - if (!@db2_execute($result, $array)) - { - return false; - } - } - else - { - $result = @db2_exec($this->db_connect_id, $query); - } - - return $result; - } - - /** - * Build LIMIT query and run it. See {@link phpbb_dbal::_sql_query_limit() _sql_query_limit()} for details. - */ - protected function _sql_query_limit($query, $total, $offset, $cache_ttl) - { - if ($total && $offset == 0) - { - return $this->sql_query($query . ' fetch first ' . $total . ' rows only', $cache_ttl); - } - - // Seek by $offset rows - if ($offset) - { - $limit_sql = 'SELECT a2.* - FROM ( - SELECT ROW_NUMBER() OVER() AS rownum, a1.* - FROM ( - ' . $query . ' - ) a1 - ) a2 - WHERE a2.rownum BETWEEN ' . ($offset + 1) . ' AND ' . ($offset + $total); - - return $this->sql_query($limit_sql, $cache_ttl); - } - - return $this->sql_query($query, $cache_ttl); - } - - /** - * Close sql connection. See {@link phpbb_dbal::_sql_close() _sql_close()} for details. - */ - protected function _sql_close() - { - return @db2_close($this->db_connect_id); - } - - /** - * SQL Transaction. See {@link phpbb_dbal::_sql_transaction() _sql_transaction()} for details. - */ - protected function _sql_transaction($status) - { - switch ($status) - { - case 'begin': - return @db2_autocommit($this->db_connect_id, DB2_AUTOCOMMIT_OFF); - break; - - case 'commit': - $result = @db2_commit($this->db_connect_id); - @db2_autocommit($this->db_connect_id, DB2_AUTOCOMMIT_ON); - return $result; - break; - - case 'rollback': - $result = @db2_rollback($this->db_connect_id); - @db2_autocommit($this->db_connect_id, DB2_AUTOCOMMIT_ON); - return $result; - break; - } - - return true; - } - - /** - * Return number of affected rows. See {@link phpbb_dbal::sql_affectedrows() sql_affectedrows()} for details. - */ - public function sql_affectedrows() - { - return ($this->db_connect_id) ? @db2_num_rows($this->db_connect_id) : false; - } - - /** - * Get last inserted id after insert statement. See {@link phpbb_dbal::sql_nextid() sql_nextid()} for details. - */ - public function sql_nextid() - { - if (function_exists('db2_last_insert_id')) - { - return @db2_last_insert_id($this->db_connect_id); - } - - $result_id = @db2_exec($this->db_connect_id, 'VALUES IDENTITY_VAL_LOCAL()'); - - if ($result_id) - { - if ($row = @db2_fetch_assoc($result_id)) - { - @db2_free_result($result_id); - return (int) $row[1]; - } - @db2_free_result($result_id); - } - - return false; - } - - /** - * Fetch current row. See {@link phpbb_dbal::_sql_fetchrow() _sql_fetchrow()} for details. - */ - protected function _sql_fetchrow($query_id) - { - return @db2_fetch_assoc($query_id); - } - - /** - * Free query result. See {@link phpbb_dbal::_sql_freeresult() _sql_freeresult()} for details. - */ - protected function _sql_freeresult($query_id) - { - return @db2_free_result($query_id); - } - - /** - * Correctly adjust LIKE expression for special characters. See {@link phpbb_dbal::_sql_like_expression() _sql_like_expression()} for details. - */ - protected function _sql_like_expression($expression) - { - return $expression . " ESCAPE '\\'"; - } - - /** - * Escape string used in sql query. See {@link phpbb_dbal::sql_escape() sql_escape()} for details. - */ - public function sql_escape($msg) - { - return @db2_escape_string($msg); - } - - /** - * Expose a DBMS specific function. See {@link phpbb_dbal::sql_function() sql_function()} for details. - */ - public function sql_function($type, $col) - { - switch ($type) - { - case 'length_varchar': - case 'length_text': - return 'LENGTH(' . $col . ')'; - break; - } - } - - /** - * Handle data by using prepared statements. See {@link phpbb_dbal::sql_handle_data() sql_handle_data()} for details. - public function sql_handle_data($type, $table, $data, $where = '') - { - if ($type == 'INSERT') - { - $stmt = db2_prepare($this->db_connect_id, "INSERT INTO $table (". implode(', ', array_keys($data)) . ") VALUES (" . substr(str_repeat('?, ', sizeof($data)) ,0, -1) . ')'); - } - else - { - $query = "UPDATE $table SET "; - - $set = array(); - foreach (array_keys($data) as $key) - { - $set[] = "$key = ?"; - } - $query .= implode(', ', $set); - - if ($where !== '') - { - $query .= $where; - } - - $stmt = db2_prepare($this->db_connect_id, $query); - } - - // get the stmt onto the top of the function arguments - array_unshift($data, $stmt); - - call_user_func_array('db2_execute', $data); - } - */ - - /** - * Build DB-specific query bits. See {@link phpbb_dbal::_sql_custom_build() _sql_custom_build()} for details. - */ - protected function _sql_custom_build($stage, $data) - { - return $data; - } - - /** - * return sql error array. See {@link phpbb_dbal::_sql_error() _sql_error()} for details. - */ - protected function _sql_error() - { - $message = @db2_stmt_errormsg(); - $code = @db2_stmt_error(); - - if (!$message && !$code) - { - $message = @db2_conn_errormsg(); - $code = @db2_conn_error(); - } - - $error = array( - 'message' => $message, - 'code' => $code, - ); - - return $error; - } - - /** - * Run DB-specific code to build SQL Report to explain queries, show statistics and runtime information. See {@link phpbb_dbal::_sql_report() _sql_report()} for details. - */ - protected function _sql_report($mode, $query = '') - { - switch ($mode) - { - case 'start': - - $html_table = false; - @db2_exec($this->db_connect_id, 'DELETE FROM EXPLAIN_INSTANCE'); - @db2_exec($this->db_connect_id, 'EXPLAIN PLAN FOR ' . $query); - - // Get the data from the plan - $sql = "SELECT O.Operator_ID, S2.Target_ID, O.Operator_Type, S.Object_Name, CAST(O.Total_Cost AS INTEGER) Cost - FROM EXPLAIN_OPERATOR O - LEFT OUTER JOIN EXPLAIN_STREAM S2 ON O.Operator_ID = S2.Source_ID - LEFT OUTER JOIN EXPLAIN_STREAM S ON O.Operator_ID = S.Target_ID AND O.Explain_Time = S.Explain_Time AND S.Object_Name IS NOT NULL - ORDER BY O.Explain_Time ASC, Operator_ID ASC"; - $query_id = @db2_exec($this->db_connect_id, $sql); - - if ($query_id) - { - while ($row = @db2_fetch_assoc($query_id)) - { - $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); - } - - @db2_free_result($query_id); - } - - if ($html_table) - { - $this->html_hold .= '</table>'; - } - break; - - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @db2_exec($this->db_connect_id, $query); - while ($void = @db2_fetch_assoc($result, IBASE_TEXT)) - { - // Take the time spent on parsing rows into account - } - @db2_free_result($result); - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/db_tools.php b/phpBB/includes/db/db_tools.php deleted file mode 100644 index 32ee807952..0000000000 --- a/phpBB/includes/db/db_tools.php +++ /dev/null @@ -1,1707 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2007 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Database Tools for handling cross-db actions such as altering columns, etc. -* -* @package dbal -*/ -class phpbb_db_tools -{ - /** - * @var object DB object - */ - public $db = NULL; - - /** - * A list of types being unsigned for better reference in some db's - * @var array - */ - public $unsigned_types = array('UINT', 'UINT:', 'USINT', 'BOOL', 'TIMESTAMP'); - - /** - * A list of supported DBMS. We change this class to support more DBMS, the DBMS itself only need to follow some rules. - * @var array - */ - public $supported_dbms = array('mysql', 'mssql', 'sqlite', 'oracle', 'firebird', 'db2', 'postgres'); - - /** - * This is set to true if user only wants to return the 'to-be-executed' SQL statement(s) (as an array). - * This mode has no effect on some methods (inserting of data for example). This is expressed within the methods command. - */ - public $return_statements = false; - - /** - * Constructor. Set DB Object and set {@link $return_statements return_statements}. - * - * @param phpbb_dbal $db DBAL object - * @param bool $return_statements True if only statements should be returned and no SQL being executed - */ - public function __construct(phpbb_dbal $db, $return_statements = false) - { - $this->db = $db; - $this->return_statements = $return_statements; - - if (!in_array($this->db->dbms_type, $this->supported_dbms)) - { - trigger_error('DBMS Type ' . $this->db->dbms_type . ' not supported by DB Tools.', E_USER_ERROR); - } - } - - /** - * Create SQL Table - * - * @param string $table_name The table name to create - * @param array $table_data Array containing table data. For a sample layout see {@example } - * @return array Statements if $return_statements is true. - */ - public function sql_create_table($table_name, $table_data) - { - // holds the DDL for a column - $columns = $statements = array(); - - // Begin transaction - $statements[] = 'begin'; - - // Determine if we have created a PRIMARY KEY in the earliest - $primary_key_gen = false; - - // Determine if the table must be created with TEXTIMAGE - $create_textimage = false; - - // Determine if the table requires a sequence - $create_sequence = false; - - // Begin table sql statement - switch ($this->sql_layer) - { - case 'mssql': - $table_sql = 'CREATE TABLE [' . $table_name . '] (' . "\n"; - break; - - default: - $table_sql = 'CREATE TABLE ' . $table_name . ' (' . "\n"; - break; - } - - // Iterate through the columns to create a table - foreach ($table_data['COLUMNS'] as $column_name => $column_data) - { - // here lies an array, filled with information compiled on the column's data - $prepared_column = $this->sql_prepare_column_data($table_name, $column_name, $column_data); - - // here we add the definition of the new column to the list of columns - switch ($this->sql_layer) - { - case 'mssql': - $columns[] = "\t [{$column_name}] " . $prepared_column['column_type_sql_default']; - break; - - default: - $columns[] = "\t {$column_name} " . $prepared_column['column_type_sql']; - break; - } - - // see if we have found a primary key set due to a column definition if we have found it, we can stop looking - if (!$primary_key_gen) - { - $primary_key_gen = isset($prepared_column['primary_key_set']) && $prepared_column['primary_key_set']; - } - - // create textimage DDL based off of the existance of certain column types - if (!$create_textimage) - { - $create_textimage = isset($prepared_column['textimage']) && $prepared_column['textimage']; - } - - // create sequence DDL based off of the existance of auto incrementing columns - if (!$create_sequence && isset($prepared_column['auto_increment']) && $prepared_column['auto_increment']) - { - $create_sequence = $column_name; - } - } - - // this makes up all the columns in the create table statement - $table_sql .= implode(",\n", $columns); - - // Close the table for two DBMS and add to the statements - switch ($this->db->dbms_type) - { - case 'firebird': - $table_sql .= "\n);"; - $statements[] = $table_sql; - break; - - case 'mssql': - $table_sql .= "\n) ON [PRIMARY]" . (($create_textimage) ? ' TEXTIMAGE_ON [PRIMARY]' : ''); - $statements[] = $table_sql; - break; - } - - // we have yet to create a primary key for this table, - // this means that we can add the one we really wanted instead - if (!$primary_key_gen) - { - // Write primary key - if (isset($table_data['PRIMARY_KEY'])) - { - if (!is_array($table_data['PRIMARY_KEY'])) - { - $table_data['PRIMARY_KEY'] = array($table_data['PRIMARY_KEY']); - } - - switch ($this->db->dbms_type) - { - case 'mysql': - case 'postgres': - case 'db2': - case 'sqlite': - $table_sql .= ",\n\t PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')'; - break; - - case 'firebird': - case 'mssql': - $primary_key_stmts = $this->sql_create_primary_key($table_name, $table_data['PRIMARY_KEY']); - foreach ($primary_key_stmts as $pk_stmt) - { - $statements[] = $pk_stmt; - } - break; - - case 'oracle': - $table_sql .= ",\n\t CONSTRAINT pk_{$table_name} PRIMARY KEY (" . implode(', ', $table_data['PRIMARY_KEY']) . ')'; - break; - } - } - } - - // close the table - switch ($this->db->dbms_type) - { - case 'mysql': - // make sure the table is in UTF-8 mode - $table_sql .= "\n) CHARACTER SET `utf8` COLLATE `utf8_bin`;"; - $statements[] = $table_sql; - break; - - case 'postgres': - // do we need to add a sequence for auto incrementing columns? - if ($create_sequence) - { - $statements[] = "CREATE SEQUENCE {$table_name}_seq;"; - } - - $table_sql .= "\n);"; - $statements[] = $table_sql; - break; - - case 'db2': - case 'sqlite': - $table_sql .= "\n);"; - $statements[] = $table_sql; - break; - - case 'oracle': - $table_sql .= "\n);"; - $statements[] = $table_sql; - - // do we need to add a sequence and a tigger for auto incrementing columns? - if ($create_sequence) - { - // create the actual sequence - $statements[] = "CREATE SEQUENCE {$table_name}_seq"; - - // the trigger is the mechanism by which we increment the counter - $trigger = "CREATE OR REPLACE TRIGGER t_{$table_name}\n"; - $trigger .= "BEFORE INSERT ON {$table_name}\n"; - $trigger .= "FOR EACH ROW WHEN (\n"; - $trigger .= "\tnew.{$create_sequence} IS NULL OR new.{$create_sequence} = 0\n"; - $trigger .= ")\n"; - $trigger .= "BEGIN\n"; - $trigger .= "\tSELECT {$table_name}_seq.nextval\n"; - $trigger .= "\tINTO :new.{$create_sequence}\n"; - $trigger .= "\tFROM dual\n"; - $trigger .= "END;"; - - $statements[] = $trigger; - } - break; - - case 'firebird': - if ($create_sequence) - { - $statements[] = "CREATE SEQUENCE {$table_name}_seq;"; - } - break; - } - - // Write Keys - if (isset($table_data['KEYS'])) - { - foreach ($table_data['KEYS'] as $key_name => $key_data) - { - if (!is_array($key_data[1])) - { - $key_data[1] = array($key_data[1]); - } - - $old_return_statements = $this->return_statements; - $this->return_statements = true; - - $key_stmts = ($key_data[0] == 'UNIQUE') ? $this->sql_create_unique_index($table_name, $key_name, $key_data[1]) : $this->sql_create_index($table_name, $key_name, $key_data[1]); - - foreach ($key_stmts as $key_stmt) - { - $statements[] = $key_stmt; - } - - $this->return_statements = $old_return_statements; - } - } - - // Commit Transaction - $statements[] = 'commit'; - - return $this->_sql_run_sql($statements); - } - - /** - * Handle passed database update array. Update table schema. - * - * Key being one of the following - * <pre> - * change_columns - Column changes (only type, not name) - * add_columns - Add columns to a table - * drop_keys - Dropping keys - * drop_columns - Removing/Dropping columns - * add_primary_keys - adding primary keys - * add_unique_index - adding an unique index - * add_index - adding an index - * </pre> - * - * For a complete definition of the layout please see {@example } - * - * @param array $schema_changes The schema array - */ - public function sql_schema_changes($schema_changes) - { - if (empty($schema_changes)) - { - return; - } - - $statements = array(); - - // Change columns? - if (!empty($schema_changes['change_columns'])) - { - foreach ($schema_changes['change_columns'] as $table => $columns) - { - foreach ($columns as $column_name => $column_data) - { - // If the column exists we change it, else we add it ;) - if ($this->sql_column_exists($table, $column_name)) - { - $result = $this->sql_column_change($table, $column_name, $column_data); - } - else - { - $result = $this->sql_column_add($table, $column_name, $column_data); - } - - if ($this->return_statements) - { - $statements = array_merge($statements, $result); - } - } - } - } - - // Add columns? - if (!empty($schema_changes['add_columns'])) - { - foreach ($schema_changes['add_columns'] as $table => $columns) - { - foreach ($columns as $column_name => $column_data) - { - // Only add the column if it does not exist yet, else change it (to be consistent) - if ($this->sql_column_exists($table, $column_name)) - { - $result = $this->sql_column_change($table, $column_name, $column_data); - } - else - { - $result = $this->sql_column_add($table, $column_name, $column_data); - } - - if ($this->return_statements) - { - $statements = array_merge($statements, $result); - } - } - } - } - - // Remove keys? - if (!empty($schema_changes['drop_keys'])) - { - foreach ($schema_changes['drop_keys'] as $table => $indexes) - { - foreach ($indexes as $index_name) - { - $result = $this->sql_index_drop($table, $index_name); - - if ($this->return_statements) - { - $statements = array_merge($statements, $result); - } - } - } - } - - // Drop columns? - if (!empty($schema_changes['drop_columns'])) - { - foreach ($schema_changes['drop_columns'] as $table => $columns) - { - foreach ($columns as $column) - { - // Only remove the column if it exists... - if ($this->sql_column_exists($table, $column)) - { - $result = $this->sql_column_remove($table, $column); - - if ($this->return_statements) - { - $statements = array_merge($statements, $result); - } - } - } - } - } - - // Add primary keys? - if (!empty($schema_changes['add_primary_keys'])) - { - foreach ($schema_changes['add_primary_keys'] as $table => $columns) - { - $result = $this->sql_create_primary_key($table, $columns); - - if ($this->return_statements) - { - $statements = array_merge($statements, $result); - } - } - } - - // Add unqiue indexes? - if (!empty($schema_changes['add_unique_index'])) - { - foreach ($schema_changes['add_unique_index'] as $table => $index_array) - { - foreach ($index_array as $index_name => $column) - { - $result = $this->sql_create_unique_index($table, $index_name, $column); - - if ($this->return_statements) - { - $statements = array_merge($statements, $result); - } - } - } - } - - // Add indexes? - if (!empty($schema_changes['add_index'])) - { - foreach ($schema_changes['add_index'] as $table => $index_array) - { - foreach ($index_array as $index_name => $column) - { - $result = $this->sql_create_index($table, $index_name, $column); - - if ($this->return_statements) - { - $statements = array_merge($statements, $result); - } - } - } - } - - if ($this->return_statements) - { - return $statements; - } - } - - /** - * Insert SQL data into tables (INSERT). This function DOES NOT SUPPORT $return_statements. SQL queries are executed as is. - * For a complete definition of the layout see {@example } - * - * @param array $schema_data The schema data array - * @param array &$data A replacement array for replacing template variables within the schema - */ - public function sql_insert_data($schema_data, &$data) - { - // Go through the columns and define our type and column name for each column - $keys = $types = array(); - - foreach ($schema_data['columns'] as $column) - { - if (strpos($column, ':') === false) - { - $types[] = false; - $keys[] = $column; - continue; - } - - list($type, $column) = explode(':', $column, 2); - $types[] = $type; - $keys[] = $column; - } - - $size = sizeof($keys); - - // Go through the data array... - foreach ($schema_data['data'] as $key => $row) - { - // Get special values - foreach ($row as $_key => $value) - { - // Special case... - $row[$_key] = $this->_sql_get_special_row($value, $data); - - if ($types[$_key] === false) - { - settype($row[$_key], gettype($row[$_key])); - } - else - { - settype($row[$_key], $types[$_key]); - } - } - - // Build SQL array for INSERT - $sql = 'INSERT INTO ' . $schema_data['table'] . ' ' . $this->db->sql_build_array('INSERT', array_combine($keys, $row)); - $this->db->sql_query($sql); - - if (!empty($schema_data['store_auto_increment'])) - { - $this->stored_increments[$schema_data['store_auto_increment']][$key] = $this->db->sql_nextid(); - } - } - } - - /** - * Update SQL data in tables (UPDATE). This function DOES NOT SUPPORT $return_statements. SQL queries are executed as is. - * For a complete definition of the layout see {@example } - * - * @param array $schema_data The schema data array - * @param array &$data A replacement array for replacing template variables within the schema - */ - public function sql_update_data($schema_data, &$data) - { - // Go through the data array... - $row = $schema_data['data']; - - // Get special values - foreach ($row as $key => $value) - { - $row[$key] = $this->_sql_get_special_row($value, $data); - } - - // Build SQL array for UPDATE - $sql_ary = array_combine(array_values($schema_data['columns']), $row); - - $sql = 'UPDATE ' . $schema_data['table'] . ' SET ' . $this->db->sql_build_array('UPDATE', $sql_ary); - - // Is WHERE statement there? - if (!empty($schema_data['where'])) - { - $where_statements = array(); - foreach ($schema_data['where'] as $_key => $array) - { - foreach ($array as $key => $value) - { - $value = $this->_sql_get_special_row($value, $data); - - if (is_string($value)) - { - $where_statements[] = $key . " = '" . $this->db->sql_escape($value) . "'"; - } - else - { - $where_statements[] = $key . ' = ' . $value; - } - } - } - - if (sizeof($where_statements)) - { - $sql .= ' WHERE ' . implode(' AND ', $where_statements); - } - } - - $this->db->sql_query($sql); - } - - /** - * Check if a specified column exist - * - * @param string $table Table to check the column at - * @param string $column_name The column to check - * - * @return bool True if column exists, else false - */ - public function sql_column_exists($table, $column_name) - { - switch ($this->db->dbms_type) - { - case 'mysql': - - $sql = "SHOW COLUMNS FROM $table"; - $result = $this->db->sql_query($sql); - - while ($row = $this->db->sql_fetchrow($result)) - { - // lower case just in case - if (strtolower($row['Field']) == $column_name) - { - $this->db->sql_freeresult($result); - return true; - } - } - $this->db->sql_freeresult($result); - return false; - break; - - // PostgreSQL has a way of doing this in a much simpler way but would - // not allow us to support all versions of PostgreSQL - case 'postgres': - $sql = "SELECT a.attname - FROM pg_class c, pg_attribute a - WHERE c.relname = '{$table}' - AND a.attnum > 0 - AND a.attrelid = c.oid"; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - // lower case just in case - if (strtolower($row['attname']) == $column_name) - { - $this->db->sql_freeresult($result); - return true; - } - } - $this->db->sql_freeresult($result); - - return false; - break; - - // same deal with PostgreSQL, we must perform more complex operations than - // we technically could - case 'mssql': - $sql = "SELECT c.name - FROM syscolumns c - LEFT JOIN sysobjects o ON c.id = o.id - WHERE o.name = '{$table}'"; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - // lower case just in case - if (strtolower($row['name']) == $column_name) - { - $this->db->sql_freeresult($result); - return true; - } - } - $this->db->sql_freeresult($result); - return false; - break; - - case 'oracle': - $sql = "SELECT column_name - FROM user_tab_columns - WHERE table_name = '{$table}'"; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - // lower case just in case - if (strtolower($row['column_name']) == $column_name) - { - $this->db->sql_freeresult($result); - return true; - } - } - $this->db->sql_freeresult($result); - return false; - break; - - case 'firebird': - $sql = "SELECT RDB\$FIELD_NAME as FNAME - FROM RDB\$RELATION_FIELDS - WHERE RDB\$RELATION_NAME = '{$table}'"; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - // lower case just in case - if (strtolower($row['fname']) == $column_name) - { - $this->db->sql_freeresult($result); - return true; - } - } - $this->db->sql_freeresult($result); - return false; - break; - - case 'db2': - $sql = "SELECT colname - FROM syscat.columns - WHERE tabname = '$table'"; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - // lower case just in case - if (strtolower($row['colname']) == $column_name) - { - $this->db->sql_freeresult($result); - return true; - } - } - $this->db->sql_freeresult($result); - return false; - break; - - // ugh, SQLite - case 'sqlite': - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '{$table}'"; - $result = $this->db->sql_query($sql); - - if (!$result) - { - return false; - } - - $row = $this->db->sql_fetchrow($result); - $this->db->sql_freeresult($result); - - preg_match('#\((.*)\)#s', $row['sql'], $matches); - - $cols = trim($matches[1]); - $col_array = preg_split('/,(?![\s\w]+\))/m', $cols); - - foreach ($col_array as $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - if ($entities[0] == 'PRIMARY') - { - continue; - } - - if (strtolower($entities[0]) == $column_name) - { - return true; - } - } - return false; - break; - } - } - - /** - * Add new column - */ - public function sql_column_add($table_name, $column_name, $column_data) - { - $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data); - $statements = array(); - - switch ($this->db->dbms_type) - { - case 'firebird': - $statements[] = 'ALTER TABLE "' . $table_name . '" ADD "' . $column_name . '" ' . $column_data['column_type_sql']; - break; - - case 'mssql': - $statements[] = 'ALTER TABLE [' . $table_name . '] ADD [' . $column_name . '] ' . $column_data['column_type_sql_default']; - break; - - case 'mysql': - $statements[] = 'ALTER TABLE `' . $table_name . '` ADD COLUMN `' . $column_name . '` ' . $column_data['column_type_sql']; - break; - - case 'oracle': - $statements[] = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' ' . $column_data['column_type_sql']; - break; - - case 'postgres': - $statements[] = 'ALTER TABLE ' . $table_name . ' ADD COLUMN "' . $column_name . '" ' . $column_data['column_type_sql']; - break; - - case 'db2': - $statements[] = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' ' . $column_data['column_type_sql']; - break; - - case 'sqlite': - if (version_compare(sqlite_libversion(), '3.0') == -1) - { - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '{$table_name}' - ORDER BY type DESC, name;"; - $result = $this->db->sql_query($sql); - - if (!$result) - { - break; - } - - $row = $this->db->sql_fetchrow($result); - $this->db->sql_freeresult($result); - - $statements[] = 'begin'; - - // Create a backup table and populate it, destroy the existing one - $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']); - $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name; - $statements[] = 'DROP TABLE ' . $table_name; - - preg_match('#\((.*)\)#s', $row['sql'], $matches); - - $new_table_cols = trim($matches[1]); - $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols); - $column_list = array(); - - foreach ($old_table_cols as $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - if ($entities[0] == 'PRIMARY') - { - continue; - } - $column_list[] = $entities[0]; - } - - $columns = implode(',', $column_list); - - $new_table_cols = $column_name . ' ' . $column_data['column_type_sql'] . ',' . $new_table_cols; - - // create a new table and fill it up. destroy the temp one - $statements[] = 'CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ');'; - $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;'; - $statements[] = 'DROP TABLE ' . $table_name . '_temp'; - - $statements[] = 'commit'; - } - else - { - $statements[] = 'ALTER TABLE ' . $table_name . ' ADD ' . $column_name . ' [' . $column_data['column_type_sql'] . ']'; - } - break; - } - - return $this->_sql_run_sql($statements); - } - - /** - * Drop column - */ - public function sql_column_remove($table_name, $column_name) - { - $statements = array(); - - switch ($this->db->dbms_type) - { - case 'firebird': - $statements[] = 'ALTER TABLE "' . $table_name . '" DROP "' . $column_name . '"'; - break; - - case 'mssql': - $statements[] = 'ALTER TABLE [' . $table_name . '] DROP COLUMN [' . $column_name . ']'; - break; - - case 'mysql': - $statements[] = 'ALTER TABLE `' . $table_name . '` DROP COLUMN `' . $column_name . '`'; - break; - - case 'oracle': - $statements[] = 'ALTER TABLE ' . $table_name . ' DROP ' . $column_name; - break; - - case 'postgres': - $statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN "' . $column_name . '"'; - break; - - case 'db2': - $statements[] = 'ALTER TABLE ' . $table_name . ' DROP ' . $column_name; - break; - - case 'sqlite': - if (version_compare(sqlite_libversion(), '3.0') == -1) - { - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '{$table_name}' - ORDER BY type DESC, name;"; - $result = $this->db->sql_query($sql); - - if (!$result) - { - break; - } - - $row = $this->db->sql_fetchrow($result); - $this->db->sql_freeresult($result); - - $statements[] = 'begin'; - - // Create a backup table and populate it, destroy the existing one - $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']); - $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name; - $statements[] = 'DROP TABLE ' . $table_name; - - preg_match('#\((.*)\)#s', $row['sql'], $matches); - - $new_table_cols = trim($matches[1]); - $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols); - $column_list = array(); - - foreach ($old_table_cols as $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - if ($entities[0] == 'PRIMARY' || $entities[0] === $column_name) - { - continue; - } - $column_list[] = $entities[0]; - } - - $columns = implode(',', $column_list); - - $new_table_cols = $new_table_cols = preg_replace('/' . $column_name . '[^,]+(?:,|$)/m', '', $new_table_cols); - - // create a new table and fill it up. destroy the temp one - $statements[] = 'CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ');'; - $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;'; - $statements[] = 'DROP TABLE ' . $table_name . '_temp'; - - $statements[] = 'commit'; - } - else - { - $statements[] = 'ALTER TABLE ' . $table_name . ' DROP COLUMN ' . $column_name; - } - break; - } - - return $this->_sql_run_sql($statements); - } - - /** - * Drop Index - */ - public function sql_index_drop($table_name, $index_name) - { - $statements = array(); - - switch ($this->db->dbms_type) - { - case 'mssql': - $statements[] = 'DROP INDEX ' . $table_name . '.' . $index_name; - break; - - case 'mysql': - $statements[] = 'DROP INDEX ' . $index_name . ' ON ' . $table_name; - break; - - case 'firebird': - case 'oracle': - case 'postgres': - case 'sqlite': - case 'db2': - $statements[] = 'DROP INDEX ' . $table_name . '_' . $index_name; - break; - } - - return $this->_sql_run_sql($statements); - } - - /** - * Drop Table - */ - public function sql_table_drop($table_name) - { - $statements = array(); - - // the most basic operation, get rid of the table - $statements[] = 'DROP TABLE ' . $table_name; - - switch ($this->db->dbms_type) - { - case 'firebird': - $sql = 'SELECT RDB$GENERATOR_NAME as gen - FROM RDB$GENERATORS - WHERE RDB$SYSTEM_FLAG = 0 - AND RDB$GENERATOR_NAME = \'' . strtoupper($table_name) . "_GEN'"; - $result = $this->db->sql_query($sql); - - // does a generator exist? - if ($row = $this->db->sql_fetchrow($result)) - { - $statements[] = "DROP GENERATOR {$row['gen']};"; - } - $this->db->sql_freeresult($result); - break; - - case 'oracle': - $sql = 'SELECT A.REFERENCED_NAME - FROM USER_DEPENDENCIES A, USER_TRIGGERS B - WHERE A.REFERENCED_TYPE = \'SEQUENCE\' - AND A.NAME = B.TRIGGER_NAME - AND B.TABLE_NAME = \'' . strtoupper($table_name) . "'"; - $result = $this->db->sql_query($sql); - - // any sequences ref'd to this table's triggers? - while ($row = $this->db->sql_fetchrow($result)) - { - $statements[] = "DROP SEQUENCE {$row['referenced_name']}"; - } - $this->db->sql_freeresult($result); - - case 'postgres': - // PGSQL does not "tightly" bind sequences and tables, we must guess... - $sql = "SELECT relname - FROM pg_class - WHERE relkind = 'S' - AND relname = '{$table_name}_seq'"; - $result = $this->db->sql_query($sql); - - // We don't even care about storing the results. We already know the answer if we get rows back. - if ($this->db->sql_fetchrow($result)) - { - $statements[] = "DROP SEQUENCE {$table_name}_seq;\n"; - } - $this->db->sql_freeresult($result); - break; - } - - return $this->_sql_run_sql($statements); - } - - /** - * Add primary key - */ - public function sql_create_primary_key($table_name, $column) - { - $statements = array(); - - switch ($this->db->dbms_type) - { - case 'firebird': - case 'postgres': - case 'mysql': - case 'db2': - $statements[] = 'ALTER TABLE ' . $table_name . ' ADD PRIMARY KEY (' . implode(', ', $column) . ')'; - break; - - case 'mssql': - $sql = "ALTER TABLE [{$table_name}] WITH NOCHECK ADD "; - $sql .= "CONSTRAINT [PK_{$table_name}] PRIMARY KEY CLUSTERED ("; - $sql .= '[' . implode("],\n\t\t[", $column) . ']'; - $sql .= ') ON [PRIMARY]'; - - $statements[] = $sql; - break; - - case 'oracle': - $statements[] = 'ALTER TABLE ' . $table_name . 'add CONSTRAINT pk_' . $table_name . ' PRIMARY KEY (' . implode(', ', $column) . ')'; - break; - - case 'sqlite': - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '{$table_name}' - ORDER BY type DESC, name;"; - $result = $this->db->sql_query($sql); - - if (!$result) - { - break; - } - - $row = $this->db->sql_fetchrow($result); - $this->db->sql_freeresult($result); - - $statements[] = 'begin'; - - // Create a backup table and populate it, destroy the existing one - $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']); - $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name; - $statements[] = 'DROP TABLE ' . $table_name; - - preg_match('#\((.*)\)#s', $row['sql'], $matches); - - $new_table_cols = trim($matches[1]); - $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols); - $column_list = array(); - - foreach ($old_table_cols as $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - if ($entities[0] == 'PRIMARY') - { - continue; - } - $column_list[] = $entities[0]; - } - - $columns = implode(',', $column_list); - - // create a new table and fill it up. destroy the temp one - $statements[] = 'CREATE TABLE ' . $table_name . ' (' . $new_table_cols . ', PRIMARY KEY (' . implode(', ', $column) . '));'; - $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;'; - $statements[] = 'DROP TABLE ' . $table_name . '_temp'; - - $statements[] = 'commit'; - break; - } - - return $this->_sql_run_sql($statements); - } - - /** - * Add unique index - */ - public function sql_create_unique_index($table_name, $index_name, $column) - { - $statements = array(); - - switch ($this->db->dbms_type) - { - case 'firebird': - case 'postgres': - case 'oracle': - case 'sqlite': - case 'db2': - $statements[] = 'CREATE UNIQUE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; - break; - - case 'mysql': - $statements[] = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; - break; - - case 'mssql': - $statements[] = 'CREATE UNIQUE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]'; - break; - } - - return $this->_sql_run_sql($statements); - } - - /** - * Add index - */ - public function sql_create_index($table_name, $index_name, $column) - { - $statements = array(); - - switch ($this->db->dbms_type) - { - case 'firebird': - case 'postgres': - case 'oracle': - case 'sqlite': - case 'db2': - $statements[] = 'CREATE INDEX ' . $table_name . '_' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; - break; - - case 'mysql': - $statements[] = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ')'; - break; - - case 'mssql': - $statements[] = 'CREATE INDEX ' . $index_name . ' ON ' . $table_name . '(' . implode(', ', $column) . ') ON [PRIMARY]'; - break; - } - - return $this->_sql_run_sql($statements); - } - - /** - * List all of the indices that belong to a table, - * does not count: - * * UNIQUE indices - * * PRIMARY keys - */ - public function sql_list_index($table_name) - { - $index_array = array(); - - if ($this->db->dbms_type == 'mssql') - { - $sql = "EXEC sp_statistics '$table_name'"; - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - if ($row['TYPE'] == 3) - { - $index_array[] = $row['INDEX_NAME']; - } - } - $this->db->sql_freeresult($result); - } - else - { - switch ($this->db->dbms_type) - { - case 'firebird': - $sql = "SELECT LOWER(RDB\$INDEX_NAME) as index_name - FROM RDB\$INDICES - WHERE RDB\$RELATION_NAME = " . strtoupper($table_name) . " - AND RDB\$UNIQUE_FLAG IS NULL - AND RDB\$FOREIGN_KEY IS NULL"; - $col = 'index_name'; - break; - - case 'postgres': - $sql = "SELECT ic.relname as index_name - FROM pg_class bc, pg_class ic, pg_index i - WHERE (bc.oid = i.indrelid) - AND (ic.oid = i.indexrelid) - AND (bc.relname = '" . $table_name . "') - AND (i.indisunique != 't') - AND (i.indisprimary != 't')"; - $col = 'index_name'; - break; - - case 'mysql': - $sql = 'SHOW KEYS - FROM ' . $table_name; - $col = 'Key_name'; - break; - - case 'oracle': - $sql = "SELECT index_name - FROM user_indexes - WHERE table_name = '" . $table_name . "' - AND generated = 'N'"; - $col = 'index_name'; - break; - - case 'sqlite': - $sql = "PRAGMA index_info('" . $table_name . "');"; - $col = 'name'; - break; - - case 'db2': - $sql = "SELECT indname - FROM SYSCAT.INDEXES - WHERE TABNAME = '$table_name' - AND UNIQUERULE <> 'P'"; - $col = 'name'; - } - - $result = $this->db->sql_query($sql); - while ($row = $this->db->sql_fetchrow($result)) - { - if ($this->db->dbms_type == 'mysql' && !$row['Non_unique']) - { - continue; - } - - switch ($this->db->dbms_type) - { - case 'firebird': - case 'oracle': - case 'postgres': - case 'sqlite': - case 'db2': - $row[$col] = substr($row[$col], strlen($table_name) + 1); - break; - } - - $index_array[] = $row[$col]; - } - $this->db->sql_freeresult($result); - } - - return array_map('strtolower', $index_array); - } - - /** - * Change column type (not name!) - */ - public function sql_column_change($table_name, $column_name, $column_data) - { - $column_data = $this->sql_prepare_column_data($table_name, $column_name, $column_data); - $statements = array(); - - switch ($this->db->dbms_type) - { - case 'firebird': - // Change type... - $statements[] = 'ALTER TABLE "' . $table_name . '" ALTER COLUMN "' . $column_name . '" TYPE ' . ' ' . $column_data['column_type_sql']; - break; - - case 'mssql': - $statements[] = 'ALTER TABLE [' . $table_name . '] ALTER COLUMN [' . $column_name . '] ' . $column_data['column_type_sql']; - break; - - case 'mysql': - $statements[] = 'ALTER TABLE `' . $table_name . '` CHANGE `' . $column_name . '` `' . $column_name . '` ' . $column_data['column_type_sql']; - break; - - case 'oracle': - $statements[] = 'ALTER TABLE ' . $table_name . ' MODIFY ' . $column_name . ' ' . $column_data['column_type_sql']; - break; - - case 'db2': - $statements[] = 'ALTER TABLE ' . $table_name . ' ALTER ' . $column_name . ' SET DATA TYPE ' . $column_data['column_type_sql']; - break; - - case 'postgres': - $sql = 'ALTER TABLE ' . $table_name . ' '; - - $sql_array = array(); - $sql_array[] = 'ALTER COLUMN ' . $column_name . ' TYPE ' . $column_data['column_type']; - - if (isset($column_data['null'])) - { - if ($column_data['null'] == 'NOT NULL') - { - $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET NOT NULL'; - } - else if ($column_data['null'] == 'NULL') - { - $sql_array[] = 'ALTER COLUMN ' . $column_name . ' DROP NOT NULL'; - } - } - - if (isset($column_data['default'])) - { - $sql_array[] = 'ALTER COLUMN ' . $column_name . ' SET DEFAULT ' . $column_data['default']; - } - - // we don't want to double up on constraints if we change different number data types - if (isset($column_data['constraint'])) - { - $constraint_sql = "SELECT consrc as constraint_data - FROM pg_constraint, pg_class bc - WHERE conrelid = bc.oid - AND bc.relname = '{$table_name}' - AND NOT EXISTS ( - SELECT * - FROM pg_constraint as c, pg_inherits as i - WHERE i.inhrelid = pg_constraint.conrelid - AND c.conname = pg_constraint.conname - AND c.consrc = pg_constraint.consrc - AND c.conrelid = i.inhparent - )"; - - $constraint_exists = false; - - $result = $this->db->sql_query($constraint_sql); - while ($row = $this->db->sql_fetchrow($result)) - { - if (trim($row['constraint_data']) == trim($column_data['constraint'])) - { - $constraint_exists = true; - break; - } - } - $this->db->sql_freeresult($result); - - if (!$constraint_exists) - { - $sql_array[] = 'ADD ' . $column_data['constraint']; - } - } - - $sql .= implode(', ', $sql_array); - - $statements[] = $sql; - break; - - case 'sqlite': - $sql = "SELECT sql - FROM sqlite_master - WHERE type = 'table' - AND name = '{$table_name}' - ORDER BY type DESC, name;"; - $result = $this->db->sql_query($sql); - - if (!$result) - { - break; - } - - $row = $this->db->sql_fetchrow($result); - $this->db->sql_freeresult($result); - - $statements[] = 'begin'; - - // Create a temp table and populate it, destroy the existing one - $statements[] = preg_replace('#CREATE\s+TABLE\s+"?' . $table_name . '"?#i', 'CREATE TEMPORARY TABLE ' . $table_name . '_temp', $row['sql']); - $statements[] = 'INSERT INTO ' . $table_name . '_temp SELECT * FROM ' . $table_name; - $statements[] = 'DROP TABLE ' . $table_name; - - preg_match('#\((.*)\)#s', $row['sql'], $matches); - - $new_table_cols = trim($matches[1]); - $old_table_cols = preg_split('/,(?![\s\w]+\))/m', $new_table_cols); - $column_list = array(); - - foreach ($old_table_cols as $key => $declaration) - { - $entities = preg_split('#\s+#', trim($declaration)); - $column_list[] = $entities[0]; - if ($entities[0] == $column_name) - { - $old_table_cols[$key] = $column_name . ' ' . $column_data['column_type_sql']; - } - } - - $columns = implode(',', $column_list); - - // create a new table and fill it up. destroy the temp one - $statements[] = 'CREATE TABLE ' . $table_name . ' (' . implode(',', $old_table_cols) . ');'; - $statements[] = 'INSERT INTO ' . $table_name . ' (' . $columns . ') SELECT ' . $columns . ' FROM ' . $table_name . '_temp;'; - $statements[] = 'DROP TABLE ' . $table_name . '_temp'; - - $statements[] = 'commit'; - - break; - } - - return $this->_sql_run_sql($statements); - } - - private function _sql_get_special_row($value, &$data) - { - if (is_array($value)) - { - if (isset($value['auto_increment'])) - { - $auto_key = explode(':', $value['auto_increment'], 2); - $value_key = $auto_key[0]; - $auto_key = (int) $auto_key[1]; - - if (isset($this->stored_increments[$value_key][$auto_key])) - { - $value = $this->stored_increments[$value_key][$auto_key]; - } - } - else - { - $value = NULL; - } - } - else if (strpos($value, '{') === 0 && strpos($value, '}') === strlen($value) - 1) - { - if (strpos($value, '{L_') === 0 && isset(phpbb::$user->lang[substr($value, 3, -1)])) - { - $value = phpbb::$user->lang[substr($value, 3, -1)]; - } - else if (isset($data[substr($value, 1, -1)])) - { - $value = $data[substr($value, 1, -1)]; - } - } - - return $value; - } - - /** - * Private method for performing sql statements (either execute them or return them) - * @access private - */ - private function _sql_run_sql($statements) - { - if ($this->return_statements) - { - return $statements; - } - - // We could add error handling here... - foreach ($statements as $sql) - { - if ($sql === 'begin') - { - $this->db->sql_transaction('begin'); - } - else if ($sql === 'commit') - { - $this->db->sql_transaction('commit'); - } - else - { - $this->db->sql_query($sql); - } - } - - return true; - } - - /** - * Function to prepare some column information for better usage - * @access private - */ - private function sql_prepare_column_data($table_name, $column_name, $column_data) - { - // Get type - if (strpos($column_data[0], ':') !== false) - { - list($orig_column_type, $column_length) = explode(':', $column_data[0]); - - if (!is_array($this->db->dbms_type_map[$orig_column_type . ':'])) - { - $column_type = sprintf($this->db->dbms_type_map[$orig_column_type . ':'], $column_length); - } - else - { - if (isset($this->db->dbms_type_map[$orig_column_type . ':']['rule'])) - { - switch ($this->db->dbms_type_map[$orig_column_type . ':']['rule'][0]) - { - case 'div': - $column_length /= $this->db->dbms_type_map[$orig_column_type . ':']['rule'][1]; - $column_length = ceil($column_length); - $column_type = sprintf($this->db->dbms_type_map[$orig_column_type . ':'][0], $column_length); - break; - } - } - - if (isset($this->db->dbms_type_map[$orig_column_type . ':']['limit'])) - { - switch ($this->db->dbms_type_map[$orig_column_type . ':']['limit'][0]) - { - case 'mult': - $column_length *= $this->db->dbms_type_map[$orig_column_type . ':']['limit'][1]; - if ($column_length > $this->db->dbms_type_map[$orig_column_type . ':']['limit'][2]) - { - $column_type = $this->db->dbms_type_map[$orig_column_type . ':']['limit'][3]; - } - else - { - $column_type = sprintf($this->db->dbms_type_map[$orig_column_type . ':'][0], $column_length); - } - break; - } - } - } - - $orig_column_type .= ':'; - } - else - { - $orig_column_type = $column_data[0]; - $column_type = $this->db->dbms_type_map[$column_data[0]]; - } - - // Adjust default value if db-dependant specified - if (is_array($column_data[1])) - { - $column_data[1] = (isset($column_data[1][$this->db->dbms_type])) ? $column_data[1][$this->db->dbms_type] : $column_data[1]['default']; - } - - $sql = ''; - - $return_array = array(); - - switch ($this->db->dbms_type) - { - case 'firebird': - $sql .= " {$column_type} "; - - if (!is_null($column_data[1])) - { - $sql .= 'DEFAULT ' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ' '; - } - - $sql .= 'NOT NULL'; - - // This is a UNICODE column and thus should be given it's fair share - if (preg_match('/^X?STEXT_UNI|VCHAR_(CI|UNI:?)/', $column_data[0])) - { - $sql .= ' COLLATE UNICODE'; - } - - $return_array['auto_increment'] = false; - if (isset($column_data[2]) && $column_data[2] == 'auto_increment') - { - $return_array['auto_increment'] = true; - } - - break; - - case 'mssql': - $sql .= " {$column_type} "; - $sql_default = " {$column_type} "; - - // For adding columns we need the default definition - if (!is_null($column_data[1])) - { - // For hexadecimal values do not use single quotes - if (strpos($column_data[1], '0x') === 0) - { - $sql_default .= 'DEFAULT (' . $column_data[1] . ') '; - } - else - { - $sql_default .= 'DEFAULT (' . ((is_numeric($column_data[1])) ? $column_data[1] : "'{$column_data[1]}'") . ') '; - } - } - - if (isset($column_data[2]) && $column_data[2] == 'auto_increment') - { -// $sql .= 'IDENTITY (1, 1) '; - $sql_default .= 'IDENTITY (1, 1) '; - } - - $return_array['textimage'] = $column_type === '[text]'; - - $sql .= 'NOT NULL'; - $sql_default .= 'NOT NULL'; - - $return_array['column_type_sql_default'] = $sql_default; - break; - - case 'mysql': - $sql .= " {$column_type} "; - - // For hexadecimal values do not use single quotes - if (!is_null($column_data[1]) && substr($column_type, -4) !== 'text' && substr($column_type, -4) !== 'blob') - { - $sql .= (strpos($column_data[1], '0x') === 0) ? "DEFAULT {$column_data[1]} " : "DEFAULT '{$column_data[1]}' "; - } - $sql .= 'NOT NULL'; - - if (isset($column_data[2])) - { - if ($column_data[2] == 'auto_increment') - { - $sql .= ' auto_increment'; - } - else if ($column_data[2] == 'true_sort') - { - $sql .= ' COLLATE utf8_unicode_ci'; - } - } - - break; - - case 'oracle': - $sql .= " {$column_type} "; - $sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}' " : ''; - - // In Oracle empty strings ('') are treated as NULL. - // Therefore in oracle we allow NULL's for all DEFAULT '' entries - // Oracle does not like setting NOT NULL on a column that is already NOT NULL (this happens only on number fields) - if (!preg_match('/number/i', $column_type)) - { - $sql .= ($column_data[1] === '') ? '' : 'NOT NULL'; - } - - $return_array['auto_increment'] = false; - if (isset($column_data[2]) && $column_data[2] == 'auto_increment') - { - $return_array['auto_increment'] = true; - } - break; - - case 'postgres': - $return_array['column_type'] = $column_type; - - $sql .= " {$column_type} "; - - $return_array['auto_increment'] = false; - if (isset($column_data[2]) && $column_data[2] == 'auto_increment') - { - $default_val = "nextval('{$table_name}_seq')"; - $return_array['auto_increment'] = true; - } - else if (!is_null($column_data[1])) - { - $default_val = "'" . $column_data[1] . "'"; - $return_array['null'] = 'NOT NULL'; - $sql .= 'NOT NULL '; - } - - $return_array['default'] = $default_val; - - $sql .= "DEFAULT {$default_val}"; - - // Unsigned? Then add a CHECK contraint - if (in_array($orig_column_type, $this->unsigned_types)) - { - $return_array['constraint'] = "CHECK ({$column_name} >= 0)"; - $sql .= " CHECK ({$column_name} >= 0)"; - } - break; - - case 'sqlite': - $return_array['primary_key_set'] = false; - if (isset($column_data[2]) && $column_data[2] == 'auto_increment') - { - $sql .= ' INTEGER PRIMARY KEY'; - $return_array['primary_key_set'] = true; - } - else - { - $sql .= ' ' . $column_type; - } - - $sql .= ' NOT NULL '; - $sql .= (!is_null($column_data[1])) ? "DEFAULT '{$column_data[1]}'" : ''; - break; - - case 'db2': - $sql .= " {$column_type} NOT NULL"; - - if (isset($column_data[2]) && $column_data[2] == 'auto_increment') - { - $sql .= ' GENERATED BY DEFAULT AS IDENTITY (START WITH 1, INCREMENT BY 1)'; - } - else - { - if (preg_match('/^(integer|smallint|float)$/', $column_type)) - { - $sql .= " DEFAULT {$column_data[1]}"; - } - else - { - $sql .= " DEFAULT '{$column_data[1]}'"; - } - } - break; - } - - $return_array['column_type_sql'] = $sql; - - return $return_array; - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/dbal.php b/phpBB/includes/db/dbal.php deleted file mode 100644 index 15127509cc..0000000000 --- a/phpBB/includes/db/dbal.php +++ /dev/null @@ -1,1553 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* DBAL Factory -* Only used to instantiate a new DB object -* -* @package dbal -* @static -*/ -abstract class phpbb_db_dbal -{ - /** - * Get new database object - * - * @param string $dbms Database module to call - * @return object Database object - * @access public - */ - public static function new_instance($dbms) - { - $class = 'phpbb_dbal_' . $dbms; - - if (!class_exists($class)) - { - include PHPBB_ROOT_PATH . 'includes/db/' . $dbms . '.' . PHP_EXT; - } - - // Instantiate class - $db = new $class(); - - // Fill default sql layer - $db->sql_layer = $dbms; - - return $db; - } - - /** - * Get new database object and connect to database - * - * @param string $dbms Database module to call - * @param string $server DB server address to connect to - * @param string $user DB user name - * @param string $password DB password to use - * @param string $database Database name to connect to - * @param int $port DB Port - * @param bool $persistency Open persistent DB connection if true - * @param bool $new_link If set to true a new connection is opened instead of re-using old connections - * - * @return object Database object - * @access public - */ - public static function connect($dbms, $server, $user, $password, $database, $port = false, $persistency = false, $new_link = false) - { - $class = 'phpbb_dbal_' . $dbms; - - if (!class_exists($class)) - { - include PHPBB_ROOT_PATH . 'includes/db/' . $dbms . '.' . PHP_EXT; - } - - // Instantiate class - $db = new $class(); - - // Fill default sql layer - $db->sql_layer = $dbms; - - // Connect to DB - $db->sql_connect($server, $user, $password, $database, $port, $persistency, $new_link); - - // Return db object - return $db; - } -} - -/** -* Database Abstraction Layer -* @package dbal -*/ -abstract class phpbb_dbal -{ - /** - * @var array required phpBB objects - */ - public $phpbb_required = array('config'); - - /** - * @var array Optional phpBB objects - */ - public $phpbb_optional = array('acm', 'user', 'acl'); - - /** - * @var string Current sql layer name - */ - public $sql_layer = ''; - - /** - * @var string Exact version of the DBAL, directly queried - */ - public $sql_server_version = false; - - /** - * @var mixed Database connection id/resource - */ - public $db_connect_id; - - /** - * @var mixed Database query result id/resource - */ - public $query_result; - - /** - * @var bool Persistent connection - */ - public $persistency = false; - - /** - * @var string DB user name - */ - public $user = ''; - - /** - * @var string DB server address connected to - */ - public $server = ''; - - /** - * @var string Database name connected to - */ - public $dbname = ''; - - /** - * @var int Database port used - */ - public $port = 0; - - /** - * @var bool Is true if in transaction - */ - public $transaction = false; - - /** - * @var int Holding transaction count - */ - public $transactions = 0; - - /** - * Stores number of queries - * - * Keys are: - * <ul> - * <li>cached: Number of cached queries executed</li> - * <li>normal: Number of non-cached queries executed</li> - * <li>total: Total number of queries executed</li> - * </ul> - * - * @var array - */ - public $num_queries = array(); - - /** - * Stores opened queries. - * - * The key is returned by {@link phpbb_dbal::sql_get_result_key() sql_get_result_key()}. - * The value is the {@link phpbb_dbal::$query_result Database query result id/resource}. - * - * @var array - */ - public $open_queries = array(); - - /** - * @var string Wildcard for matching any (%) character within LIKE expressions - */ - public $any_char; - - /** - * @var string Wildcard for matching exactly one (_) character within LIKE expressions - */ - public $one_char; - - /** - * @var array Storing cached result rowset - */ - protected $cache_rowset = array(); - - /** - * @var int Storing cached result rowset index - */ - protected $cache_index = 0; - - /** - * @var bool If true then methods do not call {@link phpbb_dbal::sql_error() sql_error()} on SQL error, but return silently. - */ - public $return_on_error = false; - - /** - * @var bool This is set to true if an error had been triggered. - */ - public $sql_error_triggered = false; - - /** - * @var string Holds the last sql query on triggered sql error. - */ - public $sql_error_sql = ''; - - /** - * @var array Holds the SQL error information - only populated if {@link phpbb_dbal::$sql_error_triggered sql_error_triggered} is set to true. - */ - public $sql_error_returned = array(); - - /** - * Database features - * - * <ul> - * <li>multi_insert: Supports multi inserts</li> - * <li>count_distinct: Supports COUNT(DISTINGT ...)</li> - * <li>multi_table_deletion: Supports multiple table deletion</li> - * <li>truncate: Supports table truncation</li> - * </ul> - * - * @var array - */ - public $features = array( - 'multi_insert' => true, - 'count_distinct' => true, - 'multi_table_deletion' => true, - 'truncate' => true, - ); - - /** - * @var int Passed time for executing SQL queries - */ - public $sql_time = 0; - - /** - * @var int Current timestamp - */ - public $curtime = 0; - - /**#@+ - * @var string String to hold information for {@link phpbb_dbal::sql_report() SQL report}. - */ - protected $query_hold = ''; - protected $html_hold = ''; - protected $sql_report = ''; - /**#@-*/ - - /** - * Constructor. Set default values. - * @access public - */ - public function __construct() - { - $this->num_queries = array( - 'cached' => 0, - 'normal' => 0, - 'total' => 0, - ); - - // Do not change this please! This variable is used to easy the use of it - and is hardcoded. - $this->any_char = chr(0) . '%'; - $this->one_char = chr(0) . '_'; - - $this->cache_rowset = array(); - $this->cache_index = 0; - } - - /** - * Connect to SQL Server. - * - * @param string $server DB server address to connect to - * @param string $user DB user name - * @param string $password DB password to use - * @param string $database Database name to connect to - * @param int $port DB Port - * @param bool $persistency Open persistent DB connection if true - * @param bool $new_link If set to true a new connection is opened instead of re-using old connections - * - * @return mixed Database connection id/resource - * @access public - */ - abstract public function sql_connect($server, $user, $password, $database, $port = false, $persistency = false , $new_link = false); - - /** - * Version information about used database - * - * @param bool $raw If true, only return the fetched sql_server_version without any additional strings - * - * @return string Sql server version - * @access public - */ - abstract public function sql_server_info($raw = false); - - /** - * Return number of affected rows. - * - * @return int Number of affected rows. False if there is no valid database connection id. - * @access public - */ - abstract public function sql_affectedrows(); - - /** - * Get last inserted id after insert statement - * - * @return int Last inserted id. False if there is no valid database connection id. - * @access public - */ - abstract public function sql_nextid(); - - /** - * Escape string used in sql query. - * - * @param string $msg Text to escape - * - * @return string Escaped text - * @access public - */ - abstract public function sql_escape($msg); - - /** - * Expose a DBMS specific function. - * - * Supported types are: - * <ul> - * <li>length_varchar: Get expression to return length of VARCHAR</li> - * <li>length_text: Get expression to return length of TEXT</li> - * </ul> - * - * @param string $type Type to return DB-specific code for - * @param string $col Column name to operate on - * - * @return string DB-specific code able to be used in SQL query - * @access public - */ - abstract public function sql_function($type, $col); - - /** - * Handle data by using prepared statements. - * - * @param string $type The type to handle. Possible values are: INSERT, UPDATE - * @param string $table The table to use insert or update - * @param mixed $data The data to insert/update in an array (key == column, value == value) - * @param string $where An optional where-statement - * @access public - * @todo implement correctly by using types and only overwrite if DB supports prepared statements - */ - public function sql_handle_data($type, $table, $data, $where = '') - { - if ($type === 'UPDATE') - { - $where = ($where) ? ' WHERE ' . $where : ''; - $this->sql_query('UPDATE ' . $table . ' SET ' . $this->sql_build_array('UPDATE', $data) . $where); - } - else - { - $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $data)); - } - } - - /** - * DB-specific base query method. Called by {@link phpbb_dbal::sql_query() sql_query()}. - * - * @param string $query Contains the SQL query which shall be executed - * - * @return mixed Returns the query result resource. When casted to bool the returned value returns true on success and false on failure - * @access protected - */ - abstract protected function _sql_query($query); - - /** - * DB-specific method to Build LIMIT query and run it. Called by {@link phpbb_dbal::sql_query_limit() sql_query_limit}. - * - * @param string $query SQL query LIMIT should be applied to - * @param int $total Total number of rows returned - * @param int $offset Offset to read from - * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache - * - * @return mixed Returns the query result resource. When casted to bool the returned value returns true on success and false on failure - * @access protected - */ - abstract protected function _sql_query_limit($query, $total, $offset, $cache_ttl); - - /** - * DB-specific method to close sql connection. Called by {@link phpbb_dbal::sql_close() sql_close()}. - * @access protected - */ - abstract protected function _sql_close(); - - /** - * DB-specific SQL Transaction. Called by {@link phpbb_dbal::sql_transaction() sql_transaction()}. - * - * @param string $status The status code. See {@link phpbb_dbal::sql_transaction() sql_transaction()} for status codes. - * - * @return mixed The result returned by the DB - * @access protected - */ - abstract protected function _sql_transaction($status); - - /** - * Fetch current row. Called by {@link phpbb_dbal::sql_fetchrow() sql_fetchrow()}. - * - * @param mixed $query_id Query result resource - * - * @return array|bool The current row or false if an error occurred - * @access protected - */ - abstract protected function _sql_fetchrow($query_id); - - /** - * Free query result. Called by {@link phpbb_dbal::sql_freeresult() sql_freeresult()}. - * - * @param mixed $query_id Query result resource - * - * @return mixed The DB result - * @access protected - */ - abstract protected function _sql_freeresult($query_id); - - /** - * Correctly adjust LIKE expression for special characters. Called by {@link phpbb_dbal::sql_like_expression() sql_like_expression()}. - * - * @param string $expression The expression to use. Every wildcard is escaped, except {@link phpbb_dbal::$any_char $any_char} and {@link phpbb_dbal::$one_char $one_char} - * - * @return string LIKE expression including the keyword! - * @access protected - */ - abstract protected function _sql_like_expression($expression); - - /** - * Build DB-specific query bits for {@link phpbb_dbal::sql_build_query() sql_build_query()}. - * - * Currently used stages are ($stage: $data) - * <ul> - * <li>FROM: implode(', ', $table_array)</li> - * <li>WHERE: Full WHERE-Statement without WHERE keyword</li> - * </ul> - * - * @param string $stage The current stage build_query needs db-specific data for. Currently used are: FROM and WHERE. - * @param string $data Data to operate with - * - * @return string $data in it's original form or adjusted to meet DB-specific standard - * @access protected - */ - abstract protected function _sql_custom_build($stage, $data); - - /** - * Return sql error array. Called by {@link phpbb_dbal::sql_error() sql_error()}. - * - * @return array Array with two keys. 'code' for the error code and 'message' for the error message. - * @access protected - */ - abstract protected function _sql_error(); - - /** - * Run DB-specific code to build SQL Report to explain queries, show statistics and runtime information. Called by {@link phpbb_dbal::sql_report() sql_report()}. - * - * This function only executes if the GET parameter 'explain' is true and phpbb::$base_config['debug_extra'] enabled. - * - * @param string $mode The mode to handle. 'display' is used for displaying the report, all other modes are internal. - * @param string $query Query to document/explain. Only used internally to build the plan. - * - * @access protected - */ - abstract protected function _sql_report($mode, $query = ''); - - /** - * Base query method - * - * @param string $query Contains the SQL query which shall be executed - * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache - * - * @return mixed Returns the query result resource. When casted to bool the returned value returns true on success and false on failure - * @access public - */ - public function sql_query($query = '', $cache_ttl = 0) - { - if (empty($query)) - { - return false; - } - - // EXPLAIN only in extra debug mode - if (phpbb::$base_config['debug_extra']) - { - $this->sql_report('start', $query); - } - - $this->query_result = false; - - if ($cache_ttl) - { - $this->sql_get_cache($query); - } - - $this->sql_add_num_queries($this->query_result); - - if ($this->query_result !== false) - { - if (phpbb::$base_config['debug_extra']) - { - $this->sql_report('fromcache', $query); - } - - return $this->query_result; - } - - if (($this->query_result = $this->_sql_query($query)) === false) - { - $this->sql_error($query); - } - - if (phpbb::$base_config['debug_extra']) - { - $this->sql_report('stop', $query); - } - - if ($cache_ttl) - { - $this->sql_put_cache($query, $cache_ttl); - } - - if ($cache_ttl || strpos($query, 'SELECT') === 0) - { - if (($key = $this->sql_get_result_key($this->query_result)) !== false) - { - $this->open_queries[$key] = $this->query_result; - } - } - - return $this->query_result; - } - - /** - * Build LIMIT query and run it. - * - * @param string $query SQL query LIMIT should be applied to - * @param int $total Total number of rows returned - * @param int $offset Offset to read from - * @param int $cache_ttl Either 0 to avoid caching or the time in seconds which the result shall be kept in cache - * - * @return mixed Returns the query result resource. When casted to bool the returned value returns true on success and false on failure - * @access public - */ - public function sql_query_limit($query, $total, $offset = 0, $cache_ttl = 0) - { - if (empty($query)) - { - return false; - } - - // Never use a negative total or offset - $total = ($total < 0) ? 0 : $total; - $offset = ($offset < 0) ? 0 : $offset; - - return $this->_sql_query_limit($query, $total, $offset, $cache_ttl); - } - - /** - * Switch for "return on error" or "display error message". Affects {@link phpbb_dbal::$return_on_error $return_on_error}. - * - * @param bool $fail True to return on SQL error. False to display error message on SQL error. - * @access public - */ - public function sql_return_on_error($fail = false) - { - $this->sql_error_triggered = false; - $this->sql_error_sql = ''; - - $this->return_on_error = $fail; - } - - /** - * Return number of sql queries and cached sql queries used. - * - * @param bool $cached True to return cached queries executed. False to return non-cached queries executed. - * - * @return int Number of queries executed - * @access public - */ - public function sql_num_queries($cached = false) - { - return ($cached) ? $this->num_queries['cached'] : $this->num_queries['normal']; - } - - /** - * DBAL garbage collection, close sql connection. - * - * Iterates through {@link phpbb_dbal::$open_queries open queries} and closes them. - * For connection close {@link phpbb_dbal::_sql_close() the DB-specific method} is called. - * - * @return bool False if there was no db connection to close or an error occurred, else true - * @access public - */ - public function sql_close() - { - if (!$this->db_connect_id) - { - return false; - } - - if ($this->transaction) - { - do - { - $this->sql_transaction('commit'); - } - while ($this->transaction); - } - - foreach ($this->open_queries as $key => $query_result) - { - $this->sql_freeresult($query_result); - } - - // Connection closed correctly. Set db_connect_id to false to prevent errors - if ($result = $this->_sql_close()) - { - $this->db_connect_id = false; - } - - return $result; - } - - /** - * SQL Transaction. - * - * Standard status codes are: - * <ul> - * <li>begin: Begin transaction</li> - * <li>commit: Commit/end transaction</li> - * <li>rollback: Rollback transaction</li> - * </ul> - * - * @param string $status The status code. - * - * @return mixed The result returned by the DB - * @access public - */ - public function sql_transaction($status = 'begin') - { - switch ($status) - { - case 'begin': - // If we are within a transaction we will not open another one, but enclose the current one to not loose data (prevening auto commit) - if ($this->transaction) - { - $this->transactions++; - return true; - } - - $result = $this->_sql_transaction('begin'); - - if (!$result) - { - $this->sql_error(); - } - - $this->transaction = true; - break; - - case 'commit': - // If there was a previously opened transaction we do not commit yet... but count back the number of inner transactions - if ($this->transaction && $this->transactions) - { - $this->transactions--; - return true; - } - - // Check if there is a transaction (no transaction can happen if there was an error, with a combined rollback and error returning enabled) - // This implies we have transaction always set for autocommit db's - if (!$this->transaction) - { - return false; - } - - $result = $this->_sql_transaction('commit'); - - if (!$result) - { - $this->sql_error(); - } - - $this->transaction = false; - $this->transactions = 0; - break; - - case 'rollback': - $result = $this->_sql_transaction('rollback'); - $this->transaction = false; - $this->transactions = 0; - break; - - default: - $result = $this->_sql_transaction($status); - break; - } - - return $result; - } - - /** - * Fetch current row. - * - * @param mixed $query_id Query result resource - * - * @return array|bool The current row or false if an error occurred - * @access public - */ - public function sql_fetchrow($query_id = false) - { - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if ($this->sql_cache_exists($query_id)) - { - return $this->sql_cache_fetchrow($query_id); - } - - return ($query_id !== false) ? $this->_sql_fetchrow($query_id) : false; - } - - /** - * Fetch rowset (all rows). - * - * @param mixed $query_id Query result resource - * - * @return array|bool The complete rowset or false if an error occurred - * @access public - */ - public function sql_fetchrowset($query_id = false) - { - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if ($query_id !== false) - { - $result = array(); - while ($row = $this->sql_fetchrow($query_id)) - { - $result[] = $row; - } - - return $result; - } - - return false; - } - - /** - * Fetch field from current row. - * - * @param string $field Field/Column name to fetch data from. - * @param mixed $query_id Query result resource - * - * @return mixed The fields value - * @access public - */ - public function sql_fetchfield($field, $query_id = false) - { - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if ($query_id !== false) - { - if ($this->sql_cache_exists($query_id)) - { - return $this->sql_cache_fetchfield($query_id, $field); - } - - $row = $this->sql_fetchrow($query_id); - return (isset($row[$field])) ? $row[$field] : false; - } - - return false; - } - - /** - * Free query result. - * - * @param mixed $query_id Query result resource - * - * @return mixed The DB result - * @access public - */ - public function sql_freeresult($query_id) - { - if ($query_id === false) - { - $query_id = $this->query_result; - } - - if ($this->sql_cache_exists($query_id)) - { - return $this->sql_cache_freeresult($query_id); - } - - if (($key = $this->sql_get_result_key($query_id)) !== false) - { - unset($this->open_queries[$key]); - } - - return $this->_sql_freeresult($query_id); - } - - /** - * Correctly adjust LIKE expression for special characters, some DBMS are handling them in a different way. - * - * @param string $expression The expression to use. Every wildcard is escaped, except {@link phpbb_dbal::$any_char $any_char} and {@link phpbb_dbal::$one_char $one_char} - * - * @return string LIKE expression including the keyword! - * @access public - */ - public function sql_like_expression($expression) - { - $expression = str_replace(array('_', '%'), array("\_", "\%"), $expression); - $expression = str_replace(array(chr(0) . "\_", chr(0) . "\%"), array('_', '%'), $expression); - - return $this->_sql_like_expression('LIKE \'' . $this->sql_escape($expression) . '\''); - } - - /** - * Build sql statement from array for insert/update/select statements. - * - * Idea for this from Ikonboard - * Possible query values: INSERT, INSERT_SELECT, UPDATE, SELECT - * - * @param string $mode The mode to handle - * @param array $assoc_ary The SQL array to insert/update/select (key == column, value == data) - * - * @return string Query able to be used in SQL queries - * @access public - */ - public function sql_build_array($mode, $assoc_ary = false) - { - if (!is_array($assoc_ary)) - { - return false; - } - - $fields = $values = array(); - $query = ''; - - if ($mode == 'INSERT' || $mode == 'INSERT_SELECT') - { - foreach ($assoc_ary as $key => $var) - { - $fields[] = $key; - - if (is_array($var) && is_string($var[0])) - { - // This is used for INSERT_SELECT(s) - $values[] = $var[0]; - } - else - { - $values[] = $this->_sql_validate_value($var); - } - } - - $query = ($mode == 'INSERT') ? ' (' . implode(', ', $fields) . ') VALUES (' . implode(', ', $values) . ')' : ' (' . implode(', ', $fields) . ') SELECT ' . implode(', ', $values) . ' '; - } - else if ($mode == 'MULTI_INSERT') - { - trigger_error('The MULTI_INSERT query value is no longer supported. Please use sql_multi_insert() instead.', E_USER_ERROR); - } - else if ($mode == 'UPDATE' || $mode == 'SELECT') - { - foreach ($assoc_ary as $key => $var) - { - $values[] = "$key = " . $this->_sql_validate_value($var); - } - $query = implode(($mode == 'UPDATE') ? ', ' : ' AND ', $values); - } - - return $query; - } - - /** - * Build IN or NOT IN sql comparison string, uses <> or = on single element to improve comparison speed - * - * @param string $field Name of the sql column that shall be compared - * @param array $array Array of values that are allowed (IN) or not allowed (NOT IN) - * @param bool $negate True for NOT IN (), false for IN () (default) - * @param bool $allow_empty_set If true, allow $array to be empty - this function will return 1=1 or 1=0 then. - * - * @return string SQL statement able to be used in SQL queries - * @access public - */ - public function sql_in_set($field, $array, $negate = false, $allow_empty_set = false) - { - if (!sizeof($array)) - { - if (!$allow_empty_set) - { - // Print the backtrace to help identifying the location of the problematic code - $this->sql_error('No values specified for SQL IN comparison'); - } - else - { - // NOT IN () actually means everything so use a tautology - if ($negate) - { - return '1=1'; - } - // IN () actually means nothing so use a contradiction - else - { - return '1=0'; - } - } - } - - if (!is_array($array)) - { - $array = array($array); - } - - if (sizeof($array) == 1) - { - @reset($array); - $var = current($array); - - return $field . ($negate ? ' <> ' : ' = ') . $this->_sql_validate_value($var); - } - else - { - return $field . ($negate ? ' NOT IN ' : ' IN ') . '(' . implode(', ', array_map(array($this, '_sql_validate_value'), $array)) . ')'; - } - } - - /** - * Run more than one insert statement. - * - * @param string $table Table name to run the statements on - * @param array &$sql_ary Multi-dimensional array holding the statement data. - * - * @return bool False if no statements were executed. - * @access public - * @todo use sql_prepare_data() - */ - public function sql_multi_insert($table, &$sql_ary) - { - if (!sizeof($sql_ary)) - { - return false; - } - - if ($this->features['multi_insert']) - { - $ary = array(); - foreach ($sql_ary as $id => $_sql_ary) - { - // If by accident the sql array is only one-dimensional we build a normal insert statement - if (!is_array($_sql_ary)) - { - $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $sql_ary)); - return true; - } - - $values = array(); - foreach ($_sql_ary as $key => $var) - { - $values[] = $this->_sql_validate_value($var); - } - $ary[] = '(' . implode(', ', $values) . ')'; - } - - $this->sql_query('INSERT INTO ' . $table . ' ' . ' (' . implode(', ', array_keys($sql_ary[0])) . ') VALUES ' . implode(', ', $ary)); - } - else - { - foreach ($sql_ary as $ary) - { - if (!is_array($ary)) - { - return false; - } - - $this->sql_query('INSERT INTO ' . $table . ' ' . $this->sql_build_array('INSERT', $ary)); - } - } - - return true; - } - - /** - * Build sql statement from array for select and select distinct statements - * - * @todo add more in-depth explanation about all possible array keys and their effects. - * - * @param string $query Query value. Possible query values: SELECT, SELECT_DISTINCT - * @param string $array Array to build statement from - * - * @return string SQL Statement - * @access public - */ - public function sql_build_query($query, $array) - { - $sql = ''; - switch ($query) - { - case 'SELECT': - case 'SELECT_DISTINCT'; - - $sql = str_replace('_', ' ', $query) . ' ' . $array['SELECT'] . ' FROM '; - - $table_array = array(); - foreach ($array['FROM'] as $table_name => $alias) - { - if (is_array($alias)) - { - foreach ($alias as $multi_alias) - { - $table_array[] = $table_name . ' ' . $multi_alias; - } - } - else - { - $table_array[] = $table_name . ' ' . $alias; - } - } - - $sql .= $this->_sql_custom_build('FROM', implode(', ', $table_array)); - - if (!empty($array['LEFT_JOIN'])) - { - foreach ($array['LEFT_JOIN'] as $join) - { - $sql .= ' LEFT JOIN ' . key($join['FROM']) . ' ' . current($join['FROM']) . ' ON (' . $join['ON'] . ')'; - } - } - - if (!empty($array['WHERE'])) - { - $sql .= ' WHERE ' . $this->_sql_custom_build('WHERE', $array['WHERE']); - } - - if (!empty($array['GROUP_BY'])) - { - $sql .= ' GROUP BY ' . $array['GROUP_BY']; - } - - if (!empty($array['ORDER_BY'])) - { - $sql .= ' ORDER BY ' . $array['ORDER_BY']; - } - - break; - } - - return $sql; - } - - /** - * Display SQL Error message. - * - * The DB-specific information is retrieved by {@link phpbb_dbal::_sql_error() _sql_error()}. - * - * @param string $sql SQL statement which triggered the error - * - * @return mixed Returns sql error array if {@link phpbb_dbal::$return_on_error $return_on_error} is true. Else script is halted. - * @access public - */ - public function sql_error($sql = '') - { - // Set var to retrieve errored status - $this->sql_error_triggered = true; - $this->sql_error_sql = $sql; - - $this->sql_error_returned = $this->_sql_error(); - - if (!$this->return_on_error) - { - $sql_message = $this->sql_error_returned['message']; - $sql_code = $this->sql_error_returned['code']; - - $message = 'SQL ERROR [ ' . $this->sql_layer . ' ]' . (($sql_message) ? '<br /><br />' . $sql_message : '') . (($sql_code) ? ' [' . $sql_code . ']' : ''); - - // Show complete SQL error and path to administrators only - // Additionally show complete error on installation or if extended debug mode is enabled - // The phpbb::$base_config['debug_extra'] variable is for development only! - if ((phpbb::registered('acl') && phpbb::$acl->acl_get('a_')) || defined('IN_INSTALL') || phpbb::$base_config['debug_extra']) - { - $message .= ($sql) ? '<br /><br />SQL<br /><br />' . htmlspecialchars($sql) : ''; - $message .= '<br />'; - } - else - { - // If error occurs in initiating the session we need to use a pre-defined language string - // This could happen if the connection could not be established for example (then we are not able to grab the default language) - if (!phpbb::registered('user')) - { - $message .= '<br /><br />An sql error occurred while fetching this page. Please contact an administrator if this problem persists.'; - } - else - { - if (!empty(phpbb::$config['board_contact'])) - { - $message .= '<br /><br />' . phpbb::$user->lang('SQL_ERROR_OCCURRED', '<a href="mailto:' . htmlspecialchars(phpbb::$config['board_contact']) . '">', '</a>'); - } - else - { - $message .= '<br /><br />' . phpbb::$user->lang('SQL_ERROR_OCCURRED', '', ''); - } - } - } - - if ($this->transaction) - { - $this->sql_transaction('rollback'); - } - - if (strlen($message) > 1024) - { - // We need to define $msg_long_text here to circumvent text stripping. - global $msg_long_text; - $msg_long_text = $message; - - trigger_error(false, E_USER_ERROR); - } - - trigger_error($message, E_USER_ERROR); - } - - if ($this->transaction) - { - $this->sql_transaction('rollback'); - } - - return $this->sql_error_returned; - } - - /** - * Build SQL Report to explain queries, show statistics and runtime information. - * - * This function only executes if the GET parameter 'explain' is true and phpbb::$base_config['debug_extra'] enabled. - * - * @param string $mode The mode to handle. 'display' is used for displaying the report, all other modes are internal. - * @param string $query Query to document/explain. Only used internally to build the plan. - * - * @access public - */ - public function sql_report($mode, $query = '') - { - global $starttime; - - if (!phpbb_request::variable('explain', false)) - { - return false; - } - - if (!$query && $this->query_hold != '') - { - $query = $this->query_hold; - } - - switch ($mode) - { - case 'display': - $this->sql_close(); - - if (phpbb::registered('acm')) - { - phpbb::$acm->unload(); - } - - $mtime = explode(' ', microtime()); - $totaltime = $mtime[0] + $mtime[1] - $starttime; - - echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd"> - <html xmlns="http://www.w3.org/1999/xhtml" dir="ltr"> - <head> - <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" /> - <meta http-equiv="Content-Style-Type" content="text/css" /> - <meta http-equiv="imagetoolbar" content="no" /> - <title>SQL Report</title> - <link href="' . PHPBB_ROOT_PATH . 'adm/style/admin.css" rel="stylesheet" type="text/css" media="screen" /> - </head> - <body id="errorpage"> - <div id="wrap"> - <div id="page-header"> - <a href="' . phpbb::$url->build_url('explain') . '">Return to previous page</a> - </div> - <div id="page-body"> - <div id="acp"> - <div class="panel"> - <span class="corners-top"><span></span></span> - <div id="content"> - <h1>SQL Report</h1> - <br /> - <p><b>Page generated in ' . round($totaltime, 4) . " seconds with {$this->num_queries['normal']} queries" . (($this->num_queries['cached']) ? " + {$this->num_queries['cached']} " . (($this->num_queries['cached'] == 1) ? 'query' : 'queries') . ' returning data from cache' : '') . '</b></p> - - <p>Time spent on ' . $this->sql_layer . ' queries: <b>' . round($this->sql_time, 5) . 's</b> | Time spent on PHP: <b>' . round($totaltime - $this->sql_time, 5) . 's</b></p> - - <br /><br /> - ' . $this->sql_report . ' - </div> - <span class="corners-bottom"><span></span></span> - </div> - </div> - </div> - <div id="page-footer"> - Powered by phpBB © 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a> - </div> - </div> - </body> - </html>'; - - exit_handler(); - - break; - - case 'stop': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $this->sql_report .= ' - - <table cellspacing="1"> - <thead> - <tr> - <th>Query #' . $this->num_queries['total'] . '</th> - </tr> - </thead> - <tbody> - <tr> - <td class="row3"><textarea style="font-family:\'Courier New\',monospace;width:99%" rows="5" cols="10">' . preg_replace('/\t(AND|OR)(\W)/', "\$1\$2", htmlspecialchars(preg_replace('/[\s]*[\n\r\t]+[\n\r\s\t]*/', "\n", $query))) . '</textarea></td> - </tr> - </tbody> - </table> - - ' . $this->html_hold . ' - - <p style="text-align: center;"> - '; - - if ($this->query_result) - { - if (preg_match('/^(UPDATE|DELETE|REPLACE)/', $query)) - { - $this->sql_report .= 'Affected rows: <b>' . $this->sql_affectedrows($this->query_result) . '</b> | '; - } - $this->sql_report .= 'Before: ' . sprintf('%.5f', $this->curtime - $starttime) . 's | After: ' . sprintf('%.5f', $endtime - $starttime) . 's | Elapsed: <b>' . sprintf('%.5f', $endtime - $this->curtime) . 's</b>'; - } - else - { - $error = $this->sql_error(); - $this->sql_report .= '<b style="color: red">FAILED</b> - ' . $this->sql_layer . ' Error ' . $error['code'] . ': ' . htmlspecialchars($error['message']); - } - - $this->sql_report .= '</p><br /><br />'; - - $this->sql_time += $endtime - $this->curtime; - break; - - case 'start': - $this->query_hold = $query; - $this->html_hold = ''; - - $this->_sql_report($mode, $query); - - $this->curtime = explode(' ', microtime()); - $this->curtime = $this->curtime[0] + $this->curtime[1]; - - break; - - case 'add_select_row': - - $html_table = func_get_arg(2); - $row = func_get_arg(3); - - if (!$html_table && sizeof($row)) - { - $html_table = true; - $this->html_hold .= '<table cellspacing="1"><tr>'; - - foreach (array_keys($row) as $val) - { - $this->html_hold .= '<th>' . (($val) ? ucwords(str_replace('_', ' ', $val)) : ' ') . '</th>'; - } - $this->html_hold .= '</tr>'; - } - $this->html_hold .= '<tr>'; - - $class = 'row1'; - foreach (array_values($row) as $val) - { - $class = ($class == 'row1') ? 'row2' : 'row1'; - $this->html_hold .= '<td class="' . $class . '">' . (($val) ? $val : ' ') . '</td>'; - } - $this->html_hold .= '</tr>'; - - return $html_table; - - break; - - case 'fromcache': - - $this->_sql_report($mode, $query); - - break; - - case 'record_fromcache': - - $endtime = func_get_arg(2); - $splittime = func_get_arg(3); - - $time_cache = $endtime - $this->curtime; - $time_db = $splittime - $endtime; - $color = ($time_db > $time_cache) ? 'green' : 'red'; - - $this->sql_report .= '<table cellspacing="1"><thead><tr><th>Query results obtained from the cache</th></tr></thead><tbody><tr>'; - $this->sql_report .= '<td class="row3"><textarea style="font-family:\'Courier New\',monospace;width:99%" rows="5" cols="10">' . preg_replace('/\t(AND|OR)(\W)/', "\$1\$2", htmlspecialchars(preg_replace('/[\s]*[\n\r\t]+[\n\r\s\t]*/', "\n", $query))) . '</textarea></td></tr></tbody></table>'; - $this->sql_report .= '<p style="text-align: center;">'; - $this->sql_report .= 'Before: ' . sprintf('%.5f', $this->curtime - $starttime) . 's | After: ' . sprintf('%.5f', $endtime - $starttime) . 's | Elapsed [cache]: <b style="color: ' . $color . '">' . sprintf('%.5f', ($time_cache)) . 's</b> | Elapsed [db]: <b>' . sprintf('%.5f', $time_db) . 's</b></p><br /><br />'; - - // Pad the start time to not interfere with page timing - $starttime += $time_db; - - break; - - default: - - $this->_sql_report($mode, $query); - - break; - } - - return true; - } - - /** - * Get stored data from SQL cache and fill the relevant cach rowset. - * - * @param string $query The query cached. - * - * @return bool True if the caching was successful, else false - * @access private - */ - private function sql_get_cache($query) - { - if (!phpbb::registered('acm') || !phpbb::$acm->supported('sql')) - { - return false; - } - - // Remove extra spaces and tabs - $var_name = preg_replace('/[\n\r\s\t]+/', ' ', $query); - $var_name = md5($this->sql_layer . '_' . $var_name); - - $data = phpbb::$acm->get_sql($var_name); - - if ($data !== false) - { - $this->query_result = ++$this->cache_index; - $this->cache_rowset[$this->query_result] = $data['rowset']; - - return true; - } - - return false; - } - - /** - * Put query to cache. - * - * @param string $query The query cached. - * @param int $cache_ttl Cache lifetime in seconds. - * - * @return bool True if the caching was successful, else false - * @access private - */ - private function sql_put_cache($query, $cache_ttl) - { - if (!phpbb::registered('acm') || !phpbb::$acm->supported('sql')) - { - return false; - } - - // Prepare the data - $var_name = preg_replace('/[\n\r\s\t]+/', ' ', $query); - $var_name = md5($this->sql_layer . '_' . $var_name); - - $data = array( - 'query' => $query, - 'rowset' => array(), - ); - - while ($row = $this->sql_fetchrow($this->query_result)) - { - $data['rowset'][] = $row; - } - $this->sql_freeresult($this->query_result); - - phpbb::$acm->put_sql($var_name, $data, $cache_ttl); - - $this->query_result = ++$this->cache_index; - $this->cache_rowset[$this->query_result] = $data['rowset']; - @reset($this->cache_rowset[$this->query_result]); - - return true; - } - - /** - * Check if an sql cache exist for a specific query id. - * - * @param int $query_id The query_id to check (int) - * - * @return bool True if an cache entry exists. - * @access private - */ - private function sql_cache_exists($query_id) - { - return is_int($query_id) && isset($this->cache_rowset[$query_id]); - } - - /** - * Fetch row from cache (database). Used in {@link phpbb_dbal::sql_fetchrow() sql_fetchrow()}. - * - * @param int $query_id The query_id to fetch from. - * - * @return array The result row - * @access private - */ - private function sql_cache_fetchrow($query_id) - { - list(, $row) = each($this->cache_rowset[$query_id]); - return ($row !== NULL) ? $row : false; - } - - /** - * Fetch a field from the current row of a cached database result (database). Used in {@link phpbb_dbal::sql_fetchfield() sql_fetchfield()}. - * - * @param int $query_id The query_id to fetch from. - * @param string $field The column name. - * - * @return array The field data - * @access private - */ - private function sql_cache_fetchfield($query_id, $field) - { - $row = current($this->cache_rowset[$query_id]); - return ($row !== false && isset($row[$field])) ? $row[$field] : false; - } - - /** - * Free memory used for a cached database result (database). Used in {@link phpbb_dbal::sql_freeresult() sql_freeresult()}. - * - * @param int $query_id The query_id. - * - * @return bool True on success - * @access private - */ - private function sql_cache_freeresult($query_id) - { - if (!isset($this->cache_rowset[$query_id])) - { - return false; - } - - if (($key = $this->sql_get_result_key($query_id)) !== false) - { - unset($this->open_queries[$key]); - } - - unset($this->cache_rowset[$query_id]); - return true; - } - - /** - * Function for validating SQL values - * - * @param mixed Value. Typecasted to it's type. - * - * @return mixed Typecasted value. - * @access private - */ - private function _sql_validate_value($var) - { - if (is_null($var)) - { - return 'NULL'; - } - else if (is_string($var)) - { - return "'" . $this->sql_escape($var) . "'"; - } - else - { - return (is_bool($var)) ? intval($var) : $var; - } - } - - /** - * Add "one" to query count. - * - * @param bool $cached If true, add one to cached query count. Otherwise to non-cached query count - * @access private - */ - private function sql_add_num_queries($cached = false) - { - $this->num_queries['cached'] += ($cached !== false) ? 1 : 0; - $this->num_queries['normal'] += ($cached !== false) ? 0 : 1; - $this->num_queries['total'] += 1; - } - - /** - * Get SQL result key for storing open connection - * - * @param string $query_result Query result id/resource/object - * - * @return mixed Key usable as array key. False if storing is not possible. - * @access private - */ - private function sql_get_result_key($query_result) - { - $key = $query_result; - - if (is_object($query_result)) - { - $key = false; - } - else if (is_resource($query_result)) - { - $key = (int) $query_result; - } - - return $key; - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/firebird.php b/phpBB/includes/db/firebird.php deleted file mode 100644 index be704ad835..0000000000 --- a/phpBB/includes/db/firebird.php +++ /dev/null @@ -1,453 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Firebird/Interbase Database Abstraction Layer -* Minimum Requirement: 2.0+ -* @package dbal -*/ -class phpbb_dbal_firebird extends phpbb_dbal -{ - /** - * @var string Database type. No distinction between versions or used extensions. - */ - public $dbms_type = 'firebird'; - - /** - * @var array Database type map, column layout information - */ - public $dbms_type_map = array( - 'INT:' => 'INTEGER', - 'BINT' => 'DOUBLE PRECISION', - 'UINT' => 'INTEGER', - 'UINT:' => 'INTEGER', - 'TINT:' => 'INTEGER', - 'USINT' => 'INTEGER', - 'BOOL' => 'INTEGER', - 'VCHAR' => 'VARCHAR(255) CHARACTER SET NONE', - 'VCHAR:' => 'VARCHAR(%d) CHARACTER SET NONE', - 'CHAR:' => 'CHAR(%d) CHARACTER SET NONE', - 'XSTEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', - 'STEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', - 'TEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', - 'MTEXT' => 'BLOB SUB_TYPE TEXT CHARACTER SET NONE', - 'XSTEXT_UNI'=> 'VARCHAR(100) CHARACTER SET UTF8', - 'STEXT_UNI' => 'VARCHAR(255) CHARACTER SET UTF8', - 'TEXT_UNI' => 'BLOB SUB_TYPE TEXT CHARACTER SET UTF8', - 'MTEXT_UNI' => 'BLOB SUB_TYPE TEXT CHARACTER SET UTF8', - 'TIMESTAMP' => 'INTEGER', - 'DECIMAL' => 'DOUBLE PRECISION', - 'DECIMAL:' => 'DOUBLE PRECISION', - 'PDECIMAL' => 'DOUBLE PRECISION', - 'PDECIMAL:' => 'DOUBLE PRECISION', - 'VCHAR_UNI' => 'VARCHAR(255) CHARACTER SET UTF8', - 'VCHAR_UNI:'=> 'VARCHAR(%d) CHARACTER SET UTF8', - 'VARBINARY' => 'CHAR(255) CHARACTER SET NONE', - ); - - /** - * @var string Last query executed. We need this for sql_nextid() - */ - var $last_query_text = ''; - - /** - * @var resource Attached service handle. - */ - var $service_handle = false; - - /** - * @var array Database features - */ - public $features = array( - 'multi_insert' => false, - 'count_distinct' => true, - 'multi_table_deletion' => true, - 'truncate' => false, - ); - - /** - * Connect to server. See {@link phpbb_dbal::sql_connect() sql_connect()} for details. - */ - public function sql_connect($server, $user, $password, $database, $port = false, $persistency = false , $new_link = false) - { - $this->persistency = $persistency; - $this->user = $user; - $this->server = $server . (($port) ? ':' . $port : ''); - $this->dbname = str_replace('\\', '/', $database); - - // There are three possibilities to connect to an interbase db - if (!$this->server) - { - $use_database = $this->dbname; - } - else if (strpos($this->server, '//') === 0) - { - $use_database = $this->server . $this->dbname; - } - else - { - $use_database = $this->server . ':' . $this->dbname; - } - - $this->db_connect_id = ($this->persistency) ? @ibase_pconnect($use_database, $this->user, $password, false, false, 3) : @ibase_connect($use_database, $this->user, $password, false, false, 3); - - if (!$this->db_connect_id) - { - return $this->sql_error(''); - } - - $this->service_handle = ($this->server) ? @ibase_service_attach($this->server, $this->user, $password) : false; - - return $this->db_connect_id; - } - - /** - * Version information about used database. See {@link phpbb_dbal::sql_server_info() sql_server_info()} for details. - */ - public function sql_server_info($raw = false) - { - if (!phpbb::registered('acm') || ($this->sql_server_version = phpbb::$acm->get('#firebird_version')) === false) - { - $version = false; - - if ($this->service_handle !== false) - { - $val = @ibase_server_info($this->service_handle, IBASE_SVC_SERVER_VERSION); - preg_match('#V([\d.]+)#', $val, $version); - $version = (!empty($version[1])) ? $version[1] : false; - } - - $this->sql_server_version = (!$version) ? '2.0' : $version; - - if (phpbb::registered('acm')) - { - phpbb::$acm->put('#firebird_version', $this->sql_server_version); - } - } - - return ($raw) ? $this->sql_server_version : 'Firebird/Interbase ' . $this->sql_server_version; - } - - /** - * DB-specific base query method. See {@link phpbb_dbal::_sql_query() _sql_query()} for details. - */ - protected function _sql_query($query) - { - $this->last_query_text = $query; - - $array = array(); - - // We overcome Firebird's 32767 char limit by binding vars - if (strlen($query) > 32767) - { - if (preg_match('/^(INSERT INTO[^(]++)\\(([^()]+)\\) VALUES[^(]++\\((.*?)\\)$/s', $query, $regs)) - { - if (strlen($regs[3]) > 32767) - { - preg_match_all('/\'(?:[^\']++|\'\')*+\'|[\d-.]+/', $regs[3], $vals, PREG_PATTERN_ORDER); - - $inserts = $vals[0]; - unset($vals); - - foreach ($inserts as $key => $value) - { - // check to see if this thing is greater than the max + 'x2 - if (!empty($value) && $value[0] === "'" && strlen($value) > 32769) - { - $inserts[$key] = '?'; - $array[] = str_replace("''", "'", substr($value, 1, -1)); - } - } - - $query = $regs[1] . '(' . $regs[2] . ') VALUES (' . implode(', ', $inserts) . ')'; - } - } - else if (preg_match('/^(UPDATE ([\\w_]++)\\s+SET )([\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|\\d+)(?:,\\s*[\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+))*+)\\s+(WHERE.*)$/s', $query, $data)) - { - if (strlen($data[3]) > 32767) - { - $update = $data[1]; - $where = $data[4]; - preg_match_all('/(\\w++)\\s*=\\s*(\'(?:[^\']++|\'\')*+\'|[\d-.]++)/', $data[3], $temp, PREG_SET_ORDER); - unset($data); - - $cols = array(); - foreach ($temp as $value) - { - // check to see if this thing is greater than the max + 'x2 - if (!empty($value[2]) && $value[2][0] === "'" && strlen($value[2]) > 32769) - { - $array[] = str_replace("''", "'", substr($value[2], 1, -1)); - $cols[] = $value[1] . '=?'; - } - else - { - $cols[] = $value[1] . '=' . $value[2]; - } - } - - $query = $update . implode(', ', $cols) . ' ' . $where; - unset($cols); - } - } - } - - if (sizeof($array)) - { - $p_query = @ibase_prepare($this->db_connect_id, $query); - array_unshift($array, $p_query); - $result = call_user_func_array('ibase_execute', $array); - unset($array); - } - else - { - $result = @ibase_query($this->db_connect_id, $query); - - if ($result && !$this->transaction) - { - @ibase_commit_ret(); - } - } - - return $result; - } - - /** - * Build LIMIT query and run it. See {@link phpbb_dbal::_sql_query_limit() _sql_query_limit()} for details. - */ - protected function _sql_query_limit($query, $total, $offset, $cache_ttl) - { - $query = 'SELECT FIRST ' . $total . ((!empty($offset)) ? ' SKIP ' . $offset : '') . substr($query, 6); - return $this->sql_query($query, $cache_ttl); - } - - /** - * Close sql connection. See {@link phpbb_dbal::_sql_close() _sql_close()} for details. - */ - protected function _sql_close() - { - if ($this->service_handle !== false) - { - @ibase_service_detach($this->service_handle); - } - - return @ibase_close($this->db_connect_id); - } - - /** - * SQL Transaction. See {@link phpbb_dbal::_sql_transaction() _sql_transaction()} for details. - */ - protected function _sql_transaction($status) - { - switch ($status) - { - case 'begin': - return true; - break; - - case 'commit': - return @ibase_commit(); - break; - - case 'rollback': - return @ibase_rollback(); - break; - } - - return true; - } - - /** - * Return number of affected rows. See {@link phpbb_dbal::sql_affectedrows() sql_affectedrows()} for details. - */ - public function sql_affectedrows() - { - return ($this->db_connect_id) ? @ibase_affected_rows($this->db_connect_id) : false; - } - - /** - * Get last inserted id after insert statement. See {@link phpbb_dbal::sql_nextid() sql_nextid()} for details. - */ - public function sql_nextid() - { - if (!$this->query_result || !$this->last_query_text) - { - return false; - } - - if (preg_match('#^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)#i', $this->last_query_text, $tablename)) - { - $sql = 'SELECT GEN_ID(' . $tablename[1] . '_gen, 0) AS new_id FROM RDB$DATABASE'; - - if (!($temp_q_id = @ibase_query($this->db_connect_id, $sql))) - { - return false; - } - - $temp_result = @ibase_fetch_assoc($temp_q_id); - @ibase_free_result($temp_q_id); - - return ($temp_result) ? $temp_result['NEW_ID'] : false; - } - - return false; - } - - /** - * Fetch current row. See {@link phpbb_dbal::_sql_fetchrow() _sql_fetchrow()} for details. - */ - protected function _sql_fetchrow($query_id) - { - $cur_row = @ibase_fetch_object($query_id, IBASE_TEXT); - - if (!$cur_row) - { - return false; - } - - foreach (get_object_vars($cur_row) as $key => $value) - { - $row[strtolower($key)] = (is_string($value)) ? trim(str_replace(array("\\0", "\\n"), array("\0", "\n"), $value)) : $value; - } - - return (sizeof($row)) ? $row : false; - } - - /** - * Free query result. See {@link phpbb_dbal::_sql_freeresult() _sql_freeresult()} for details. - */ - protected function _sql_freeresult($query_id) - { - return @ibase_free_result($query_id); - } - - /** - * Correctly adjust LIKE expression for special characters. See {@link phpbb_dbal::_sql_like_expression() _sql_like_expression()} for details. - */ - protected function _sql_like_expression($expression) - { - return $expression . " ESCAPE '\\'"; - } - - /** - * Escape string used in sql query. See {@link phpbb_dbal::sql_escape() sql_escape()} for details. - */ - public function sql_escape($msg) - { - return str_replace(array("'", "\0"), array("''", ''), $msg); - } - - /** - * Expose a DBMS specific function. See {@link phpbb_dbal::sql_function() sql_function()} for details. - */ - public function sql_function($type, $col) - { - switch ($type) - { - case 'length_varchar': - case 'length_text': - return 'OCTET_LENGTH(' . $col . ')'; - break; - } - } - - /** - * Handle data by using prepared statements. See {@link phpbb_dbal::sql_handle_data() sql_handle_data()} for details. - public function sql_handle_data($type, $table, $data, $where = '') - { - if ($type == 'INSERT') - { - $stmt = ibase_prepare($this->db_connect_id, "INSERT INTO $table (". implode(', ', array_keys($data)) . ") VALUES (" . substr(str_repeat('?, ', sizeof($data)) ,0, -1) . ')'); - } - else - { - $query = "UPDATE $table SET "; - - $set = array(); - foreach (array_keys($data) as $key) - { - $set[] = "$key = ?"; - } - $query .= implode(', ', $set); - - if ($where !== '') - { - $query .= $where; - } - - $stmt = ibase_prepare($this->db_connect_id, $query); - } - - // get the stmt onto the top of the function arguments - array_unshift($data, $stmt); - - call_user_func_array('ibase_execute', $data); - } - */ - - /** - * Build DB-specific query bits. See {@link phpbb_dbal::_sql_custom_build() _sql_custom_build()} for details. - */ - protected function _sql_custom_build($stage, $data) - { - return $data; - } - - /** - * return sql error array. See {@link phpbb_dbal::_sql_error() _sql_error()} for details. - */ - protected function _sql_error() - { - return array( - 'message' => @ibase_errmsg(), - 'code' => @ibase_errcode() - ); - } - - /** - * Run DB-specific code to build SQL Report to explain queries, show statistics and runtime information. See {@link phpbb_dbal::_sql_report() _sql_report()} for details. - */ - protected function _sql_report($mode, $query = '') - { - switch ($mode) - { - case 'start': - break; - - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @ibase_query($this->db_connect_id, $query); - while ($void = @ibase_fetch_object($result, IBASE_TEXT)) - { - // Take the time spent on parsing rows into account - } - @ibase_free_result($result); - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/mssql.php b/phpBB/includes/db/mssql.php deleted file mode 100644 index d0dcb590fd..0000000000 --- a/phpBB/includes/db/mssql.php +++ /dev/null @@ -1,382 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* MSSQL Database Abstraction Layer -* Minimum Requirement is MSSQL 2000+ -* @package dbal -*/ -class phpbb_dbal_mssql extends phpbb_dbal -{ - /** - * @var string Database type. No distinction between versions or used extensions. - */ - public $dbms_type = 'mssql'; - - /** - * @var array Database type map, column layout information - */ - public $dbms_type_map = array( - 'INT:' => '[int]', - 'BINT' => '[float]', - 'UINT' => '[int]', - 'UINT:' => '[int]', - 'TINT:' => '[int]', - 'USINT' => '[int]', - 'BOOL' => '[int]', - 'VCHAR' => '[varchar] (255)', - 'VCHAR:' => '[varchar] (%d)', - 'CHAR:' => '[char] (%d)', - 'XSTEXT' => '[varchar] (1000)', - 'STEXT' => '[varchar] (3000)', - 'TEXT' => '[varchar] (8000)', - 'MTEXT' => '[text]', - 'XSTEXT_UNI'=> '[varchar] (100)', - 'STEXT_UNI' => '[varchar] (255)', - 'TEXT_UNI' => '[varchar] (4000)', - 'MTEXT_UNI' => '[text]', - 'TIMESTAMP' => '[int]', - 'DECIMAL' => '[float]', - 'DECIMAL:' => '[float]', - 'PDECIMAL' => '[float]', - 'PDECIMAL:' => '[float]', - 'VCHAR_UNI' => '[varchar] (255)', - 'VCHAR_UNI:'=> '[varchar] (%d)', - 'VARBINARY' => '[varchar] (255)', - ); - - /** - * Connect to server. See {@link phpbb_dbal::sql_connect() sql_connect()} for details. - */ - public function sql_connect($server, $user, $password, $database, $port = false, $persistency = false , $new_link = false) - { - $this->persistency = $persistency; - $this->user = $user; - $this->dbname = $database; - $this->port = $port; - - $port_delimiter = (defined('PHP_OS') && substr(PHP_OS, 0, 3) === 'WIN') ? ',' : ':'; - $this->server = $server . (($this->port) ? $port_delimiter . $this->port : ''); - - @ini_set('mssql.charset', 'UTF-8'); - @ini_set('mssql.textlimit', 2147483647); - @ini_set('mssql.textsize', 2147483647); - - $this->db_connect_id = ($this->persistency) ? @mssql_pconnect($this->server, $this->user, $password, $new_link) : @mssql_connect($this->server, $this->user, $password, $new_link); - - if (!$this->db_connect_id || !$this->dbname) - { - return $this->sql_error(phpbb::$last_notice['message']); - } - - if (!@mssql_select_db($this->dbname, $this->db_connect_id)) - { - return $this->sql_error(''); - } - - return $this->db_connect_id; - } - - /** - * Version information about used database. See {@link phpbb_dbal::sql_server_info() sql_server_info()} for details. - */ - public function sql_server_info($raw = false) - { - if (!phpbb::registered('acm') || ($this->sql_server_version = phpbb::$acm->get('#mssql_version')) === false) - { - $result_id = @mssql_query("SELECT SERVERPROPERTY('productversion'), SERVERPROPERTY('productlevel'), SERVERPROPERTY('edition')", $this->db_connect_id); - - $row = false; - if ($result_id) - { - $row = @mssql_fetch_assoc($result_id); - @mssql_free_result($result_id); - } - - $this->sql_server_version = ($row) ? trim(implode(' ', $row)) : 0; - - if (phpbb::registered('acm')) - { - phpbb::$acm->put('#mssql_version', $this->sql_server_version); - } - } - - if ($raw) - { - return $this->sql_server_version; - } - - return ($this->sql_server_version) ? 'MSSQL<br />' . $this->sql_server_version : 'MSSQL'; - } - - /** - * DB-specific base query method. See {@link phpbb_dbal::_sql_query() _sql_query()} for details. - */ - protected function _sql_query($query) - { - return @mssql_query($query, $this->db_connect_id); - } - - /** - * Build LIMIT query and run it. See {@link phpbb_dbal::_sql_query_limit() _sql_query_limit()} for details. - */ - protected function _sql_query_limit($query, $total, $offset, $cache_ttl) - { - // Since TOP is only returning a set number of rows we won't need it if total is set to 0 (return all rows) - if ($total) - { - // We need to grab the total number of rows + the offset number of rows to get the correct result - if (strpos($query, 'SELECT DISTINCT') === 0) - { - $query = 'SELECT DISTINCT TOP ' . ($total + $offset) . ' ' . substr($query, 15); - } - else - { - $query = 'SELECT TOP ' . ($total + $offset) . ' ' . substr($query, 6); - } - } - - $result = $this->sql_query($query, $cache_ttl); - - // Seek by $offset rows - if ($offset) - { - @mssql_data_seek($result, $offset); - } - - return $result; - } - - /** - * Close sql connection. See {@link phpbb_dbal::_sql_close() _sql_close()} for details. - */ - protected function _sql_close() - { - return @mssql_close($this->db_connect_id); - } - - /** - * SQL Transaction. See {@link phpbb_dbal::_sql_transaction() _sql_transaction()} for details. - */ - protected function _sql_transaction($status) - { - switch ($status) - { - case 'begin': - return @mssql_query('BEGIN TRANSACTION', $this->db_connect_id); - break; - - case 'commit': - return @mssql_query('COMMIT TRANSACTION', $this->db_connect_id); - break; - - case 'rollback': - return @mssql_query('ROLLBACK TRANSACTION', $this->db_connect_id); - break; - } - - return true; - } - - /** - * Return number of affected rows. See {@link phpbb_dbal::sql_affectedrows() sql_affectedrows()} for details. - */ - public function sql_affectedrows() - { - return ($this->db_connect_id) ? @mssql_rows_affected($this->db_connect_id) : false; - } - - /** - * Get last inserted id after insert statement. See {@link phpbb_dbal::sql_nextid() sql_nextid()} for details. - */ - public function sql_nextid() - { - $result_id = @mssql_query('SELECT SCOPE_IDENTITY()', $this->db_connect_id); - - if ($result_id) - { - if ($row = @mssql_fetch_assoc($result_id)) - { - @mssql_free_result($result_id); - return $row['computed']; - } - @mssql_free_result($result_id); - } - - return false; - } - - /** - * Fetch current row. See {@link phpbb_dbal::_sql_fetchrow() _sql_fetchrow()} for details. - */ - protected function _sql_fetchrow($query_id) - { - $row = @mssql_fetch_assoc($query_id); - - // I hope i am able to remove this later... hopefully only a PHP or MSSQL bug - if ($row) - { - foreach ($row as $key => $value) - { - $row[$key] = ($value === ' ' || $value === NULL) ? '' : $value; - } - } - - return $row; - } - - /** - * Free query result. See {@link phpbb_dbal::_sql_freeresult() _sql_freeresult()} for details. - */ - protected function _sql_freeresult($query_id) - { - return @mssql_free_result($query_id); - } - - /** - * Correctly adjust LIKE expression for special characters. See {@link phpbb_dbal::_sql_like_expression() _sql_like_expression()} for details. - */ - protected function _sql_like_expression($expression) - { - return $expression . " ESCAPE '\\'"; - } - - /** - * Escape string used in sql query. See {@link phpbb_dbal::sql_escape() sql_escape()} for details. - */ - public function sql_escape($msg) - { - return str_replace(array("'", "\0"), array("''", ''), $msg); - } - - /** - * Expose a DBMS specific function. See {@link phpbb_dbal::sql_function() sql_function()} for details. - */ - public function sql_function($type, $col) - { - switch ($type) - { - case 'length_varchar': - case 'length_text': - return 'DATALENGTH(' . $col . ')'; - break; - } - } - - /** - * Handle data by using prepared statements. See {@link phpbb_dbal::sql_handle_data() sql_handle_data()} for details. - public function sql_handle_data($type, $table, $data, $where = '') - { - } - */ - - /** - * Build DB-specific query bits. See {@link phpbb_dbal::_sql_custom_build() _sql_custom_build()} for details. - */ - protected function _sql_custom_build($stage, $data) - { - return $data; - } - - /** - * return sql error array. See {@link phpbb_dbal::_sql_error() _sql_error()} for details. - */ - protected function _sql_error() - { - $error = array( - 'message' => @mssql_get_last_message(), - 'code' => '' - ); - - // Get error code number - $result_id = @mssql_query('SELECT @@ERROR as code', $this->db_connect_id); - if ($result_id) - { - $row = @mssql_fetch_assoc($result_id); - $error['code'] = $row['code']; - @mssql_free_result($result_id); - } - - // Get full error message if possible - $sql = 'SELECT CAST(description as varchar(255)) as message - FROM master.dbo.sysmessages - WHERE error = ' . $error['code']; - $result_id = @mssql_query($sql); - - if ($result_id) - { - $row = @mssql_fetch_assoc($result_id); - if (!empty($row['message'])) - { - $error['message'] .= '<br />' . $row['message']; - } - @mssql_free_result($result_id); - } - - return $error; - } - - /** - * Run DB-specific code to build SQL Report to explain queries, show statistics and runtime information. See {@link phpbb_dbal::_sql_report() _sql_report()} for details. - */ - protected function _sql_report($mode, $query = '') - { - switch ($mode) - { - case 'start': - $html_table = false; - @mssql_query('SET SHOWPLAN_TEXT ON;', $this->db_connect_id); - if ($result = @mssql_query($query, $this->db_connect_id)) - { - @mssql_next_result($result); - while ($row = @mssql_fetch_row($result)) - { - $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); - } - } - @mssql_query('SET SHOWPLAN_TEXT OFF;', $this->db_connect_id); - @mssql_free_result($result); - - if ($html_table) - { - $this->html_hold .= '</table>'; - } - break; - - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @mssql_query($query, $this->db_connect_id); - while ($void = @mssql_fetch_assoc($result)) - { - // Take the time spent on parsing rows into account - } - @mssql_free_result($result); - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/mssql_2005.php b/phpBB/includes/db/mssql_2005.php deleted file mode 100644 index 4206e1f7e3..0000000000 --- a/phpBB/includes/db/mssql_2005.php +++ /dev/null @@ -1,350 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -include_once(PHPBB_ROOT_PATH . 'includes/db/dbal.' . PHP_EXT); - -/** -* MSSQL Database Abstraction Layer -* Minimum Requirement is MSSQL 2005+ -* @package dbal -*/ -class phpbb_dbal_mssql_2005 extends phpbb_dbal -{ - /** - * @var string Database type. No distinction between versions or used extensions. - */ - public $dbms_type = 'mssql'; - - /** - * @var array Database type map, column layout information - */ - public $dbms_type_map = array( - 'INT:' => '[int]', - 'BINT' => '[float]', - 'UINT' => '[int]', - 'UINT:' => '[int]', - 'TINT:' => '[int]', - 'USINT' => '[int]', - 'BOOL' => '[int]', - 'VCHAR' => '[varchar] (255)', - 'VCHAR:' => '[varchar] (%d)', - 'CHAR:' => '[char] (%d)', - 'XSTEXT' => '[varchar] (1000)', - 'STEXT' => '[varchar] (3000)', - 'TEXT' => '[varchar] (8000)', - 'MTEXT' => '[text]', - 'XSTEXT_UNI'=> '[varchar] (100)', - 'STEXT_UNI' => '[varchar] (255)', - 'TEXT_UNI' => '[varchar] (4000)', - 'MTEXT_UNI' => '[text]', - 'TIMESTAMP' => '[int]', - 'DECIMAL' => '[float]', - 'DECIMAL:' => '[float]', - 'PDECIMAL' => '[float]', - 'PDECIMAL:' => '[float]', - 'VCHAR_UNI' => '[varchar] (255)', - 'VCHAR_UNI:'=> '[varchar] (%d)', - 'VARBINARY' => '[varchar] (255)', - ); - - /** - * Connect to server. See {@link phpbb_dbal::sql_connect() sql_connect()} for details. - */ - public function sql_connect($server, $user, $password, $database, $port = false, $persistency = false , $new_link = false) - { - $this->persistency = $persistency; - $this->user = $user; - $this->server = $server . (($port) ? ':' . $port : ''); - $this->dbname = $database; - $this->port = $port; - - $conn_info = array(); - if ($this->user) - { - $conn_info['UID'] = $this->user; - } - - if ($password) - { - $conn_info['PWD'] = $password; - } - - $this->db_connect_id = @sqlsrv_connect($this->server, $conn_info); - - if (!$this->db_connect_id || !$this->dbname) - { - return $this->sql_error(''); - } - - if (!@sqlsrv_query($this->db_connect_id, 'USE ' . $this->dbname)) - { - return $this->sql_error(''); - } - - return $this->db_connect_id; - } - - /** - * Version information about used database. See {@link phpbb_dbal::sql_server_info() sql_server_info()} for details. - */ - public function sql_server_info($raw = false) - { - if (!phpbb::registered('acm') || ($this->sql_server_version = phpbb::$acm->get('#mssql2005_version')) === false) - { - $server_info = @sqlsrv_server_info($this->db_connect_id); - - $this->sql_server_version = (!empty($server_info['SQLServerVersion'])) ? $server_info['SQLServerVersion'] : 0; - - if (phpbb::registered('acm')) - { - phpbb::$acm->put('#mssql2005_version', $this->sql_server_version); - } - } - - return ($raw) ? $this->sql_server_version : 'MSSQL ' . $this->sql_server_version; - } - - /** - * DB-specific base query method. See {@link phpbb_dbal::_sql_query() _sql_query()} for details. - */ - protected function _sql_query($query) - { - if (strpos($query, 'BEGIN') === 0 || strpos($query, 'COMMIT') === 0) - { - return true; - } - - return @sqlsrv_query($this->db_connect_id, $query); - } - - /** - * Build LIMIT query and run it. See {@link phpbb_dbal::_sql_query_limit() _sql_query_limit()} for details. - */ - protected function _sql_query_limit($query, $total, $offset, $cache_ttl) - { - // Since TOP is only returning a set number of rows we won't need it if total is set to 0 (return all rows) - if ($total) - { - // We need to grab the total number of rows + the offset number of rows to get the correct result - if (strpos($query, 'SELECT DISTINCT') === 0) - { - $query = 'SELECT DISTINCT TOP ' . ($total + $offset) . ' ' . substr($query, 15); - } - else - { - $query = 'SELECT TOP ' . ($total + $offset) . ' ' . substr($query, 6); - } - } - - $result = $this->sql_query($query, $cache_ttl); - - // Seek by $offset rows - if ($offset) - { - // We do not fetch the row for rownum == 0 because then the next resultset would be the second row - for ($i = 0; $i < $offset; $i++) - { - if (!$this->sql_fetchrow($result)) - { - return false; - } - } - } - - return $result; - } - - /** - * Close sql connection. See {@link phpbb_dbal::_sql_close() _sql_close()} for details. - */ - protected function _sql_close() - { - return @sqlsrv_close($this->db_connect_id); - } - - /** - * SQL Transaction. See {@link phpbb_dbal::_sql_transaction() _sql_transaction()} for details. - */ - protected function _sql_transaction($status) - { - switch ($status) - { - case 'begin': - return @sqlsrv_query($this->db_connect_id, 'BEGIN TRANSACTION'); - break; - - case 'commit': - return @sqlsrv_query($this->db_connect_id, 'COMMIT TRANSACTION'); - break; - - case 'rollback': - return @sqlsrv_query($this->db_connect_id, 'ROLLBACK TRANSACTION'); - break; - } - - return true; - } - - /** - * Return number of affected rows. See {@link phpbb_dbal::sql_affectedrows() sql_affectedrows()} for details. - */ - public function sql_affectedrows() - { - return ($this->db_connect_id) ? @sqlsrv_rows_affected($this->db_connect_id) : false; - } - - /** - * Get last inserted id after insert statement. See {@link phpbb_dbal::sql_nextid() sql_nextid()} for details. - */ - public function sql_nextid() - { - $result_id = @sqlsrv_query($this->db_connect_id, 'SELECT SCOPE_IDENTITY()'); - if ($result_id) - { - if ($row = @sqlsrv_fetch_array($result_id, SQLSRV_FETCH_ASSOC)) - { - @sqlsrv_free_stmt($result_id); - return $row['computed']; - } - @sqlsrv_free_stmt($result_id); - } - - return false; - } - - /** - * Fetch current row. See {@link phpbb_dbal::_sql_fetchrow() _sql_fetchrow()} for details. - */ - protected function _sql_fetchrow($query_id) - { - $row = @sqlsrv_fetch_array($query_id, SQLSRV_FETCH_ASSOC); - - // I hope i am able to remove this later... hopefully only a PHP or MSSQL bug - if ($row) - { - foreach ($row as $key => $value) - { - $row[$key] = ($value === ' ' || $value === NULL) ? '' : $value; - } - } - - return $row; - } - - /** - * Free query result. See {@link phpbb_dbal::_sql_freeresult() _sql_freeresult()} for details. - */ - protected function _sql_freeresult($query_id) - { - return @sqlsrv_free_stmt($query_id); - } - - /** - * Correctly adjust LIKE expression for special characters. See {@link phpbb_dbal::_sql_like_expression() _sql_like_expression()} for details. - */ - protected function _sql_like_expression($expression) - { - return $expression . " ESCAPE '\\'"; - } - - /** - * Escape string used in sql query. See {@link phpbb_dbal::sql_escape() sql_escape()} for details. - */ - public function sql_escape($msg) - { - return str_replace("'", "''", $msg); - } - - /** - * Expose a DBMS specific function. See {@link phpbb_dbal::sql_function() sql_function()} for details. - */ - public function sql_function($type, $col) - { - switch ($type) - { - case 'length_varchar': - case 'length_text': - return 'DATALENGTH(' . $col . ')'; - break; - } - } - - /** - * Handle data by using prepared statements. See {@link phpbb_dbal::sql_handle_data() sql_handle_data()} for details. - public function sql_handle_data($type, $table, $data, $where = '') - { - } - */ - - /** - * Build DB-specific query bits. See {@link phpbb_dbal::_sql_custom_build() _sql_custom_build()} for details. - */ - protected function _sql_custom_build($stage, $data) - { - return $data; - } - - /** - * return sql error array. See {@link phpbb_dbal::_sql_error() _sql_error()} for details. - */ - protected function _sql_error() - { - $message = $code = array(); - foreach (@sqlsrv_errors() as $error_array) - { - $message[] = $error_array['message']; - $code[] = $error_array['code']; - } - - $error = array( - 'message' => implode('<br />', $message), - 'code' => implode('<br />', $code), - ); - - return $error; - } - - /** - * Run DB-specific code to build SQL Report to explain queries, show statistics and runtime information. See {@link phpbb_dbal::_sql_report() _sql_report()} for details. - */ - protected function _sql_report($mode, $query = '') - { - switch ($mode) - { - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @sqlsrv_query($this->db_connect_id, $query); - while ($void = @sqlsrv_fetch_array($result, SQLSRV_FETCH_ASSOC)) - { - // Take the time spent on parsing rows into account - } - @sqlsrv_free_stmt($result); - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/mssql_odbc.php b/phpBB/includes/db/mssql_odbc.php deleted file mode 100644 index 3fd5635150..0000000000 --- a/phpBB/includes/db/mssql_odbc.php +++ /dev/null @@ -1,380 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -include_once(PHPBB_ROOT_PATH . 'includes/db/dbal.' . PHP_EXT); - -/** -* Unified ODBC functions -* Unified ODBC functions support any database having ODBC driver, for example Adabas D, IBM DB2, iODBC, Solid, Sybase SQL Anywhere... -* Here we only support MSSQL Server 2000+ because of the provided schema -* -* @note number of bytes returned for returning data depends on odbc.defaultlrl php.ini setting. -* If it is limited to 4K for example only 4K of data is returned max, resulting in incomplete theme data for example. -* @note odbc.defaultbinmode may affect UTF8 characters -* -* @package dbal -*/ -class phpbb_dbal_mssql_odbc extends phpbb_dbal -{ - /** - * @var string Database type. No distinction between versions or used extensions. - */ - public $dbms_type = 'mssql'; - - /** - * @var array Database type map, column layout information - */ - public $dbms_type_map = array( - 'INT:' => '[int]', - 'BINT' => '[float]', - 'UINT' => '[int]', - 'UINT:' => '[int]', - 'TINT:' => '[int]', - 'USINT' => '[int]', - 'BOOL' => '[int]', - 'VCHAR' => '[varchar] (255)', - 'VCHAR:' => '[varchar] (%d)', - 'CHAR:' => '[char] (%d)', - 'XSTEXT' => '[varchar] (1000)', - 'STEXT' => '[varchar] (3000)', - 'TEXT' => '[varchar] (8000)', - 'MTEXT' => '[text]', - 'XSTEXT_UNI'=> '[varchar] (100)', - 'STEXT_UNI' => '[varchar] (255)', - 'TEXT_UNI' => '[varchar] (4000)', - 'MTEXT_UNI' => '[text]', - 'TIMESTAMP' => '[int]', - 'DECIMAL' => '[float]', - 'DECIMAL:' => '[float]', - 'PDECIMAL' => '[float]', - 'PDECIMAL:' => '[float]', - 'VCHAR_UNI' => '[varchar] (255)', - 'VCHAR_UNI:'=> '[varchar] (%d)', - 'VARBINARY' => '[varchar] (255)', - ); - - /** - * Connect to server. See {@link phpbb_dbal::sql_connect() sql_connect()} for details. - */ - public function sql_connect($server, $user, $password, $database, $port = false, $persistency = false , $new_link = false) - { - $this->persistency = $persistency; - $this->user = $user; - $this->dbname = $database; - $this->port = $port; - - $port_delimiter = (defined('PHP_OS') && substr(PHP_OS, 0, 3) === 'WIN') ? ',' : ':'; - $this->server = $server . (($port) ? $port_delimiter . $port : ''); - - $max_size = @ini_get('odbc.defaultlrl'); - if (!empty($max_size)) - { - $unit = strtolower(substr($max_size, -1, 1)); - $max_size = (int) $max_size; - - if ($unit == 'k') - { - $max_size = floor($max_size / 1024); - } - else if ($unit == 'g') - { - $max_size *= 1024; - } - else if (is_numeric($unit)) - { - $max_size = floor((int) ($max_size . $unit) / 1048576); - } - $max_size = max(8, $max_size) . 'M'; - - @ini_set('odbc.defaultlrl', $max_size); - } - - $this->db_connect_id = ($this->persistency) ? @odbc_pconnect($this->server, $this->user, $password) : @odbc_connect($this->server, $this->user, $password); - - return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); - } - - /** - * Version information about used database. See {@link phpbb_dbal::sql_server_info() sql_server_info()} for details. - */ - public function sql_server_info($raw = false) - { - if (!phpbb::registered('acm') || ($this->sql_server_version = phpbb::$acm->get('#mssqlodbc_version')) === false) - { - $result_id = @odbc_exec($this->db_connect_id, "SELECT SERVERPROPERTY('productversion'), SERVERPROPERTY('productlevel'), SERVERPROPERTY('edition')"); - - $row = false; - if ($result_id) - { - $row = @odbc_fetch_array($result_id); - @odbc_free_result($result_id); - } - - $this->sql_server_version = ($row) ? trim(implode(' ', $row)) : 0; - - if (phpbb::registered('acm')) - { - phpbb::$acm->put('#mssqlodbc_version', $this->sql_server_version); - } - } - - if ($raw) - { - return $this->sql_server_version; - } - - return ($this->sql_server_version) ? 'MSSQL (ODBC)<br />' . $this->sql_server_version : 'MSSQL (ODBC)'; - } - - /** - * DB-specific base query method. See {@link phpbb_dbal::_sql_query() _sql_query()} for details. - */ - protected function _sql_query($query) - { - return @odbc_exec($this->db_connect_id, $query); - } - - /** - * Build LIMIT query and run it. See {@link phpbb_dbal::_sql_query_limit() _sql_query_limit()} for details. - */ - protected function _sql_query_limit($query, $total, $offset, $cache_ttl) - { - // Since TOP is only returning a set number of rows we won't need it if total is set to 0 (return all rows) - if ($total) - { - // We need to grab the total number of rows + the offset number of rows to get the correct result - if (strpos($query, 'SELECT DISTINCT') === 0) - { - $query = 'SELECT DISTINCT TOP ' . ($total + $offset) . ' ' . substr($query, 15); - } - else - { - $query = 'SELECT TOP ' . ($total + $offset) . ' ' . substr($query, 6); - } - } - - $result = $this->sql_query($query, $cache_ttl); - - // Seek by $offset rows - if ($offset) - { - // We do not fetch the row for rownum == 0 because then the next resultset would be the second row - for ($i = 0; $i < $offset; $i++) - { - if (!$this->sql_fetchrow($result)) - { - return false; - } - } - } - - return $result; - } - - /** - * Close sql connection. See {@link phpbb_dbal::_sql_close() _sql_close()} for details. - */ - protected function _sql_close() - { - return @odbc_close($this->db_connect_id); - } - - /** - * SQL Transaction. See {@link phpbb_dbal::_sql_transaction() _sql_transaction()} for details. - */ - protected function _sql_transaction($status) - { - switch ($status) - { - case 'begin': - return @odbc_exec($this->db_connect_id, 'BEGIN TRANSACTION'); - break; - - case 'commit': - return @odbc_exec($this->db_connect_id, 'COMMIT TRANSACTION'); - break; - - case 'rollback': - return @odbc_exec($this->db_connect_id, 'ROLLBACK TRANSACTION'); - break; - } - - return true; - } - - /** - * Return number of affected rows. See {@link phpbb_dbal::sql_affectedrows() sql_affectedrows()} for details. - */ - public function sql_affectedrows() - { - return ($this->db_connect_id) ? @odbc_num_rows($this->query_result) : false; - } - - /** - * Get last inserted id after insert statement. See {@link phpbb_dbal::sql_nextid() sql_nextid()} for details. - */ - public function sql_nextid() - { - $result_id = @odbc_exec($this->db_connect_id, 'SELECT @@IDENTITY'); - - if ($result_id) - { - if (@odbc_fetch_array($result_id)) - { - $id = @odbc_result($result_id, 1); - @odbc_free_result($result_id); - return $id; - } - @odbc_free_result($result_id); - } - - return false; - } - - /** - * Fetch current row. See {@link phpbb_dbal::_sql_fetchrow() _sql_fetchrow()} for details. - * @note number of bytes returned depends on odbc.defaultlrl php.ini setting. If it is limited to 4K for example only 4K of data is returned max. - */ - protected function _sql_fetchrow($query_id) - { - return @odbc_fetch_array($query_id); - } - - /** - * Free query result. See {@link phpbb_dbal::_sql_freeresult() _sql_freeresult()} for details. - */ - protected function _sql_freeresult($query_id) - { - return @odbc_free_result($query_id); - } - - /** - * Correctly adjust LIKE expression for special characters. See {@link phpbb_dbal::_sql_like_expression() _sql_like_expression()} for details. - */ - protected function _sql_like_expression($expression) - { - return $expression . " ESCAPE '\\'"; - } - - /** - * Escape string used in sql query. See {@link phpbb_dbal::sql_escape() sql_escape()} for details. - */ - public function sql_escape($msg) - { - return str_replace(array("'", "\0"), array("''", ''), $msg); - } - - /** - * Expose a DBMS specific function. See {@link phpbb_dbal::sql_function() sql_function()} for details. - */ - public function sql_function($type, $col) - { - switch ($type) - { - case 'length_varchar': - case 'length_text': - return 'DATALENGTH(' . $col . ')'; - break; - } - } - - /** - * Handle data by using prepared statements. See {@link phpbb_dbal::sql_handle_data() sql_handle_data()} for details. - public function sql_handle_data($type, $table, $data, $where = '') - { - if ($type === 'INSERT') - { - $stmt = odbc_prepare($this->db_connect_id, "INSERT INTO $table (". implode(', ', array_keys($data)) . ") VALUES (" . substr(str_repeat('?, ', sizeof($data)) ,0, -1) . ')'); - } - else - { - $query = "UPDATE $table SET "; - - $set = array(); - foreach (array_keys($data) as $key) - { - $set[] = "$key = ?"; - } - $query .= implode(', ', $set); - - if ($where !== '') - { - $query .= $where; - } - - $stmt = odbc_prepare($this->db_connect_id, $query); - } - - // get the stmt onto the top of the function arguments - array_unshift($data, $stmt); - - call_user_func_array('odbc_execute', $data); - } - */ - - /** - * Build DB-specific query bits. See {@link phpbb_dbal::_sql_custom_build() _sql_custom_build()} for details. - */ - protected function _sql_custom_build($stage, $data) - { - return $data; - } - - /** - * return sql error array. See {@link phpbb_dbal::_sql_error() _sql_error()} for details. - */ - protected function _sql_error() - { - return array( - 'message' => @odbc_errormsg(), - 'code' => @odbc_error() - ); - } - - /** - * Run DB-specific code to build SQL Report to explain queries, show statistics and runtime information. See {@link phpbb_dbal::_sql_report() _sql_report()} for details. - */ - protected function _sql_report($mode, $query = '') - { - switch ($mode) - { - case 'start': - break; - - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @odbc_exec($this->db_connect_id, $query); - while ($void = @odbc_fetch_array($result)) - { - // Take the time spent on parsing rows into account - } - @odbc_free_result($result); - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/mysql.php b/phpBB/includes/db/mysql.php deleted file mode 100644 index ac0384d523..0000000000 --- a/phpBB/includes/db/mysql.php +++ /dev/null @@ -1,447 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* MySQL Database Abstraction Layer -* Compatible with: -* MySQL 4.1+ -* MySQL 5.0+ -* @package dbal -*/ -class phpbb_dbal_mysql extends phpbb_dbal -{ - /** - * @var string Database type. No distinction between versions or used extensions. - */ - public $dbms_type = 'mysql'; - - /** - * @var array Database type map, column layout information - */ - public $dbms_type_map = array( - 'INT:' => 'int(%d)', - 'BINT' => 'bigint(20)', - 'UINT' => 'mediumint(8) UNSIGNED', - 'UINT:' => 'int(%d) UNSIGNED', - 'TINT:' => 'tinyint(%d)', - 'USINT' => 'smallint(4) UNSIGNED', - 'BOOL' => 'tinyint(1) UNSIGNED', - 'VCHAR' => 'varchar(255)', - 'VCHAR:' => 'varchar(%d)', - 'CHAR:' => 'char(%d)', - 'XSTEXT' => 'text', - 'XSTEXT_UNI'=> 'varchar(100)', - 'STEXT' => 'text', - 'STEXT_UNI' => 'varchar(255)', - 'TEXT' => 'text', - 'TEXT_UNI' => 'text', - 'MTEXT' => 'mediumtext', - 'MTEXT_UNI' => 'mediumtext', - 'TIMESTAMP' => 'int(11) UNSIGNED', - 'DECIMAL' => 'decimal(5,2)', - 'DECIMAL:' => 'decimal(%d,2)', - 'PDECIMAL' => 'decimal(6,3)', - 'PDECIMAL:' => 'decimal(%d,3)', - 'VCHAR_UNI' => 'varchar(255)', - 'VCHAR_UNI:'=> 'varchar(%d)', - 'VARBINARY' => 'varbinary(255)', - ); - - /** - * Connect to server. See {@link phpbb_dbal::sql_connect() sql_connect()} for details. - */ - public function sql_connect($server, $user, $password, $database, $port = false, $persistency = false , $new_link = false) - { - $this->persistency = $persistency; - $this->user = $user; - $this->server = $server . (($port) ? ':' . $port : ''); - $this->dbname = $database; - $this->port = $port; - - $this->db_connect_id = ($this->persistency) ? @mysql_pconnect($this->server, $this->user, $password, $new_link) : @mysql_connect($this->server, $this->user, $password, $new_link); - - if (!$this->db_connect_id || !$this->dbname) - { - return $this->sql_error(''); - } - - if (!@mysql_select_db($this->dbname, $this->db_connect_id)) - { - return $this->sql_error(''); - } - - @mysql_query("SET NAMES 'utf8'", $this->db_connect_id); - - // enforce strict mode on databases that support it - if (version_compare($this->sql_server_info(true), '5.0.2', '>=')) - { - $result = @mysql_query('SELECT @@session.sql_mode AS sql_mode', $this->db_connect_id); - $row = @mysql_fetch_assoc($result); - @mysql_free_result($result); - - $modes = array_map('trim', explode(',', $row['sql_mode'])); - - // TRADITIONAL includes STRICT_ALL_TABLES and STRICT_TRANS_TABLES - if (!in_array('TRADITIONAL', $modes)) - { - if (!in_array('STRICT_ALL_TABLES', $modes)) - { - $modes[] = 'STRICT_ALL_TABLES'; - } - - if (!in_array('STRICT_TRANS_TABLES', $modes)) - { - $modes[] = 'STRICT_TRANS_TABLES'; - } - } - - $mode = implode(',', $modes); - @mysql_query("SET SESSION sql_mode='{$mode}'", $this->db_connect_id); - } - - return $this->db_connect_id; - } - - /** - * Version information about used database. See {@link phpbb_dbal::sql_server_info() sql_server_info()} for details. - */ - public function sql_server_info($raw = false) - { - if (!phpbb::registered('acm') || ($this->sql_server_version = phpbb::$acm->get('#mysql_version')) === false) - { - $result = @mysql_query('SELECT VERSION() AS version', $this->db_connect_id); - $row = @mysql_fetch_assoc($result); - @mysql_free_result($result); - - $this->sql_server_version = trim($row['version']); - - if (phpbb::registered('acm')) - { - phpbb::$acm->put('#mysql_version', $this->sql_server_version); - } - } - - return ($raw) ? $this->sql_server_version : 'MySQL ' . $this->sql_server_version; - } - - /** - * DB-specific base query method. See {@link phpbb_dbal::_sql_query() _sql_query()} for details. - */ - protected function _sql_query($query) - { - return @mysql_query($query, $this->db_connect_id); - } - - /** - * Build LIMIT query and run it. See {@link phpbb_dbal::_sql_query_limit() _sql_query_limit()} for details. - */ - protected function _sql_query_limit($query, $total, $offset, $cache_ttl) - { - // if $total is set to 0 we do not want to limit the number of rows - if ($total == 0) - { - // MySQL 4.1+ no longer supports -1 in limit queries - $total = '18446744073709551615'; - } - - $query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total); - return $this->sql_query($query, $cache_ttl); - } - - /** - * Close sql connection. See {@link phpbb_dbal::_sql_close() _sql_close()} for details. - */ - protected function _sql_close() - { - return @mysql_close($this->db_connect_id); - } - - /** - * SQL Transaction. See {@link phpbb_dbal::_sql_transaction() _sql_transaction()} for details. - */ - protected function _sql_transaction($status) - { - switch ($status) - { - case 'begin': - return @mysql_query('BEGIN', $this->db_connect_id); - break; - - case 'commit': - return @mysql_query('COMMIT', $this->db_connect_id); - break; - - case 'rollback': - return @mysql_query('ROLLBACK', $this->db_connect_id); - break; - } - - return true; - } - - /** - * Return number of affected rows. See {@link phpbb_dbal::sql_affectedrows() sql_affectedrows()} for details. - */ - public function sql_affectedrows() - { - return ($this->db_connect_id) ? @mysql_affected_rows($this->db_connect_id) : false; - } - - /** - * Get last inserted id after insert statement. See {@link phpbb_dbal::sql_nextid() sql_nextid()} for details. - */ - public function sql_nextid() - { - return ($this->db_connect_id) ? @mysql_insert_id($this->db_connect_id) : false; - } - - /** - * Fetch current row. See {@link phpbb_dbal::_sql_fetchrow() _sql_fetchrow()} for details. - */ - protected function _sql_fetchrow($query_id) - { - return @mysql_fetch_assoc($query_id); - } - - /** - * Free query result. See {@link phpbb_dbal::_sql_freeresult() _sql_freeresult()} for details. - */ - protected function _sql_freeresult($query_id) - { - return @mysql_free_result($query_id); - } - - /** - * Correctly adjust LIKE expression for special characters. See {@link phpbb_dbal::_sql_like_expression() _sql_like_expression()} for details. - */ - protected function _sql_like_expression($expression) - { - return $expression; - } - - /** - * Escape string used in sql query. See {@link phpbb_dbal::sql_escape() sql_escape()} for details. - */ - public function sql_escape($msg) - { - if (!$this->db_connect_id) - { - return @mysql_real_escape_string($msg); - } - - return @mysql_real_escape_string($msg, $this->db_connect_id); - } - - /** - * Expose a DBMS specific function. See {@link phpbb_dbal::sql_function() sql_function()} for details. - */ - public function sql_function($type, $col) - { - switch ($type) - { - case 'length_varchar': - case 'length_text': - return 'LENGTH(' . $col . ')'; - break; - } - } - - /** - * Handle data by using prepared statements. See {@link phpbb_dbal::sql_handle_data() sql_handle_data()} for details. - public function sql_handle_data($type, $table, $data, $where = '') - { - } - */ - - /** - * Build DB-specific query bits. See {@link phpbb_dbal::_sql_custom_build() _sql_custom_build()} for details. - */ - protected function _sql_custom_build($stage, $data) - { - switch ($stage) - { - case 'FROM': - $data = '(' . $data . ')'; - break; - } - - return $data; - } - - /** - * return sql error array. See {@link phpbb_dbal::_sql_error() _sql_error()} for details. - */ - protected function _sql_error() - { - if (!$this->db_connect_id) - { - return array( - 'message' => @mysql_error(), - 'code' => @mysql_errno() - ); - } - - return array( - 'message' => @mysql_error($this->db_connect_id), - 'code' => @mysql_errno($this->db_connect_id) - ); - } - - /** - * Run DB-specific code to build SQL Report to explain queries, show statistics and runtime information. See {@link phpbb_dbal::_sql_report() _sql_report()} for details. - */ - protected function _sql_report($mode, $query = '') - { - static $test_prof; - static $test_extend; - - // current detection method, might just switch to see the existance of INFORMATION_SCHEMA.PROFILING - if ($test_prof === null) - { - $test_prof = $test_extend = false; - if (version_compare($this->sql_server_info(true), '5.0.37', '>=') && version_compare($this->sql_server_info(true), '5.1', '<')) - { - $test_prof = true; - } - - if (version_compare($this->sql_server_info(true), '4.1.1', '>=')) - { - $test_extend = true; - } - } - - switch ($mode) - { - case 'start': - - $explain_query = $query; - if (preg_match('/UPDATE ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m)) - { - $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2]; - } - else if (preg_match('/DELETE FROM ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m)) - { - $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2]; - } - - if (preg_match('/^SELECT/', $explain_query)) - { - $html_table = false; - - // begin profiling - if ($test_prof) - { - @mysql_query('SET profiling = 1;', $this->db_connect_id); - } - - if ($result = @mysql_query('EXPLAIN ' . (($test_extend) ? 'EXTENDED ' : '') . "$explain_query", $this->db_connect_id)) - { - while ($row = @mysql_fetch_assoc($result)) - { - $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); - } - } - @mysql_free_result($result); - - if ($html_table) - { - $this->html_hold .= '</table>'; - } - - if ($test_extend) - { - $html_table = false; - - if ($result = @mysql_query('SHOW WARNINGS', $this->db_connect_id)) - { - $this->html_hold .= '<br />'; - while ($row = @mysql_fetch_assoc($result)) - { - $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); - } - } - @mysql_free_result($result); - - if ($html_table) - { - $this->html_hold .= '</table>'; - } - } - - if ($test_prof) - { - $html_table = false; - - // get the last profile - if ($result = @mysql_query('SHOW PROFILE ALL;', $this->db_connect_id)) - { - $this->html_hold .= '<br />'; - while ($row = @mysql_fetch_assoc($result)) - { - // make <unknown> HTML safe - if (!empty($row['Source_function'])) - { - $row['Source_function'] = str_replace(array('<', '>'), array('<', '>'), $row['Source_function']); - } - - // remove unsupported features - foreach ($row as $key => $val) - { - if ($val === null) - { - unset($row[$key]); - } - } - $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); - } - } - @mysql_free_result($result); - - if ($html_table) - { - $this->html_hold .= '</table>'; - } - - @mysql_query('SET profiling = 0;', $this->db_connect_id); - } - } - - break; - - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @mysql_query($query, $this->db_connect_id); - while ($void = @mysql_fetch_assoc($result)) - { - // Take the time spent on parsing rows into account - } - @mysql_free_result($result); - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/mysqli.php b/phpBB/includes/db/mysqli.php deleted file mode 100644 index 386efdbff0..0000000000 --- a/phpBB/includes/db/mysqli.php +++ /dev/null @@ -1,472 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* MySQLi Database Abstraction Layer -* Compatible with: -* MySQL 4.1+ -* MySQL 5.0+ -* @package dbal -*/ -class phpbb_dbal_mysqli extends phpbb_dbal -{ - /** - * @var string Database type. No distinction between versions or used extensions. - */ - public $dbms_type = 'mysql'; - - /** - * @var array Database type map, column layout information - */ - public $dbms_type_map = array( - 'INT:' => 'int(%d)', - 'BINT' => 'bigint(20)', - 'UINT' => 'mediumint(8) UNSIGNED', - 'UINT:' => 'int(%d) UNSIGNED', - 'TINT:' => 'tinyint(%d)', - 'USINT' => 'smallint(4) UNSIGNED', - 'BOOL' => 'tinyint(1) UNSIGNED', - 'VCHAR' => 'varchar(255)', - 'VCHAR:' => 'varchar(%d)', - 'CHAR:' => 'char(%d)', - 'XSTEXT' => 'text', - 'XSTEXT_UNI'=> 'varchar(100)', - 'STEXT' => 'text', - 'STEXT_UNI' => 'varchar(255)', - 'TEXT' => 'text', - 'TEXT_UNI' => 'text', - 'MTEXT' => 'mediumtext', - 'MTEXT_UNI' => 'mediumtext', - 'TIMESTAMP' => 'int(11) UNSIGNED', - 'DECIMAL' => 'decimal(5,2)', - 'DECIMAL:' => 'decimal(%d,2)', - 'PDECIMAL' => 'decimal(6,3)', - 'PDECIMAL:' => 'decimal(%d,3)', - 'VCHAR_UNI' => 'varchar(255)', - 'VCHAR_UNI:'=> 'varchar(%d)', - 'VARBINARY' => 'varbinary(255)', - ); - - /** - * Connect to server. See {@link phpbb_dbal::sql_connect() sql_connect()} for details. - */ - public function sql_connect($server, $user, $password, $database, $port = false, $persistency = false , $new_link = false) - { - $this->persistency = $persistency; - $this->user = $user; - $this->server = $server; - $this->dbname = $database; - $this->port = (!$port) ? NULL : $port; - - // Persistant connections not supported by the mysqli extension? - $this->db_connect_id = @mysqli_connect($this->server, $this->user, $password, $this->dbname, $this->port); - - if (!$this->db_connect_id || !$this->dbname) - { - return $this->sql_error(''); - } - - @mysqli_query($this->db_connect_id, "SET NAMES 'utf8'"); - - // enforce strict mode on databases that support it - if (version_compare($this->sql_server_info(true), '5.0.2', '>=')) - { - $result = @mysqli_query($this->db_connect_id, 'SELECT @@session.sql_mode AS sql_mode'); - $row = @mysqli_fetch_assoc($result); - @mysqli_free_result($result); - - $modes = array_map('trim', explode(',', $row['sql_mode'])); - - // TRADITIONAL includes STRICT_ALL_TABLES and STRICT_TRANS_TABLES - if (!in_array('TRADITIONAL', $modes)) - { - if (!in_array('STRICT_ALL_TABLES', $modes)) - { - $modes[] = 'STRICT_ALL_TABLES'; - } - - if (!in_array('STRICT_TRANS_TABLES', $modes)) - { - $modes[] = 'STRICT_TRANS_TABLES'; - } - } - - $mode = implode(',', $modes); - @mysqli_query($this->db_connect_id, "SET SESSION sql_mode='{$mode}'"); - } - - return $this->db_connect_id; - } - - /** - * Version information about used database. See {@link phpbb_dbal::sql_server_info() sql_server_info()} for details. - */ - public function sql_server_info($raw = false) - { - if (!phpbb::registered('acm') || ($this->sql_server_version = phpbb::$acm->get('#mysqli_version')) === false) - { - $result = @mysqli_query($this->db_connect_id, 'SELECT VERSION() AS version'); - $row = @mysqli_fetch_assoc($result); - @mysqli_free_result($result); - - $this->sql_server_version = trim($row['version']); - - if (phpbb::registered('acm')) - { - phpbb::$acm->put('#mysqli_version', $this->sql_server_version); - } - } - - return ($raw) ? $this->sql_server_version : 'MySQL(i) ' . $this->sql_server_version; - } - - /** - * DB-specific base query method. See {@link phpbb_dbal::_sql_query() _sql_query()} for details. - */ - protected function _sql_query($query) - { - return @mysqli_query($this->db_connect_id, $query); - } - - /** - * Build LIMIT query and run it. See {@link phpbb_dbal::_sql_query_limit() _sql_query_limit()} for details. - */ - protected function _sql_query_limit($query, $total, $offset, $cache_ttl) - { - // if $total is set to 0 we do not want to limit the number of rows - if ($total == 0) - { - // MySQL 4.1+ no longer supports -1 in limit queries - $total = '18446744073709551615'; - } - - $query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total); - return $this->sql_query($query, $cache_ttl); - } - - /** - * Close sql connection. See {@link phpbb_dbal::_sql_close() _sql_close()} for details. - */ - protected function _sql_close() - { - return @mysqli_close($this->db_connect_id); - } - - /** - * SQL Transaction. See {@link phpbb_dbal::_sql_transaction() _sql_transaction()} for details. - */ - protected function _sql_transaction($status) - { - switch ($status) - { - case 'begin': - return @mysqli_autocommit($this->db_connect_id, false); - break; - - case 'commit': - $result = @mysqli_commit($this->db_connect_id); - @mysqli_autocommit($this->db_connect_id, true); - return $result; - break; - - case 'rollback': - $result = @mysqli_rollback($this->db_connect_id); - @mysqli_autocommit($this->db_connect_id, true); - return $result; - break; - } - - return true; - } - - /** - * Return number of affected rows. See {@link phpbb_dbal::sql_affectedrows() sql_affectedrows()} for details. - */ - public function sql_affectedrows() - { - return ($this->db_connect_id) ? @mysqli_affected_rows($this->db_connect_id) : false; - } - - /** - * Get last inserted id after insert statement. See {@link phpbb_dbal::sql_nextid() sql_nextid()} for details. - */ - public function sql_nextid() - { - return ($this->db_connect_id) ? @mysqli_insert_id($this->db_connect_id) : false; - } - - /** - * Fetch current row. See {@link phpbb_dbal::_sql_fetchrow() _sql_fetchrow()} for details. - */ - protected function _sql_fetchrow($query_id) - { - return @mysqli_fetch_assoc($query_id); - } - - /** - * Free query result. See {@link phpbb_dbal::_sql_freeresult() _sql_freeresult()} for details. - */ - protected function _sql_freeresult($query_id) - { - return @mysqli_free_result($query_id); - } - - /** - * Correctly adjust LIKE expression for special characters. See {@link phpbb_dbal::_sql_like_expression() _sql_like_expression()} for details. - */ - protected function _sql_like_expression($expression) - { - return $expression; - } - - /** - * Escape string used in sql query. See {@link phpbb_dbal::sql_escape() sql_escape()} for details. - */ - public function sql_escape($msg) - { - return @mysqli_real_escape_string($this->db_connect_id, $msg); - } - - /** - * Expose a DBMS specific function. See {@link phpbb_dbal::sql_function() sql_function()} for details. - */ - public function sql_function($type, $col) - { - switch ($type) - { - case 'length_varchar': - case 'length_text': - return 'LENGTH(' . $col . ')'; - break; - } - } - - /** - * Handle data by using prepared statements. See {@link phpbb_dbal::sql_handle_data() sql_handle_data()} for details. - public function sql_handle_data($type, $table, $data, $where = '') - { - if ($type === 'INSERT') - { - $stmt = mysqli_prepare($this->db_connect_id, "INSERT INTO $table (". implode(', ', array_keys($data)) . ") VALUES (" . substr(str_repeat('?, ', sizeof($data)) ,0, -1) . ')'); - } - else - { - $query = "UPDATE $table SET "; - - $set = array(); - foreach (array_keys($data) as $key) - { - $set[] = "$key = ?"; - } - $query .= implode(', ', $set); - - if ($where !== '') - { - $query .= ' WHERE ' . $where; - } - - $stmt = mysqli_prepare($this->db_connect_id, $query); - } - - // get the stmt onto the top of the function arguments - array_unshift($data, $stmt); - - call_user_func_array('mysqli_stmt_bind_param', $data); - mysqli_stmt_execute($stmt); - - mysqli_stmt_close($stmt); - } -*/ - - /** - * Build DB-specific query bits. See {@link phpbb_dbal::_sql_custom_build() _sql_custom_build()} for details. - */ - protected function _sql_custom_build($stage, $data) - { - switch ($stage) - { - case 'FROM': - $data = '(' . $data . ')'; - break; - } - - return $data; - } - - /** - * return sql error array. See {@link phpbb_dbal::_sql_error() _sql_error()} for details. - */ - protected function _sql_error() - { - if (!$this->db_connect_id) - { - return array( - 'message' => @mysqli_connect_error(), - 'code' => @mysqli_connect_errno() - ); - } - - return array( - 'message' => @mysqli_error($this->db_connect_id), - 'code' => @mysqli_errno($this->db_connect_id) - ); - } - - /** - * Run DB-specific code to build SQL Report to explain queries, show statistics and runtime information. See {@link phpbb_dbal::_sql_report() _sql_report()} for details. - */ - protected function _sql_report($mode, $query = '') - { - static $test_prof; - static $test_extend; - - // current detection method, might just switch to see the existance of INFORMATION_SCHEMA.PROFILING - if ($test_prof === null) - { - $test_prof = $test_extend = false; - if (version_compare($this->sql_server_info(true), '5.0.37', '>=') && version_compare($this->sql_server_info(true), '5.1', '<')) - { - $test_prof = true; - } - - if (version_compare($this->sql_server_info(true), '4.1.1', '>=')) - { - $test_extend = true; - } - } - - switch ($mode) - { - case 'start': - - $explain_query = $query; - if (preg_match('/UPDATE ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m)) - { - $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2]; - } - else if (preg_match('/DELETE FROM ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m)) - { - $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2]; - } - - if (preg_match('/^SELECT/', $explain_query)) - { - $html_table = false; - - // begin profiling - if ($test_prof) - { - @mysqli_query($this->db_connect_id, 'SET profiling = 1;'); - } - - if ($result = @mysqli_query($this->db_connect_id, 'EXPLAIN ' . (($test_extend) ? 'EXTENDED ' : '') . "$explain_query")) - { - while ($row = @mysqli_fetch_assoc($result)) - { - $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); - } - } - @mysqli_free_result($result); - - if ($html_table) - { - $this->html_hold .= '</table>'; - } - - if ($test_extend) - { - $html_table = false; - - if ($result = @mysqli_query($this->db_connect_id, 'SHOW WARNINGS')) - { - $this->html_hold .= '<br />'; - while ($row = @mysqli_fetch_assoc($result)) - { - $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); - } - } - @mysqli_free_result($result); - - if ($html_table) - { - $this->html_hold .= '</table>'; - } - } - - if ($test_prof) - { - $html_table = false; - - // get the last profile - if ($result = @mysqli_query($this->db_connect_id, 'SHOW PROFILE ALL;')) - { - $this->html_hold .= '<br />'; - while ($row = @mysqli_fetch_assoc($result)) - { - // make <unknown> HTML safe - if (!empty($row['Source_function'])) - { - $row['Source_function'] = str_replace(array('<', '>'), array('<', '>'), $row['Source_function']); - } - - // remove unsupported features - foreach ($row as $key => $val) - { - if ($val === null) - { - unset($row[$key]); - } - } - $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); - } - } - @mysqli_free_result($result); - - if ($html_table) - { - $this->html_hold .= '</table>'; - } - - @mysqli_query($this->db_connect_id, 'SET profiling = 0;'); - } - } - - break; - - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @mysqli_query($this->db_connect_id, $query); - while ($void = @mysqli_fetch_assoc($result)) - { - // Take the time spent on parsing rows into account - } - @mysqli_free_result($result); - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/oracle.php b/phpBB/includes/db/oracle.php deleted file mode 100644 index 3a69565e05..0000000000 --- a/phpBB/includes/db/oracle.php +++ /dev/null @@ -1,664 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Oracle Database Abstraction Layer -* Minimum Requirement: 9.2+ -* @package dbal -*/ -class phpbb_dbal_oracle extends phpbb_dbal -{ - /** - * @var string Database type. No distinction between versions or used extensions. - */ - public $dbms_type = 'oracle'; - - /** - * @var array Database type map, column layout information - */ - public $dbms_type_map = array( - 'INT:' => 'number(%d)', - 'BINT' => 'number(20)', - 'UINT' => 'number(8)', - 'UINT:' => 'number(%d)', - 'TINT:' => 'number(%d)', - 'USINT' => 'number(4)', - 'BOOL' => 'number(1)', - 'VCHAR' => 'varchar2(255)', - 'VCHAR:' => 'varchar2(%d)', - 'CHAR:' => 'char(%d)', - 'XSTEXT' => 'varchar2(1000)', - 'STEXT' => 'varchar2(3000)', - 'TEXT' => 'clob', - 'MTEXT' => 'clob', - 'XSTEXT_UNI'=> 'varchar2(300)', - 'STEXT_UNI' => 'varchar2(765)', - 'TEXT_UNI' => 'clob', - 'MTEXT_UNI' => 'clob', - 'TIMESTAMP' => 'number(11)', - 'DECIMAL' => 'number(5, 2)', - 'DECIMAL:' => 'number(%d, 2)', - 'PDECIMAL' => 'number(6, 3)', - 'PDECIMAL:' => 'number(%d, 3)', - 'VCHAR_UNI' => 'varchar2(255)', - 'VCHAR_UNI:'=> array('varchar2(%d)', 'limit' => array('mult', 3, 765, 'clob')), - 'VARBINARY' => 'raw(255)', - ); - - /** - * @var string Last query executed. We need this for sql_nextid() - */ - var $last_query_text = ''; - - /** - * Connect to server. See {@link phpbb_dbal::sql_connect() sql_connect()} for details. - */ - public function sql_connect($server, $user, $password, $database, $port = false, $persistency = false , $new_link = false) - { - $this->persistency = $persistency; - $this->user = $user; - $this->server = $server . (($port) ? ':' . $port : ''); - $this->dbname = $database; - $this->port = $port; - - $connect = $database; - - // support for "easy connect naming" - if ($server !== '' && $server !== '/') - { - if (substr($server, -1, 1) == '/') - { - $server == substr($sqlserver, 0, -1); - } - $connect = $server . (($port) ? ':' . $port : '') . '/' . $database; - } - - $this->db_connect_id = ($new_link) ? @oci_new_connect($this->user, $password, $connect, 'AL32UTF8') : (($this->persistency) ? @oci_pconnect($this->user, $password, $connect, 'AL32UTF8') : @oci_connect($this->user, $password, $connect, 'AL32UTF8')); - - return ($this->db_connect_id) ? $this->db_connect_id : $this->sql_error(''); - } - - /** - * Version information about used database. See {@link phpbb_dbal::sql_server_info() sql_server_info()} for details. - */ - public function sql_server_info($raw = false) - { - if (!phpbb::registered('acm') || ($this->sql_server_version = phpbb::$acm->get('#oracle_version')) === false) - { - $sql = "SELECT value - FROM NLS_DATABASE_PARAMETERS - WHERE PARAMETER = 'NLS_RDBMS_VERSION'"; - $result = @ociparse($this->db_connect_id, $sql); - @ociexecute($result, OCI_DEFAULT); - @ocicommit($this->db_connect_id); - - $row = array(); - @ocifetchinto($result, $row, OCI_ASSOC + OCI_RETURN_NULLS); - @ocifreestatement($result); - - $this->sql_server_version = (isset($row['VALUE'])) ? trim($row['VALUE']) : 0; - - if (phpbb::registered('acm')) - { - phpbb::$acm->put('#oracle_version', $this->sql_server_version); - } - } - - return ($raw) ? $this->sql_server_version : @oci_server_version($this->db_connect_id); - } - - /** - * DB-specific base query method. See {@link phpbb_dbal::_sql_query() _sql_query()} for details. - */ - protected function _sql_query($query) - { - $this->last_query_text = $query; - - $in_transaction = false; - if (!$this->transaction) - { - $this->sql_transaction('begin'); - } - else - { - $in_transaction = true; - } - - $array = array(); - - // We overcome Oracle's 4000 char limit by binding vars - if (strlen($query) > 4000) - { - if (preg_match('/^(INSERT INTO[^(]++)\\(([^()]+)\\) VALUES[^(]++\\((.*?)\\)$/s', $query, $regs)) - { - if (strlen($regs[3]) > 4000) - { - $cols = explode(', ', $regs[2]); - preg_match_all('/\'(?:[^\']++|\'\')*+\'|[\d-.]+/', $regs[3], $vals, PREG_PATTERN_ORDER); - - $inserts = $vals[0]; - unset($vals); - - foreach ($inserts as $key => $value) - { - // check to see if this thing is greater than the max + 'x2 - if (!empty($value) && $value[0] === "'" && strlen($value) > 4002) - { - $inserts[$key] = ':' . strtoupper($cols[$key]); - $array[$inserts[$key]] = str_replace("''", "'", substr($value, 1, -1)); - } - } - - $query = $regs[1] . '(' . $regs[2] . ') VALUES (' . implode(', ', $inserts) . ')'; - } - } - else if (preg_match_all('/^(UPDATE [\\w_]++\\s+SET )([\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+)(?:,\\s*[\\w_]++\\s*=\\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]+))*+)\\s+(WHERE.*)$/s', $query, $data, PREG_SET_ORDER)) - { - if (strlen($data[0][2]) > 4000) - { - $update = $data[0][1]; - $where = $data[0][3]; - preg_match_all('/([\\w_]++)\\s*=\\s*(\'(?:[^\']++|\'\')*+\'|[\d-.]++)/', $data[0][2], $temp, PREG_SET_ORDER); - unset($data); - - $cols = array(); - foreach ($temp as $value) - { - // check to see if this thing is greater than the max + 'x2 - if (!empty($value[2]) && $value[2][0] === "'" && strlen($value[2]) > 4002) - { - $cols[] = $value[1] . '=:' . strtoupper($value[1]); - $array[$value[1]] = str_replace("''", "'", substr($value[2], 1, -1)); - } - else - { - $cols[] = $value[1] . '=' . $value[2]; - } - } - - $query = $update . implode(', ', $cols) . ' ' . $where; - unset($cols); - } - } - } - - switch (substr($query, 0, 6)) - { - case 'DELETE': - if (preg_match('/^(DELETE FROM [\w_]++ WHERE)((?:\s*(?:AND|OR)?\s*[\w_]+\s*(?:(?:=|<>)\s*(?>\'(?>[^\']++|\'\')*+\'|[\d-.]+)|(?:NOT )?IN\s*\((?>\'(?>[^\']++|\'\')*+\',? ?|[\d-.]+,? ?)*+\)))*+)$/', $query, $regs)) - { - $query = $regs[1] . $this->_rewrite_where($regs[2]); - unset($regs); - } - break; - - case 'UPDATE': - if (preg_match('/^(UPDATE [\\w_]++\\s+SET [\\w_]+\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]++|:\w++)(?:, [\\w_]+\s*=\s*(?:\'(?:[^\']++|\'\')*+\'|[\d-.]++|:\w++))*+\\s+WHERE)(.*)$/s', $query, $regs)) - { - $query = $regs[1] . $this->_rewrite_where($regs[2]); - unset($regs); - } - break; - - case 'SELECT': - $query = preg_replace_callback('/([\w_.]++)\s*(?:(=|<>)\s*(?>\'(?>[^\']++|\'\')*+\'|[\d-.]++|([\w_.]++))|(?:NOT )?IN\s*\((?>\'(?>[^\']++|\'\')*+\',? ?|[\d-.]++,? ?)*+\))/', array($this, '_rewrite_col_compare'), $query); - break; - } - - $result = @oci_parse($this->db_connect_id, $query); - - if (!$result) - { - return false; - } - - foreach ($array as $key => $value) - { - @oci_bind_by_name($result, $key, $array[$key], -1); - } - - $success = @oci_execute($result, OCI_DEFAULT); - - if (!$success) - { - return false; - } - - if (!$in_transaction) - { - $this->sql_transaction('commit'); - } - - return $result; - } - - /** - * Build LIMIT query and run it. See {@link phpbb_dbal::_sql_query_limit() _sql_query_limit()} for details. - */ - protected function _sql_query_limit($query, $total, $offset, $cache_ttl) - { - $query = 'SELECT * FROM (SELECT /*+ FIRST_ROWS */ rownum AS xrownum, a.* FROM (' . $query . ') a WHERE rownum <= ' . ($offset + $total) . ') WHERE xrownum >= ' . $offset; - return $this->sql_query($query, $cache_ttl); - } - - /** - * Close sql connection. See {@link phpbb_dbal::_sql_close() _sql_close()} for details. - */ - protected function _sql_close() - { - return @oci_close($this->db_connect_id); - } - - /** - * SQL Transaction. See {@link phpbb_dbal::_sql_transaction() _sql_transaction()} for details. - */ - protected function _sql_transaction($status) - { - switch ($status) - { - case 'begin': - return true; - break; - - case 'commit': - return @oci_commit($this->db_connect_id); - break; - - case 'rollback': - return @oci_rollback($this->db_connect_id); - break; - } - - return true; - } - - /** - * Return number of affected rows. See {@link phpbb_dbal::sql_affectedrows() sql_affectedrows()} for details. - */ - public function sql_affectedrows() - { - return ($this->query_result) ? @oci_num_rows($this->query_result) : false; - } - - /** - * Get last inserted id after insert statement. See {@link phpbb_dbal::sql_nextid() sql_nextid()} for details. - */ - public function sql_nextid() - { - if (!$this->query_result || !$this->last_query_text) - { - return false; - } - - if (preg_match('#^INSERT[\t\n ]+INTO[\t\n ]+([a-z0-9\_\-]+)#is', $this->last_query_text, $tablename)) - { - $query = 'SELECT ' . $tablename[1] . '_seq.currval FROM DUAL'; - $stmt = @oci_parse($this->db_connect_id, $query); - @oci_execute($stmt, OCI_DEFAULT); - - $temp_array = @oci_fetch_array($stmt, OCI_ASSOC + OCI_RETURN_NULLS); - @oci_free_statement($stmt); - - return (isset($temp_array['CURRVAL'])) ? $temp_array['CURRVAL'] : false; - } - - return false; - } - - /** - * Fetch current row. See {@link phpbb_dbal::_sql_fetchrow() _sql_fetchrow()} for details. - */ - protected function _sql_fetchrow($query_id) - { - $row = @oci_fetch_array($query_id, OCI_ASSOC + OCI_RETURN_NULLS); - - if (!$row) - { - return false; - } - - $result_row = array(); - foreach ($row as $key => $value) - { - // Oracle treats empty strings as null - if (is_null($value)) - { - $value = ''; - } - - // OCI->CLOB? - if (is_object($value)) - { - $value = $value->load(); - } - - $result_row[strtolower($key)] = $value; - } - - return $result_row; - } - - /** - * Free query result. See {@link phpbb_dbal::_sql_freeresult() _sql_freeresult()} for details. - */ - protected function _sql_freeresult($query_id) - { - return @oci_free_statement($query_id); - } - - /** - * Correctly adjust LIKE expression for special characters. See {@link phpbb_dbal::_sql_like_expression() _sql_like_expression()} for details. - */ - protected function _sql_like_expression($expression) - { - return $expression . " ESCAPE '\\'"; - } - - /** - * Escape string used in sql query. See {@link phpbb_dbal::sql_escape() sql_escape()} for details. - */ - public function sql_escape($msg) - { - return str_replace(array("'", "\0"), array("''", ''), $msg); - } - - /** - * Expose a DBMS specific function. See {@link phpbb_dbal::sql_function() sql_function()} for details. - */ - public function sql_function($type, $col) - { - switch ($type) - { - case 'length_varchar': - return 'LENGTH(' . $col . ')'; - break; - - case 'length_text': - return 'dbms_lob.getlength(' . $col . ')'; - break; - } - } - - /** - * Handle data by using prepared statements. See {@link phpbb_dbal::sql_handle_data() sql_handle_data()} for details. - public function sql_handle_data($type, $table, $data, $where = '') - { - if ($type === 'INSERT') - { - $stmt = oci_parse($this->db_connect_id, "INSERT INTO $table (". implode(', ', array_keys($data)) . ") VALUES (:" . implode(', :', array_keys($data)) . ')'); - } - else - { - $query = "UPDATE $table SET "; - - $set = array(); - foreach (array_keys($data) as $key) - { - $set[] = "$key = :$key"; - } - $query .= implode(', ', $set); - - if ($where !== '') - { - $query .= $where; - } - - $stmt = oci_parse($this->db_connect_id, $query); - } - - foreach ($data as $column => $value) - { - oci_bind_by_name($stmt, ":$column", $data[$column], -1); - } - - oci_execute($stmt); - } - */ - - /** - * Build DB-specific query bits. See {@link phpbb_dbal::_sql_custom_build() _sql_custom_build()} for details. - */ - protected function _sql_custom_build($stage, $data) - { - return $data; - } - - /** - * return sql error array. See {@link phpbb_dbal::_sql_error() _sql_error()} for details. - */ - protected function _sql_error() - { - $error = @oci_error(); - $error = (empty($error)) ? @oci_error($this->query_result) : $error; - $error = (empty($error)) ? @oci_error($this->db_connect_id) : $error; - - if (empty($error)) - { - $error = array( - 'message' => '', - 'code' => '', - ); - } - - return $error; - } - - /** - * Run DB-specific code to build SQL Report to explain queries, show statistics and runtime information. See {@link phpbb_dbal::_sql_report() _sql_report()} for details. - */ - protected function _sql_report($mode, $query = '') - { - switch ($mode) - { - case 'start': - $html_table = false; - - // Grab a plan table, any will do - $sql = "SELECT table_name - FROM USER_TABLES - WHERE table_name LIKE '%PLAN_TABLE%'"; - $stmt = @oci_parse($this->db_connect_id, $sql); - @oci_execute($stmt); - $result = array(); - - if ($result = @oci_fetch_array($stmt, OCI_ASSOC + OCI_RETURN_NULLS)) - { - $table = $result['TABLE_NAME']; - - // This is the statement_id that will allow us to track the plan - $statement_id = substr(md5($query), 0, 30); - - // Remove any stale plans - $stmt2 = @oci_parse($this->db_connect_id, "DELETE FROM $table WHERE statement_id='$statement_id'"); - @oci_execute($stmt2); - @oci_free_statement($stmt2); - - // Explain the plan - $sql = "EXPLAIN PLAN - SET STATEMENT_ID = '$statement_id' - FOR $query"; - $stmt2 = @ociparse($this->db_connect_id, $sql); - @oci_execute($stmt2); - @oci_free_statement($stmt2); - - // Get the data from the plan - $sql = "SELECT operation, options, object_name, object_type, cardinality, cost - FROM plan_table - START WITH id = 0 AND statement_id = '$statement_id' - CONNECT BY PRIOR id = parent_id - AND statement_id = '$statement_id'"; - $stmt2 = @oci_parse($this->db_connect_id, $sql); - @oci_execute($stmt2); - - $row = array(); - while ($row = @oci_fetch_array($stmt2, OCI_ASSOC + OCI_RETURN_NULLS)) - { - $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); - } - @oci_free_statement($stmt2); - - // Remove the plan we just made, we delete them on request anyway - $stmt2 = @oci_parse($this->db_connect_id, "DELETE FROM $table WHERE statement_id='$statement_id'"); - @oci_execute($stmt2); - @oci_free_statement($stmt2); - } - - @oci_free_statement($stmt); - - if ($html_table) - { - $this->html_hold .= '</table>'; - } - - break; - - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @oci_parse($this->db_connect_id, $query); - $success = @oci_execute($result, OCI_DEFAULT); - $row = array(); - - while ($void = @oci_fetch_array($result, OCI_ASSOC + OCI_RETURN_NULLS)) - { - // Take the time spent on parsing rows into account - } - @oci_free_statement($result); - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } - - /** - * Oracle specific code to handle the fact that it does not compare columns properly - * @access private - */ - private function _rewrite_col_compare($args) - { - if (sizeof($args) == 4) - { - if ($args[2] == '=') - { - return '(' . $args[0] . ' OR (' . $args[1] . ' is NULL AND ' . $args[3] . ' is NULL))'; - } - else if ($args[2] == '<>') - { - // really just a fancy way of saying foo <> bar or (foo is NULL XOR bar is NULL) but SQL has no XOR :P - return '(' . $args[0] . ' OR ((' . $args[1] . ' is NULL AND ' . $args[3] . ' is NOT NULL) OR (' . $args[1] . ' is NOT NULL AND ' . $args[3] . ' is NULL)))'; - } - } - else - { - return $this->_rewrite_where($args[0]); - } - } - - /** - * Oracle specific code to handle it's lack of sanity - * @access private - */ - private function _rewrite_where($where_clause) - { - preg_match_all('/\s*(AND|OR)?\s*([\w_.]++)\s*(?:(=|<[=>]?|>=?)\s*((?>\'(?>[^\']++|\'\')*+\'|[\d-.]+))|((NOT )?IN\s*\((?>\'(?>[^\']++|\'\')*+\',? ?|[\d-.]+,? ?)*+\)))/', $where_clause, $result, PREG_SET_ORDER); - $out = ''; - - foreach ($result as $val) - { - if (!isset($val[5])) - { - if ($val[4] !== "''") - { - $out .= $val[0]; - } - else - { - $out .= ' ' . $val[1] . ' ' . $val[2]; - if ($val[3] == '=') - { - $out .= ' is NULL'; - } - else if ($val[3] == '<>') - { - $out .= ' is NOT NULL'; - } - } - } - else - { - $in_clause = array(); - $sub_exp = substr($val[5], strpos($val[5], '(') + 1, -1); - $extra = false; - preg_match_all('/\'(?>[^\']++|\'\')*+\'|[\d-.]++/', $sub_exp, $sub_vals, PREG_PATTERN_ORDER); - $i = 0; - - foreach ($sub_vals[0] as $sub_val) - { - // two things: - // 1) This determines if an empty string was in the IN clausing, making us turn it into a NULL comparison - // 2) This fixes the 1000 list limit that Oracle has (ORA-01795) - if ($sub_val !== "''") - { - $in_clause[(int) $i++/1000][] = $sub_val; - } - else - { - $extra = true; - } - } - - if (!$extra && $i < 1000) - { - $out .= $val[0]; - } - else - { - $out .= ' ' . $val[1] . '('; - $in_array = array(); - - // constuct each IN() clause - foreach ($in_clause as $in_values) - { - $in_array[] = $val[2] . ' ' . (isset($val[6]) ? $val[6] : '') . 'IN(' . implode(', ', $in_values) . ')'; - } - - // Join the IN() clauses against a few ORs (IN is just a nicer OR anyway) - $out .= implode(' OR ', $in_array); - - // handle the empty string case - if ($extra) - { - $out .= ' OR ' . $val[2] . ' is ' . (isset($val[6]) ? $val[6] : '') . 'NULL'; - } - $out .= ')'; - - unset($in_array, $in_clause); - } - } - } - - return $out; - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/postgres.php b/phpBB/includes/db/postgres.php deleted file mode 100644 index d74a8167e9..0000000000 --- a/phpBB/includes/db/postgres.php +++ /dev/null @@ -1,409 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* PostgreSQL Database Abstraction Layer -* Minimum Requirement: 8.2+ -* @package dbal -*/ -class phpbb_dbal_postgres extends phpbb_dbal -{ - /** - * @var string Database type. No distinction between versions or used extensions. - */ - public $dbms_type = 'postgres'; - - /** - * @var array Database type map, column layout information - */ - public $dbms_type_map = array( - 'INT:' => 'INT4', - 'BINT' => 'INT8', - 'UINT' => 'INT4', // unsigned - 'UINT:' => 'INT4', // unsigned - 'USINT' => 'INT2', // unsigned - 'BOOL' => 'INT2', // unsigned - 'TINT:' => 'INT2', - 'VCHAR' => 'varchar(255)', - 'VCHAR:' => 'varchar(%d)', - 'CHAR:' => 'char(%d)', - 'XSTEXT' => 'varchar(1000)', - 'STEXT' => 'varchar(3000)', - 'TEXT' => 'varchar(8000)', - 'MTEXT' => 'TEXT', - 'XSTEXT_UNI'=> 'varchar(100)', - 'STEXT_UNI' => 'varchar(255)', - 'TEXT_UNI' => 'varchar(4000)', - 'MTEXT_UNI' => 'TEXT', - 'TIMESTAMP' => 'INT4', // unsigned - 'DECIMAL' => 'decimal(5,2)', - 'DECIMAL:' => 'decimal(%d,2)', - 'PDECIMAL' => 'decimal(6,3)', - 'PDECIMAL:' => 'decimal(%d,3)', - 'VCHAR_UNI' => 'varchar(255)', - 'VCHAR_UNI:'=> 'varchar(%d)', - 'VARBINARY' => 'bytea', - ); - - /** - * @var string PostgreSQL schema (if supplied with $database -> database.schema) - */ - public $schema = ''; - - /** - * Connect to server. See {@link phpbb_dbal::sql_connect() sql_connect()} for details. - */ - public function sql_connect($server, $user, $password, $database, $port = false, $persistency = false , $new_link = false) - { - $this->persistency = $persistency; - $this->user = $user; - $this->server = $server; - $this->dbname = $database; - $this->port = $port; - - $connect_string = ''; - - if ($this->user) - { - $connect_string .= 'user=' . $this->user . ' '; - } - - if ($password) - { - $connect_string .= 'password=' . $password . ' '; - } - - if ($this->server) - { - if (strpos($this->server, ':') !== false) - { - list($this->server, $this->port) = explode(':', $this->server, 2); - } - - if ($this->server !== 'localhost') - { - $connect_string .= 'host=' . $this->server . ' '; - } - - if ($this->port) - { - $connect_string .= 'port=' . $this->port . ' '; - } - } - - $this->schema = ''; - - if ($this->dbname) - { - if (strpos($this->dbname, '.') !== false) - { - list($this->dbname, $this->schema) = explode('.', $this->dbname, 2); - } - $connect_string .= 'dbname=' . $this->dbname; - } - - $this->db_connect_id = ($this->persistency) ? @pg_pconnect($connect_string, ($new_link) ? PGSQL_CONNECT_FORCE_NEW : false) : @pg_connect($connect_string, ($new_link) ? PGSQL_CONNECT_FORCE_NEW : false); - - if (!$this->db_connect_id) - { - return $this->sql_error(htmlspecialchars_decode(phpbb::$last_notice['message'])); - } - - if ($this->schema) - { - @pg_query($this->db_connect_id, 'SET search_path TO ' . $this->schema); - } - - return $this->db_connect_id; - } - - /** - * Version information about used database. See {@link phpbb_dbal::sql_server_info() sql_server_info()} for details. - */ - public function sql_server_info($raw = false) - { - if (!phpbb::registered('acm') || ($this->sql_server_version = phpbb::$acm->get('#pgsql_version')) === false) - { - $query_id = @pg_query($this->db_connect_id, 'SELECT VERSION() AS version'); - $row = @pg_fetch_assoc($query_id, null); - @pg_free_result($query_id); - - $this->sql_server_version = (!empty($row['version'])) ? trim(substr($row['version'], 10)) : 0; - - if (phpbb::registered('acm')) - { - phpbb::$acm->put('#pgsql_version', $this->sql_server_version); - } - } - - return ($raw) ? $this->sql_server_version : 'PostgreSQL ' . $this->sql_server_version; - } - - /** - * DB-specific base query method. See {@link phpbb_dbal::_sql_query() _sql_query()} for details. - */ - protected function _sql_query($query) - { - return @pg_query($this->db_connect_id, $query); - } - - /** - * Build LIMIT query and run it. See {@link phpbb_dbal::_sql_query_limit() _sql_query_limit()} for details. - */ - protected function _sql_query_limit($query, $total, $offset, $cache_ttl) - { - // if $total is set to 0 we do not want to limit the number of rows - if ($total == 0) - { - $total = 'ALL'; - } - - $query .= "\n LIMIT $total OFFSET $offset"; - return $this->sql_query($query, $cache_ttl); - } - - /** - * Close sql connection. See {@link phpbb_dbal::_sql_close() _sql_close()} for details. - */ - protected function _sql_close() - { - return @pg_close($this->db_connect_id); - } - - /** - * SQL Transaction. See {@link phpbb_dbal::_sql_transaction() _sql_transaction()} for details. - */ - protected function _sql_transaction($status) - { - switch ($status) - { - case 'begin': - return @pg_query($this->db_connect_id, 'BEGIN'); - break; - - case 'commit': - return @pg_query($this->db_connect_id, 'COMMIT'); - break; - - case 'rollback': - return @pg_query($this->db_connect_id, 'ROLLBACK'); - break; - } - - return true; - } - - /** - * Return number of affected rows. See {@link phpbb_dbal::sql_affectedrows() sql_affectedrows()} for details. - */ - public function sql_affectedrows() - { - return ($this->query_result) ? @pg_affected_rows($this->query_result) : false; - } - - /** - * Get last inserted id after insert statement. See {@link phpbb_dbal::sql_nextid() sql_nextid()} for details. - */ - public function sql_nextid() - { - if (!$this->db_connect_id) - { - return false; - } - - $query = "SELECT lastval() AS last_value"; - $temp_q_id = @pg_query($this->db_connect_id, $query); - - if (!$temp_q_id) - { - return false; - } - - $temp_result = @pg_fetch_assoc($temp_q_id, NULL); - @pg_free_result($query_id); - - return ($temp_result) ? $temp_result['last_value'] : false; - } - - /** - * Fetch current row. See {@link phpbb_dbal::_sql_fetchrow() _sql_fetchrow()} for details. - */ - protected function _sql_fetchrow($query_id) - { - return @pg_fetch_assoc($query_id, null); - } - - /** - * Free query result. See {@link phpbb_dbal::_sql_freeresult() _sql_freeresult()} for details. - */ - protected function _sql_freeresult($query_id) - { - return @pg_free_result($query_id); - } - - /** - * Correctly adjust LIKE expression for special characters. See {@link phpbb_dbal::_sql_like_expression() _sql_like_expression()} for details. - */ - protected function _sql_like_expression($expression) - { - return $expression; - } - - /** - * Escape string used in sql query. See {@link phpbb_dbal::sql_escape() sql_escape()} for details. - * Note: Do not use for bytea values if we may use them at a later stage - */ - public function sql_escape($msg) - { - return @pg_escape_string($msg); - } - - /** - * Expose a DBMS specific function. See {@link phpbb_dbal::sql_function() sql_function()} for details. - */ - public function sql_function($type, $col) - { - switch ($type) - { - case 'length_varchar': - case 'length_text': - return 'LENGTH(' . $col . ')'; - break; - } - } - -/* - /** - * Handle data by using prepared statements. See {@link phpbb_dbal::sql_handle_data() sql_handle_data()} for details. - public function sql_handle_data($type, $table, $data, $where = '') - { - // for now, stmtname is an empty string, it might change to something more unique in the future - if ($type === 'INSERT') - { - $stmt = pg_prepare($this->dbms_type, '', "INSERT INTO $table (". implode(', ', array_keys($data)) . ") VALUES ($" . implode(', $', range(1, sizeof($data))) . ')'); - } - else - { - $query = "UPDATE $table SET "; - - $set = array(); - foreach (array_keys($data) as $key_id => $key) - { - $set[] = $key . ' = $' . $key_id; - } - $query .= implode(', ', $set); - - if ($where !== '') - { - $query .= $where; - } - - $stmt = pg_prepare($this->db_connect_id, '', $query); - } - - // add the stmtname to the top - array_unshift($data, ''); - - // add the connection resource - array_unshift($data, $this->db_connect_id); - - call_user_func_array('pg_execute', $data); - } -*/ - - /** - * Build DB-specific query bits. See {@link phpbb_dbal::_sql_custom_build() _sql_custom_build()} for details. - */ - protected function _sql_custom_build($stage, $data) - { - return $data; - } - - /** - * return sql error array. See {@link phpbb_dbal::_sql_error() _sql_error()} for details. - */ - protected function _sql_error() - { - return array( - 'message' => (!$this->db_connect_id) ? @pg_last_error() : @pg_last_error($this->db_connect_id), - 'code' => '' - ); - } - - /** - * Run DB-specific code to build SQL Report to explain queries, show statistics and runtime information. See {@link phpbb_dbal::_sql_report() _sql_report()} for details. - */ - protected function _sql_report($mode, $query = '') - { - switch ($mode) - { - case 'start': - - $explain_query = $query; - if (preg_match('/UPDATE ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m)) - { - $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2]; - } - else if (preg_match('/DELETE FROM ([a-z0-9_]+).*?WHERE(.*)/s', $query, $m)) - { - $explain_query = 'SELECT * FROM ' . $m[1] . ' WHERE ' . $m[2]; - } - - if (preg_match('/^SELECT/', $explain_query)) - { - $html_table = false; - - if ($result = @pg_query($this->db_connect_id, "EXPLAIN $explain_query")) - { - while ($row = @pg_fetch_assoc($result, NULL)) - { - $html_table = $this->sql_report('add_select_row', $query, $html_table, $row); - } - } - @pg_free_result($result); - - if ($html_table) - { - $this->html_hold .= '</table>'; - } - } - - break; - - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @pg_query($this->db_connect_id, $query); - while ($void = @pg_fetch_assoc($result, NULL)) - { - // Take the time spent on parsing rows into account - } - @pg_free_result($result); - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/db/sqlite.php b/phpBB/includes/db/sqlite.php deleted file mode 100644 index 0c5cd74f12..0000000000 --- a/phpBB/includes/db/sqlite.php +++ /dev/null @@ -1,307 +0,0 @@ -<?php -/** -* -* @package dbal -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Sqlite Database Abstraction Layer -* Minimum Requirement: 2.8.2+ -* @package dbal -*/ -class phpbb_dbal_sqlite extends phpbb_dbal -{ - /** - * @var string Database type. No distinction between versions or used extensions. - */ - public $dbms_type = 'sqlite'; - - /** - * Database features - * - * <ul> - * <li>multi_insert: Supports multi inserts</li> - * <li>count_distinct: Supports COUNT(DISTINGT ...)</li> - * <li>multi_table_deletion: Supports multiple table deletion</li> - * <li>truncate: Supports table truncation</li> - * </ul> - * - * @var array - */ - public $features = array( - 'multi_insert' => true, - // like MS ACCESS, SQLite does not support COUNT(DISTINCT ...) - 'count_distinct' => false, - 'multi_table_deletion' => true, - // can't truncate a table - 'truncate' => false, - ); - - /** - * @var array Database type map, column layout information - */ - public $dbms_type_map = array( - 'INT:' => 'int(%d)', - 'BINT' => 'bigint(20)', - 'UINT' => 'INTEGER UNSIGNED', //'mediumint(8) UNSIGNED', - 'UINT:' => 'INTEGER UNSIGNED', // 'int(%d) UNSIGNED', - 'TINT:' => 'tinyint(%d)', - 'USINT' => 'INTEGER UNSIGNED', //'mediumint(4) UNSIGNED', - 'BOOL' => 'INTEGER UNSIGNED', //'tinyint(1) UNSIGNED', - 'VCHAR' => 'varchar(255)', - 'VCHAR:' => 'varchar(%d)', - 'CHAR:' => 'char(%d)', - 'XSTEXT' => 'text(65535)', - 'STEXT' => 'text(65535)', - 'TEXT' => 'text(65535)', - 'MTEXT' => 'mediumtext(16777215)', - 'XSTEXT_UNI'=> 'text(65535)', - 'STEXT_UNI' => 'text(65535)', - 'TEXT_UNI' => 'text(65535)', - 'MTEXT_UNI' => 'mediumtext(16777215)', - 'TIMESTAMP' => 'INTEGER UNSIGNED', //'int(11) UNSIGNED', - 'DECIMAL' => 'decimal(5,2)', - 'DECIMAL:' => 'decimal(%d,2)', - 'PDECIMAL' => 'decimal(6,3)', - 'PDECIMAL:' => 'decimal(%d,3)', - 'VCHAR_UNI' => 'varchar(255)', - 'VCHAR_UNI:'=> 'varchar(%d)', - 'VARBINARY' => 'blob', - ); - - /** - * Connect to server. See {@link phpbb_dbal::sql_connect() sql_connect()} for details. - */ - public function sql_connect($server, $user, $password, $database, $port = false, $persistency = false , $new_link = false) - { - $this->persistency = $persistency; - $this->user = $user; - $this->server = $server . (($port) ? ':' . $port : ''); - $this->dbname = $database; - - $error = ''; - $this->db_connect_id = ($this->persistency) ? @sqlite_popen($this->server, 0666, $error) : @sqlite_open($this->server, 0666, $error); - - if ($this->db_connect_id) - { - @sqlite_query('PRAGMA short_column_names = 1', $this->db_connect_id); - @sqlite_query('PRAGMA encoding = "UTF-8"', $this->db_connect_id); - } - - return ($this->db_connect_id) ? true : array('message' => $error); - } - - /** - * Version information about used database. See {@link phpbb_dbal::sql_server_info() sql_server_info()} for details. - */ - public function sql_server_info($raw = false) - { - if (!phpbb::registered('acm') || ($this->sql_server_version = phpbb::$acm->get('#sqlite_version')) === false) - { - $result = @sqlite_query('SELECT sqlite_version() AS version', $this->db_connect_id); - $row = @sqlite_fetch_array($result, SQLITE_ASSOC); - - $this->sql_server_version = (!empty($row['version'])) ? $row['version'] : 0; - - if (phpbb::registered('acm')) - { - phpbb::$acm->put('#sqlite_version', $this->sql_server_version); - } - } - - return ($raw) ? $this->sql_server_version : 'SQLite ' . $this->sql_server_version; - } - - /** - * DB-specific base query method. See {@link phpbb_dbal::_sql_query() _sql_query()} for details. - */ - protected function _sql_query($query) - { - return @sqlite_query($query, $this->db_connect_id); - } - - /** - * Build LIMIT query and run it. See {@link phpbb_dbal::_sql_query_limit() _sql_query_limit()} for details. - */ - protected function _sql_query_limit($query, $total, $offset, $cache_ttl) - { - // if $total is set to 0 we do not want to limit the number of rows - if ($total == 0) - { - $total = -1; - } - - $query .= "\n LIMIT " . ((!empty($offset)) ? $offset . ', ' . $total : $total); - - return $this->sql_query($query, $cache_ttl); - } - - /** - * Close sql connection. See {@link phpbb_dbal::_sql_close() _sql_close()} for details. - */ - protected function _sql_close() - { - return @sqlite_close($this->db_connect_id); - } - - /** - * SQL Transaction. See {@link phpbb_dbal::_sql_transaction() _sql_transaction()} for details. - */ - protected function _sql_transaction($status) - { - switch ($status) - { - case 'begin': - return @sqlite_query('BEGIN', $this->db_connect_id); - break; - - case 'commit': - return @sqlite_query('COMMIT', $this->db_connect_id); - break; - - case 'rollback': - return @sqlite_query('ROLLBACK', $this->db_connect_id); - break; - } - - return true; - } - - /** - * Return number of affected rows. See {@link phpbb_dbal::sql_affectedrows() sql_affectedrows()} for details. - */ - public function sql_affectedrows() - { - return ($this->db_connect_id) ? @sqlite_changes($this->db_connect_id) : false; - } - - /** - * Get last inserted id after insert statement. See {@link phpbb_dbal::sql_nextid() sql_nextid()} for details. - */ - public function sql_nextid() - { - return ($this->db_connect_id) ? @sqlite_last_insert_rowid($this->db_connect_id) : false; - } - - /** - * Fetch current row. See {@link phpbb_dbal::_sql_fetchrow() _sql_fetchrow()} for details. - */ - protected function _sql_fetchrow($query_id) - { - return @sqlite_fetch_array($query_id, SQLITE_ASSOC); - } - - /** - * Free query result. See {@link phpbb_dbal::_sql_freeresult() _sql_freeresult()} for details. - */ - protected function _sql_freeresult($query_id) - { - return true; - } - - /** - * Correctly adjust LIKE expression for special characters. See {@link phpbb_dbal::_sql_like_expression() _sql_like_expression()} for details. - */ - protected function _sql_like_expression($expression) - { - // Unlike LIKE, GLOB is case sensitive (unfortunatly). SQLite users need to live with it! - // We only catch * and ? here, not the character map possible for file globbing. - $expression = str_replace(array(chr(0) . '_', chr(0) . '%'), array(chr(0) . '?', chr(0) . '*'), $expression); - - $expression = str_replace(array('?', '*'), array("\?", "\*"), $expression); - $expression = str_replace(array(chr(0) . "\?", chr(0) . "\*"), array('?', '*'), $expression); - - return 'GLOB \'' . $this->sql_escape($expression) . '\''; - } - - /** - * Escape string used in sql query. See {@link phpbb_dbal::sql_escape() sql_escape()} for details. - */ - public function sql_escape($msg) - { - return @sqlite_escape_string($msg); - } - - /** - * Expose a DBMS specific function. See {@link phpbb_dbal::sql_function() sql_function()} for details. - */ - public function sql_function($type, $col) - { - switch ($type) - { - case 'length_varchar': - case 'length_text': - return 'LENGTH(' . $col . ')'; - break; - } - } - - /** - * Handle data by using prepared statements. See {@link phpbb_dbal::sql_handle_data() sql_handle_data()} for details. - public function sql_handle_data($type, $table, $data, $where = '') - { - } - */ - - /** - * Build DB-specific query bits. See {@link phpbb_dbal::_sql_custom_build() _sql_custom_build()} for details. - */ - protected function _sql_custom_build($stage, $data) - { - return $data; - } - - /** - * return sql error array. See {@link phpbb_dbal::_sql_error() _sql_error()} for details. - */ - protected function _sql_error() - { - return array( - 'message' => @sqlite_error_string(@sqlite_last_error($this->db_connect_id)), - 'code' => @sqlite_last_error($this->db_connect_id) - ); - } - - /** - * Run DB-specific code to build SQL Report to explain queries, show statistics and runtime information. See {@link phpbb_dbal::_sql_report() _sql_report()} for details. - */ - protected function _sql_report($mode, $query = '') - { - switch ($mode) - { - case 'start': - break; - - case 'fromcache': - $endtime = explode(' ', microtime()); - $endtime = $endtime[0] + $endtime[1]; - - $result = @sqlite_query($query, $this->db_connect_id); - while ($void = @sqlite_fetch_array($result, SQLITE_ASSOC)) - { - // Take the time spent on parsing rows into account - } - - $splittime = explode(' ', microtime()); - $splittime = $splittime[0] + $splittime[1]; - - $this->sql_report('record_fromcache', $query, $endtime, $splittime); - - break; - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/formatted_text.php b/phpBB/includes/formatted_text.php deleted file mode 100644 index ca801bfea7..0000000000 --- a/phpBB/includes/formatted_text.php +++ /dev/null @@ -1,297 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** - * Formatted text class to handle any text that can contain BBCodes, smilies, magic URLs or under word censor. - */ -class formatted_text -{ - /** - * Unformated text. - * - * @var string - */ - private $text; - - /** - * Internal representation (first_pass data). - * - * @var string - */ - private $meta; - - /** - * Formatting options as bit flag. - * - * @see bbcode_parser - * - * @var int - */ - private $flags; - - /** - * Compiled $text. For dispaly. - * - * @var string - */ - private $compiled; - - /** - * Set to true if text, meta or flags have been changed, false otherwise. - * - * @var bool - */ - private $changed; - - /** - * DB table to update - * - * @var string - */ - private $update_table = ''; - - /** - * Column in $update_table to update. - * - * @var string - */ - private $update_column = ''; - - /** - * Where clause for auto update. - * - * @var string - */ - private $update_where = ''; - - /** - * Creates a new instance. - * - * @param string $text - * @param string $meta - * @param int $flags - */ - public function __construct($text, $meta = '', $flags = 0) - { - $this->text = $text; - $this->meta = $meta; - $this->flags = $flags; - $this->compiled = ''; - - if ($meta == '') - { - $this->changed = true; - } - else - { - $this->changed = false; - } - } - - public function __destruct() - { - if ($this->changed && $this->update_table) - { - $this->to_db($this->update_table, $this->update_column, $this->update_where); - } - } - - /** - * Convieniently initialize a formatted_text object from - * a database result set. The array must contain the following indexes: - * $column, {$column}_meta and {$column}_flags - * - * - * @param array $data - * @param string $column - * @return formatted_text - */ - public static function from_db_data(array $data, $column) - { - return new formatted_text($data[$column], $data[$column . '_meta'], (int) $data[$column . '_flags']); - } - - /** - * Returns the $text formatted, ready to be displayed on a webpage. - * - * @return string - */ - public function to_display() - { - $this->set_compiled(); - return $this->compiled; - } - - /** - * Updates $table, sets $column, {$column}_meta and {$column}_flags. - * All 3 columns must exist. - * - * @param string $table - * @param string $column - * @param string $where - * @return bool - */ - public function to_db($table, $column, $where = '1') - { - $this->changed = false; - - $sql = 'UPDATE ' . $table . ' SET ' . phpbb::$db->sql_build_query('UPDATE', $this->to_db_data($column)) - . ' WHERE ' . $where; - return (bool) phpbb::$db->sql_query($sql); - } - - /** - * Returns an array containing $column, {$column}_meta and {$column}_flags - * indexes to be used with query generating functions. - * - * @param string $column - * @return array - */ - public function to_db_data($column) - { - $this->set_meta(); - return array($column => $this->text, $column . '_meta' => $this->meta, $column . '_flags' => $this->flags); - } - - /** - * Enable automatic database update on - * - * @param string $table - * @param string $column - * @param string $where - */ - public function set_auto_update($table, $column, $where = '1') - { - $this->update_table = $table; - $this->update_column = $column; - $this->update_where = $where; - } - - /** - * Sets $meta if not set. - */ - private function set_meta() - { - if (strlen($this->meta)) - { - return; - } - - $parser = new phpbb_bbcode_parser; - $this->meta = $parser->first_pass($this->text); - } - - /** - * Sets $compiled if not set. - */ - private function set_compiled() - { - $this->set_meta(); - - if (strlen($this->compiled)) - { - return; - } - - $parser = new phpbb_bbcode_parser; - $parser->set_flags($this->flags); - $this->compiled = $parser->second_pass($this->meta); - } - - /** - * Sets $text. - * - * @param string $text - */ - public function set_text($text) - { - if ($this->text != $text) - { - $this->text = (string) $text; - $this->meta = ''; - $this->compiled = ''; - } - } - - /** - * Sets $flags. - * - * @param int $flags - */ - public function set_flags($flags) - { - $flags = (int) $flags; - if ($this->flags != $flags) - { - $this->flags = $flags; - $this->compiled = ''; - } - } - - /** - * Returns the current text. - * - * @return string - */ - public function get_text() - { - return $this->text; - } - - /** - * Returns the current(!!) metadata. - * - * @return string - */ - public function get_meta() - { - return $this->meta; - } - - /** - * Returns the current flags. - * - * @return int - */ - public function get_flags() - { - return $this->flags; - } - - /** - * Returns true if $this is equal to $other. - * Objects are only equal if $text and $flags are equal. - * - * @param formatted_text $other - * @return bool - */ - public function eq(formatted_text $other) - { - return $this->flags == $other->get_flags() && $this->text == $other->get_text(); - } - - /** - * Cast to string. Object is represented by the formatted version of $text with respect to $flags. - * - * @return string - */ - public function __toString() - { - return $this->to_display(); - } -} diff --git a/phpBB/includes/functions.php b/phpBB/includes/functions.php deleted file mode 100644 index 71b96757b5..0000000000 --- a/phpBB/includes/functions.php +++ /dev/null @@ -1,2562 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Wrapper function of phpbb_request::variable which exists for backwards compatability. -* See {@link phpbb_request::variable phpbb_request::variable} for documentation of this function's use. -* -* @param string|array $var_name The form variable's name from which data shall be retrieved. -* If the value is an array this may be an array of indizes which will give -* direct access to a value at any depth. E.g. if the value of "var" is array(1 => "a") -* then specifying array("var", 1) as the name will return "a". -* @param mixed $default A default value that is returned if the variable was not set. -* This function will always return a value of the same type as the default. -* @param bool $multibyte If $default is a string this paramater has to be true if the variable may contain any UTF-8 characters -* Default is false, causing all bytes outside the ASCII range (0-127) to be replaced with question marks -* @param bool $cookie This param is mapped to phpbb_request::COOKIE as the last param for phpbb_request::variable for backwards compatability reasons. -* -* @return mixed The value of $_REQUEST[$var_name] run through {@link set_var set_var} to ensure that the type is the -* the same as that of $default. If the variable is not set $default is returned. -*/ -function request_var($var_name, $default, $multibyte = false, $cookie = false) -{ - return phpbb_request::variable($var_name, $default, $multibyte, ($cookie) ? phpbb_request::COOKIE : phpbb_request::REQUEST); -} - -/** -* Wrapper for phpbb::$url->append_sid() -*/ -function append_sid($url, $params = false, $is_amp = true, $session_id = false) -{ - return phpbb::$url->append_sid($url, $params, $is_amp, $session_id); -} - -/** -* Set config value. -* Creates missing config entry if update did not succeed and phpbb::$config for this entry empty. -* -* @param string $config_name The configuration keys name -* @param string $config_value The configuration value -* @param bool $is_dynamic True if the configuration entry is not cached -*/ -function set_config($config_name, $config_value, $is_dynamic = false) -{ - $sql = 'UPDATE ' . CONFIG_TABLE . " - SET config_value = '" . phpbb::$db->sql_escape($config_value) . "' - WHERE config_name = '" . phpbb::$db->sql_escape($config_name) . "'"; - phpbb::$db->sql_query($sql); - - if (!phpbb::$db->sql_affectedrows() && !isset(phpbb::$config[$config_name])) - { - $sql = 'INSERT INTO ' . CONFIG_TABLE . ' ' . phpbb::$db->sql_build_array('INSERT', array( - 'config_name' => (string) $config_name, - 'config_value' => (string) $config_value, - 'is_dynamic' => (int) $is_dynamic, - )); - phpbb::$db->sql_query($sql); - } - - phpbb::$config[$config_name] = $config_value; - - if (!$is_dynamic) - { - phpbb::$acm->destroy('#config'); - } -} - -/** -* Set dynamic config value with arithmetic operation. -*/ -function set_config_count($config_name, $increment, $is_dynamic = false) -{ - switch (phpbb::$db->sql_layer) - { - case 'firebird': - $sql_update = 'CAST(CAST(config_value as integer) + ' . (int) $increment . ' as CHAR)'; - break; - - case 'postgres': - $sql_update = 'int4(config_value) + ' . (int) $increment; - break; - - // MySQL, SQlite, mssql, mssql_odbc, oracle - default: - $sql_update = 'config_value + ' . (int) $increment; - break; - } - - phpbb::$db->sql_query('UPDATE ' . CONFIG_TABLE . ' SET config_value = ' . $sql_update . " WHERE config_name = '" . phpbb::$db->sql_escape($config_name) . "'"); - - if (!$is_dynamic) - { - phpbb::$acm->destroy('#config'); - } -} - -/** -* Return formatted string for filesizes -* @todo move those functions to a helper class? -*/ -function get_formatted_filesize($bytes, $add_size_lang = true) -{ - if ($bytes >= pow(2, 20)) - { - return ($add_size_lang) ? round($bytes / 1024 / 1024, 2) . ' ' . phpbb::$user->lang['MIB'] : round($bytes / 1024 / 1024, 2); - } - - if ($bytes >= pow(2, 10)) - { - return ($add_size_lang) ? round($bytes / 1024, 2) . ' ' . phpbb::$user->lang['KIB'] : round($bytes / 1024, 2); - } - - return ($add_size_lang) ? ($bytes) . ' ' . phpbb::$user->lang['BYTES'] : ($bytes); -} - -/** -* Determine whether we are approaching the maximum execution time. Should be called once -* at the beginning of the script in which it's used. -* @return bool Either true if the maximum execution time is nearly reached, or false -* if some time is still left. -* @todo helper? -*/ -function still_on_time($extra_time = 15) -{ - static $max_execution_time, $start_time; - - $time = explode(' ', microtime()); - $current_time = $time[0] + $time[1]; - - if (empty($max_execution_time)) - { - $max_execution_time = (function_exists('ini_get')) ? (int) @ini_get('max_execution_time') : (int) @get_cfg_var('max_execution_time'); - - // If zero, then set to something higher to not let the user catch the ten seconds barrier. - if ($max_execution_time === 0) - { - $max_execution_time = 50 + $extra_time; - } - - $max_execution_time = min(max(10, ($max_execution_time - $extra_time)), 50); - - // For debugging purposes - // $max_execution_time = 10; - - global $starttime; - $start_time = (empty($starttime)) ? $current_time : $starttime; - } - - return (ceil($current_time - $start_time) < $max_execution_time) ? true : false; -} - - /** - * Add a secret hash for use in links/GET requests - * @param string $link_name The name of the link; has to match the name used in check_link_hash, otherwise no restrictions apply - * @return string the hash -* @todo add to security, but do not use the current hash mechanism - */ -/* -@todo should use our hashing instead of a "custom" one -*/ - function generate_link_hash($link_name) - { - if (!isset(phpbb::$user->data["hash_$link_name"])) - { - phpbb::$user->data["hash_$link_name"] = substr(sha1(phpbb::$user->data['user_form_salt'] . $link_name), 0, 8); - } - - return phpbb::$user->data["hash_$link_name"]; - } - - - /** - * checks a link hash - for GET requests - * @param string $token the submitted token - * @param string $link_name The name of the link - * @return boolean true if all is fine -* @todo add to security - */ - - function check_link_hash($token, $link_name) - { - return $token === generate_link_hash($link_name); - } - -// functions used for building option fields - -/** -* Pick a language, any language ... -* @todo integrated into form builder? -*/ -function language_select($default = '') -{ - $sql = 'SELECT lang_iso, lang_local_name - FROM ' . LANG_TABLE . ' - ORDER BY lang_english_name'; - $result = phpbb::$db->sql_query($sql); - - $lang_options = ''; - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $selected = ($row['lang_iso'] == $default) ? ' selected="selected"' : ''; - $lang_options .= '<option value="' . $row['lang_iso'] . '"' . $selected . '>' . $row['lang_local_name'] . '</option>'; - } - phpbb::$db->sql_freeresult($result); - - return $lang_options; -} - -/** -* Pick a template/theme combo, -* @todo integrated into form builder? -*/ -function style_select($default = '', $all = false) -{ - $sql_where = (!$all) ? 'WHERE style_active = 1 ' : ''; - $sql = 'SELECT style_id, style_name - FROM ' . STYLES_TABLE . " - $sql_where - ORDER BY style_name"; - $result = phpbb::$db->sql_query($sql); - - $style_options = ''; - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $selected = ($row['style_id'] == $default) ? ' selected="selected"' : ''; - $style_options .= '<option value="' . $row['style_id'] . '"' . $selected . '>' . $row['style_name'] . '</option>'; - } - phpbb::$db->sql_freeresult($result); - - return $style_options; -} - -/** -* Pick a timezone -* @todo integrated into form builder? -*/ -function tz_select($default = '', $truncate = false) -{ - $tz_select = ''; - foreach (phpbb::$user->lang['tz_zones'] as $offset => $zone) - { - if ($truncate) - { - $zone_trunc = truncate_string($zone, 50, 255, false, '...'); - } - else - { - $zone_trunc = $zone; - } - - if (is_numeric($offset)) - { - $selected = ($offset == $default) ? ' selected="selected"' : ''; - $tz_select .= '<option title="'.$zone.'" value="' . $offset . '"' . $selected . '>' . $zone_trunc . '</option>'; - } - } - - return $tz_select; -} - -/** -* Marks a topic/forum as read -* Marks a topic as posted to -* -* @param int $user_id can only be used with $mode == 'post' -* @todo add to a tracking class used by forum/topic/post API, except for the marking features -*/ -function markread($mode, $forum_id = false, $topic_id = false, $post_time = 0, $user_id = 0) -{ - if ($mode == 'all') - { - if ($forum_id === false || !sizeof($forum_id)) - { - if (phpbb::$config['load_db_lastread'] && phpbb::$user->is_registered) - { - // Mark all forums read (index page) - phpbb::$db->sql_query('DELETE FROM ' . TOPICS_TRACK_TABLE . ' WHERE user_id = ' . phpbb::$user->data['user_id']); - phpbb::$db->sql_query('DELETE FROM ' . FORUMS_TRACK_TABLE . ' WHERE user_id = ' . phpbb::$user->data['user_id']); - phpbb::$db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_lastmark = ' . time() . ' WHERE user_id = ' . phpbb::$user->data['user_id']); - } - else if (phpbb::$config['load_anon_lastread'] || phpbb::$user->is_registered) - { - $tracking_topics = phpbb_request::variable(phpbb::$config['cookie_name'] . '_track', '', false, phpbb_request::COOKIE); - $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array(); - - unset($tracking_topics['tf']); - unset($tracking_topics['t']); - unset($tracking_topics['f']); - $tracking_topics['l'] = base_convert(time() - phpbb::$config['board_startdate'], 10, 36); - - phpbb::$user->set_cookie('track', tracking_serialize($tracking_topics), time() + 31536000); - phpbb_request::overwrite(phpbb::$config['cookie_name'] . '_track', tracking_serialize($tracking_topics), phpbb_request::COOKIE); - - unset($tracking_topics); - - if (phpbb::$user->is_registered) - { - phpbb::$db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_lastmark = ' . time() . ' WHERE user_id = ' . phpbb::$user->data['user_id']); - } - } - } - - return; - } - else if ($mode == 'topics') - { - // Mark all topics in forums read - if (!is_array($forum_id)) - { - $forum_id = array($forum_id); - } - - // Add 0 to forums array to mark global announcements correctly - $forum_id[] = 0; - - if (phpbb::$config['load_db_lastread'] && phpbb::$user->is_registered) - { - $sql = 'DELETE FROM ' . TOPICS_TRACK_TABLE . ' - WHERE user_id = ' . phpbb::$user->data['user_id'] . ' - AND ' . phpbb::$db->sql_in_set('forum_id', $forum_id); - phpbb::$db->sql_query($sql); - - $sql = 'SELECT forum_id - FROM ' . FORUMS_TRACK_TABLE . ' - WHERE user_id = ' . phpbb::$user->data['user_id'] . ' - AND ' . phpbb::$db->sql_in_set('forum_id', $forum_id); - $result = phpbb::$db->sql_query($sql); - - $sql_update = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $sql_update[] = (int) $row['forum_id']; - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($sql_update)) - { - $sql = 'UPDATE ' . FORUMS_TRACK_TABLE . ' - SET mark_time = ' . time() . ' - WHERE user_id = ' . phpbb::$user->data['user_id'] . ' - AND ' . phpbb::$db->sql_in_set('forum_id', $sql_update); - phpbb::$db->sql_query($sql); - } - - if ($sql_insert = array_diff($forum_id, $sql_update)) - { - $sql_ary = array(); - foreach ($sql_insert as $f_id) - { - $sql_ary[] = array( - 'user_id' => (int) phpbb::$user->data['user_id'], - 'forum_id' => (int) $f_id, - 'mark_time' => time() - ); - } - - phpbb::$db->sql_multi_insert(FORUMS_TRACK_TABLE, $sql_ary); - } - } - else if (phpbb::$config['load_anon_lastread'] || phpbb::$user->is_registered) - { - $tracking = phpbb_request::variable(phpbb::$config['cookie_name'] . '_track', '', false, phpbb_request::COOKIE); - $tracking = ($tracking) ? tracking_unserialize($tracking) : array(); - - foreach ($forum_id as $f_id) - { - $topic_ids36 = (isset($tracking['tf'][$f_id])) ? $tracking['tf'][$f_id] : array(); - - if (isset($tracking['tf'][$f_id])) - { - unset($tracking['tf'][$f_id]); - } - - foreach ($topic_ids36 as $topic_id36) - { - unset($tracking['t'][$topic_id36]); - } - - if (isset($tracking['f'][$f_id])) - { - unset($tracking['f'][$f_id]); - } - - $tracking['f'][$f_id] = base_convert(time() - phpbb::$config['board_startdate'], 10, 36); - } - - if (isset($tracking['tf']) && empty($tracking['tf'])) - { - unset($tracking['tf']); - } - - phpbb::$user->set_cookie('track', tracking_serialize($tracking), time() + 31536000); - phpbb_request::overwrite(phpbb::$config['cookie_name'] . '_track', tracking_serialize($tracking), phpbb_request::COOKIE); - - unset($tracking); - } - - return; - } - else if ($mode == 'topic') - { - if ($topic_id === false || $forum_id === false) - { - return; - } - - if (phpbb::$config['load_db_lastread'] && phpbb::$user->is_registered) - { - $sql = 'UPDATE ' . TOPICS_TRACK_TABLE . ' - SET mark_time = ' . (($post_time) ? $post_time : time()) . ' - WHERE user_id = ' . phpbb::$user->data['user_id'] . ' - AND topic_id = ' . $topic_id; - phpbb::$db->sql_query($sql); - - // insert row - if (!phpbb::$db->sql_affectedrows()) - { - phpbb::$db->sql_return_on_error(true); - - $sql_ary = array( - 'user_id' => (int) phpbb::$user->data['user_id'], - 'topic_id' => (int) $topic_id, - 'forum_id' => (int) $forum_id, - 'mark_time' => ($post_time) ? (int) $post_time : time(), - ); - - phpbb::$db->sql_query('INSERT INTO ' . TOPICS_TRACK_TABLE . ' ' . phpbb::$db->sql_build_array('INSERT', $sql_ary)); - - phpbb::$db->sql_return_on_error(false); - } - } - else if (phpbb::$config['load_anon_lastread'] || phpbb::$user->is_registered) - { - $tracking = phpbb_request::variable(phpbb::$config['cookie_name'] . '_track', '', false, phpbb_request::COOKIE); - $tracking = ($tracking) ? tracking_unserialize($tracking) : array(); - - $topic_id36 = base_convert($topic_id, 10, 36); - - if (!isset($tracking['t'][$topic_id36])) - { - $tracking['tf'][$forum_id][$topic_id36] = true; - } - - $post_time = ($post_time) ? $post_time : time(); - $tracking['t'][$topic_id36] = base_convert($post_time - phpbb::$config['board_startdate'], 10, 36); - - // If the cookie grows larger than 10000 characters we will remove the smallest value - // This can result in old topics being unread - but most of the time it should be accurate... - if (strlen(phpbb_request::variable(phpbb::$config['cookie_name'] . '_track', '', false, phpbb_request::COOKIE)) > 10000) - { - //echo 'Cookie grown too large' . print_r($tracking, true); - - // We get the ten most minimum stored time offsets and its associated topic ids - $time_keys = array(); - for ($i = 0; $i < 10 && sizeof($tracking['t']); $i++) - { - $min_value = min($tracking['t']); - $m_tkey = array_search($min_value, $tracking['t']); - unset($tracking['t'][$m_tkey]); - - $time_keys[$m_tkey] = $min_value; - } - - // Now remove the topic ids from the array... - foreach ($tracking['tf'] as $f_id => $topic_id_ary) - { - foreach ($time_keys as $m_tkey => $min_value) - { - if (isset($topic_id_ary[$m_tkey])) - { - $tracking['f'][$f_id] = $min_value; - unset($tracking['tf'][$f_id][$m_tkey]); - } - } - } - - if (phpbb::$user->is_registered) - { - phpbb::$user->data['user_lastmark'] = intval(base_convert(max($time_keys) + phpbb::$config['board_startdate'], 36, 10)); - phpbb::$db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_lastmark = ' . phpbb::$user->data['user_lastmark'] . ' WHERE user_id = ' . phpbb::$user->data['user_id']); - } - else - { - $tracking['l'] = max($time_keys); - } - } - - phpbb::$user->set_cookie('track', tracking_serialize($tracking), time() + 31536000); - phpbb_request::overwrite(phpbb::$config['cookie_name'] . '_track', tracking_serialize($tracking)); - } - - return; - } - else if ($mode == 'post') - { - if ($topic_id === false) - { - return; - } - - $use_user_id = (!$user_id) ? phpbb::$user->data['user_id'] : $user_id; - - if (phpbb::$config['load_db_track'] && $use_user_id != ANONYMOUS) - { - phpbb::$db->sql_return_on_error(true); - - $sql_ary = array( - 'user_id' => (int) $use_user_id, - 'topic_id' => (int) $topic_id, - 'topic_posted' => 1 - ); - - phpbb::$db->sql_query('INSERT INTO ' . TOPICS_POSTED_TABLE . ' ' . phpbb::$db->sql_build_array('INSERT', $sql_ary)); - - phpbb::$db->sql_return_on_error(false); - } - - return; - } -} - -/** -* Get topic tracking info by using already fetched info -* @todo add to a tracking class used by forum/topic/post API -*/ -function get_topic_tracking($forum_id, $topic_ids, &$rowset, $forum_mark_time, $global_announce_list = false) -{ - $last_read = array(); - - if (!is_array($topic_ids)) - { - $topic_ids = array($topic_ids); - } - - foreach ($topic_ids as $topic_id) - { - if (!empty($rowset[$topic_id]['mark_time'])) - { - $last_read[$topic_id] = $rowset[$topic_id]['mark_time']; - } - } - - $topic_ids = array_diff($topic_ids, array_keys($last_read)); - - if (sizeof($topic_ids)) - { - $mark_time = array(); - - // Get global announcement info - if ($global_announce_list && sizeof($global_announce_list)) - { - if (!isset($forum_mark_time[0])) - { - $sql = 'SELECT mark_time - FROM ' . FORUMS_TRACK_TABLE . ' - WHERE user_id = ' . phpbb::$user->data['user_id'] . ' - AND forum_id = 0'; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ($row) - { - $mark_time[0] = $row['mark_time']; - } - } - else - { - if ($forum_mark_time[0] !== false) - { - $mark_time[0] = $forum_mark_time[0]; - } - } - } - - if (!empty($forum_mark_time[$forum_id]) && $forum_mark_time[$forum_id] !== false) - { - $mark_time[$forum_id] = $forum_mark_time[$forum_id]; - } - - $user_lastmark = (isset($mark_time[$forum_id])) ? $mark_time[$forum_id] : phpbb::$user->data['user_lastmark']; - - foreach ($topic_ids as $topic_id) - { - if ($global_announce_list && isset($global_announce_list[$topic_id])) - { - $last_read[$topic_id] = (isset($mark_time[0])) ? $mark_time[0] : $user_lastmark; - } - else - { - $last_read[$topic_id] = $user_lastmark; - } - } - } - - return $last_read; -} - -/** -* Get topic tracking info from db (for cookie based tracking only this function is used) -* @todo add to a tracking class used by forum/topic/post API -*/ -function get_complete_topic_tracking($forum_id, $topic_ids, $global_announce_list = false) -{ - $last_read = array(); - - if (!is_array($topic_ids)) - { - $topic_ids = array($topic_ids); - } - - if (phpbb::$config['load_db_lastread'] && phpbb::$user->is_registered) - { - $sql = 'SELECT topic_id, mark_time - FROM ' . TOPICS_TRACK_TABLE . ' - WHERE user_id = ' . phpbb::$user->data['user_id'] . ' - AND ' . phpbb::$db->sql_in_set('topic_id', $topic_ids); - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $last_read[$row['topic_id']] = $row['mark_time']; - } - phpbb::$db->sql_freeresult($result); - - $topic_ids = array_diff($topic_ids, array_keys($last_read)); - - if (sizeof($topic_ids)) - { - $sql = 'SELECT forum_id, mark_time - FROM ' . FORUMS_TRACK_TABLE . ' - WHERE user_id = ' . phpbb::$user->data['user_id'] . ' - AND forum_id ' . - (($global_announce_list && sizeof($global_announce_list)) ? "IN (0, $forum_id)" : "= $forum_id"); - $result = phpbb::$db->sql_query($sql); - - $mark_time = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $mark_time[$row['forum_id']] = $row['mark_time']; - } - phpbb::$db->sql_freeresult($result); - - $user_lastmark = (isset($mark_time[$forum_id])) ? $mark_time[$forum_id] : phpbb::$user->data['user_lastmark']; - - foreach ($topic_ids as $topic_id) - { - if ($global_announce_list && isset($global_announce_list[$topic_id])) - { - $last_read[$topic_id] = (isset($mark_time[0])) ? $mark_time[0] : $user_lastmark; - } - else - { - $last_read[$topic_id] = $user_lastmark; - } - } - } - } - else if (phpbb::$config['load_anon_lastread'] || phpbb::$user->is_registered) - { - global $tracking_topics; - - if (!isset($tracking_topics) || !sizeof($tracking_topics)) - { - $tracking_topics = phpbb_request::variable(phpbb::$config['cookie_name'] . '_track', '', false, phpbb_request::COOKIE); - $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array(); - } - - if (!phpbb::$user->is_registered) - { - $user_lastmark = (isset($tracking_topics['l'])) ? base_convert($tracking_topics['l'], 36, 10) + phpbb::$config['board_startdate'] : 0; - } - else - { - $user_lastmark = phpbb::$user->data['user_lastmark']; - } - - foreach ($topic_ids as $topic_id) - { - $topic_id36 = base_convert($topic_id, 10, 36); - - if (isset($tracking_topics['t'][$topic_id36])) - { - $last_read[$topic_id] = base_convert($tracking_topics['t'][$topic_id36], 36, 10) + phpbb::$config['board_startdate']; - } - } - - $topic_ids = array_diff($topic_ids, array_keys($last_read)); - - if (sizeof($topic_ids)) - { - $mark_time = array(); - if ($global_announce_list && sizeof($global_announce_list)) - { - if (isset($tracking_topics['f'][0])) - { - $mark_time[0] = base_convert($tracking_topics['f'][0], 36, 10) + phpbb::$config['board_startdate']; - } - } - - if (isset($tracking_topics['f'][$forum_id])) - { - $mark_time[$forum_id] = base_convert($tracking_topics['f'][$forum_id], 36, 10) + phpbb::$config['board_startdate']; - } - - $user_lastmark = (isset($mark_time[$forum_id])) ? $mark_time[$forum_id] : $user_lastmark; - - foreach ($topic_ids as $topic_id) - { - if ($global_announce_list && isset($global_announce_list[$topic_id])) - { - $last_read[$topic_id] = (isset($mark_time[0])) ? $mark_time[0] : $user_lastmark; - } - else - { - $last_read[$topic_id] = $user_lastmark; - } - } - } - } - - return $last_read; -} - -/** -* Check for read forums and update topic tracking info accordingly -* -* @param int $forum_id the forum id to check -* @param int $forum_last_post_time the forums last post time -* @param int $f_mark_time the forums last mark time if user is registered and load_db_lastread enabled -* @param int $mark_time_forum false if the mark time needs to be obtained, else the last users forum mark time -* -* @return true if complete forum got marked read, else false. -* @todo add to a tracking class used by forum/topic/post API -*/ -function update_forum_tracking_info($forum_id, $forum_last_post_time, $f_mark_time = false, $mark_time_forum = false) -{ - global $tracking_topics; - - // Determine the users last forum mark time if not given. - if ($mark_time_forum === false) - { - if (phpbb::$config['load_db_lastread'] && phpbb::$user->is_registered) - { - $mark_time_forum = (!empty($f_mark_time)) ? $f_mark_time : phpbb::$user->data['user_lastmark']; - } - else if (phpbb::$config['load_anon_lastread'] || phpbb::$user->is_registered) - { - $tracking_topics = phpbb_request::variable(phpbb::$config['cookie_name'] . '_track', '', false, phpbb_request::COOKIE); - $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array(); - - if (!phpbb::$user->is_registered) - { - phpbb::$user->data['user_lastmark'] = (isset($tracking_topics['l'])) ? (int) (base_convert($tracking_topics['l'], 36, 10) + phpbb::$config['board_startdate']) : 0; - } - - $mark_time_forum = (isset($tracking_topics['f'][$forum_id])) ? (int) (base_convert($tracking_topics['f'][$forum_id], 36, 10) + phpbb::$config['board_startdate']) : phpbb::$user->data['user_lastmark']; - } - } - - // Check the forum for any left unread topics. - // If there are none, we mark the forum as read. - if (phpbb::$config['load_db_lastread'] && phpbb::$user->is_registered) - { - if ($mark_time_forum >= $forum_last_post_time) - { - // We do not need to mark read, this happened before. Therefore setting this to true - $row = true; - } - else - { - $sql = 'SELECT t.forum_id FROM ' . TOPICS_TABLE . ' t - LEFT JOIN ' . TOPICS_TRACK_TABLE . ' tt ON (tt.topic_id = t.topic_id AND tt.user_id = ' . phpbb::$user->data['user_id'] . ') - WHERE t.forum_id = ' . $forum_id . ' - AND t.topic_last_post_time > ' . $mark_time_forum . ' - AND t.topic_moved_id = 0 - AND (tt.topic_id IS NULL OR tt.mark_time < t.topic_last_post_time) - GROUP BY t.forum_id'; - $result = phpbb::$db->sql_query_limit($sql, 1); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - } - } - else if (phpbb::$config['load_anon_lastread'] || phpbb::$user->is_registered) - { - // Get information from cookie - $row = false; - - if (!isset($tracking_topics['tf'][$forum_id])) - { - // We do not need to mark read, this happened before. Therefore setting this to true - $row = true; - } - else - { - $sql = 'SELECT topic_id - FROM ' . TOPICS_TABLE . ' - WHERE forum_id = ' . $forum_id . ' - AND topic_last_post_time > ' . $mark_time_forum . ' - AND topic_moved_id = 0'; - $result = phpbb::$db->sql_query($sql); - - $check_forum = $tracking_topics['tf'][$forum_id]; - $unread = false; - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if (!isset($check_forum[base_convert($row['topic_id'], 10, 36)])) - { - $unread = true; - break; - } - } - phpbb::$db->sql_freeresult($result); - - $row = $unread; - } - } - else - { - $row = true; - } - - if (!$row) - { - markread('topics', $forum_id); - return true; - } - - return false; -} - -/** -* Transform an array into a serialized format -* @todo add to a tracking class used by forum/topic/post API -*/ -function tracking_serialize($input) -{ - $out = ''; - foreach ($input as $key => $value) - { - if (is_array($value)) - { - $out .= $key . ':(' . tracking_serialize($value) . ');'; - } - else - { - $out .= $key . ':' . $value . ';'; - } - } - return $out; -} - -/** -* Transform a serialized array into an actual array -* @todo add to a tracking class used by forum/topic/post API -*/ -function tracking_unserialize($string, $max_depth = 3) -{ - $n = strlen($string); - if ($n > 10010) - { - die('Invalid data supplied'); - } - $data = $stack = array(); - $key = ''; - $mode = 0; - $level = &$data; - for ($i = 0; $i < $n; ++$i) - { - switch ($mode) - { - case 0: - switch ($string[$i]) - { - case ':': - $level[$key] = 0; - $mode = 1; - break; - case ')': - unset($level); - $level = array_pop($stack); - $mode = 3; - break; - default: - $key .= $string[$i]; - } - break; - - case 1: - switch ($string[$i]) - { - case '(': - if (sizeof($stack) >= $max_depth) - { - die('Invalid data supplied'); - } - $stack[] = &$level; - $level[$key] = array(); - $level = &$level[$key]; - $key = ''; - $mode = 0; - break; - default: - $level[$key] = $string[$i]; - $mode = 2; - break; - } - break; - - case 2: - switch ($string[$i]) - { - case ')': - unset($level); - $level = array_pop($stack); - $mode = 3; - break; - case ';': - $key = ''; - $mode = 0; - break; - default: - $level[$key] .= $string[$i]; - break; - } - break; - - case 3: - switch ($string[$i]) - { - case ')': - unset($level); - $level = array_pop($stack); - break; - case ';': - $key = ''; - $mode = 0; - break; - default: - die('Invalid data supplied'); - break; - } - break; - } - } - - if (sizeof($stack) != 0 || ($mode != 0 && $mode != 3)) - { - die('Invalid data supplied'); - } - - return $level; -} - -// Pagination functions - -/** -* Pagination routine, generates page number sequence -* tpl_prefix is for using different pagination blocks at one page -* @todo $pagination = phpbb_api::new('pagination') -*/ -function generate_pagination($base_url, $num_items, $per_page, $start_item, $add_prevnext_text = false, $tpl_prefix = '') -{ - // Make sure $per_page is a valid value - $per_page = ($per_page <= 0) ? 1 : $per_page; - - $seperator = '<span class="page-sep">' . phpbb::$user->lang['COMMA_SEPARATOR'] . '</span>'; - $total_pages = ceil($num_items / $per_page); - - if ($total_pages == 1 || !$num_items) - { - return false; - } - - $on_page = floor($start_item / $per_page) + 1; - $url_delim = (strpos($base_url, '?') === false) ? '?' : '&'; - - $page_string = ($on_page == 1) ? '<strong>1</strong>' : '<a href="' . $base_url . '">1</a>'; - - if ($total_pages > 5) - { - $start_cnt = min(max(1, $on_page - 4), $total_pages - 5); - $end_cnt = max(min($total_pages, $on_page + 4), 6); - - $page_string .= ($start_cnt > 1) ? ' ... ' : $seperator; - - for ($i = $start_cnt + 1; $i < $end_cnt; $i++) - { - $page_string .= ($i == $on_page) ? '<strong>' . $i . '</strong>' : '<a href="' . $base_url . "{$url_delim}start=" . (($i - 1) * $per_page) . '">' . $i . '</a>'; - if ($i < $end_cnt - 1) - { - $page_string .= $seperator; - } - } - - $page_string .= ($end_cnt < $total_pages) ? ' ... ' : $seperator; - } - else - { - $page_string .= $seperator; - - for ($i = 2; $i < $total_pages; $i++) - { - $page_string .= ($i == $on_page) ? '<strong>' . $i . '</strong>' : '<a href="' . $base_url . "{$url_delim}start=" . (($i - 1) * $per_page) . '">' . $i . '</a>'; - if ($i < $total_pages) - { - $page_string .= $seperator; - } - } - } - - $page_string .= ($on_page == $total_pages) ? '<strong>' . $total_pages . '</strong>' : '<a href="' . $base_url . "{$url_delim}start=" . (($total_pages - 1) * $per_page) . '">' . $total_pages . '</a>'; - - if ($add_prevnext_text) - { - if ($on_page != 1) - { - $page_string = '<a href="' . $base_url . "{$url_delim}start=" . (($on_page - 2) * $per_page) . '">' . phpbb::$user->lang['PREVIOUS'] . '</a> ' . $page_string; - } - - if ($on_page != $total_pages) - { - $page_string .= ' <a href="' . $base_url . "{$url_delim}start=" . ($on_page * $per_page) . '">' . phpbb::$user->lang['NEXT'] . '</a>'; - } - } - - phpbb::$template->assign_vars(array( - $tpl_prefix . 'BASE_URL' => $base_url, - 'A_' . $tpl_prefix . 'BASE_URL' => addslashes($base_url), - $tpl_prefix . 'PER_PAGE' => $per_page, - - $tpl_prefix . 'PREVIOUS_PAGE' => ($on_page == 1) ? '' : $base_url . "{$url_delim}start=" . (($on_page - 2) * $per_page), - $tpl_prefix . 'NEXT_PAGE' => ($on_page == $total_pages) ? '' : $base_url . "{$url_delim}start=" . ($on_page * $per_page), - $tpl_prefix . 'TOTAL_PAGES' => $total_pages, - )); - - return $page_string; -} - -/** -* Return current page (pagination) -* @todo $pagination = phpbb_api::new('pagination') -*/ -function on_page($num_items, $per_page, $start) -{ - // Make sure $per_page is a valid value - $per_page = ($per_page <= 0) ? 1 : $per_page; - - $on_page = floor($start / $per_page) + 1; - - phpbb::$template->assign_vars(array( - 'ON_PAGE' => $on_page, - )); - - return phpbb::$user->lang('PAGE_OF', $on_page, max(ceil($num_items / $per_page), 1)); -} - - -//Form validation - - - -/** -* Add a secret token to the form (requires the S_FORM_TOKEN template variable) -* @param string $form_name The name of the form; has to match the name used in check_form_key, otherwise no restrictions apply -* @todo add to form builder -*/ -function add_form_key($form_name) -{ - $now = time(); - $token_sid = (phpbb::$user->is_guest && !empty(phpbb::$config['form_token_sid_guests'])) ? phpbb::$user->session_id : ''; - $token = sha1($now . phpbb::$user->data['user_form_salt'] . $form_name . $token_sid); - - $s_fields = build_hidden_fields(array( - 'creation_time' => $now, - 'form_token' => $token, - )); - - phpbb::$template->assign_vars(array( - 'S_FORM_TOKEN' => $s_fields, - )); -} - -/** -* Check the form key. Required for all altering actions not secured by confirm_box -* @param string $form_name The name of the form; has to match the name used in add_form_key, otherwise no restrictions apply -* @param int $timespan The maximum acceptable age for a submitted form in seconds. Defaults to the config setting. -* @param string $return_page The address for the return link -* @param bool $trigger If true, the function will triger an error when encountering an invalid form -* @todo add to form builder -*/ -function check_form_key($form_name, $timespan = false, $return_page = '', $trigger = false) -{ - if ($timespan === false) - { - // we enforce a minimum value of half a minute here. - $timespan = (phpbb::$config['form_token_lifetime'] == -1) ? -1 : max(30, phpbb::$config['form_token_lifetime']); - } - - if (phpbb_request::is_set_post('creation_time') && phpbb_request::is_set_post('form_token')) - { - $creation_time = abs(request_var('creation_time', 0)); - $token = request_var('form_token', ''); - - $diff = time() - $creation_time; - - // If creation_time and the time() now is zero we can assume it was not a human doing this (the check for if ($diff)... - if ($diff && ($diff <= $timespan || $timespan === -1)) - { - $token_sid = (phpbb::$user->is_guest && !empty(phpbb::$config['form_token_sid_guests'])) ? phpbb::$user->session_id : ''; - $key = sha1($creation_time . phpbb::$user->data['user_form_salt'] . $form_name . $token_sid); - - if ($key === $token) - { - return true; - } - } - } - - if ($trigger) - { - trigger_error(phpbb::$user->lang['FORM_INVALID'] . $return_page); - } - - return false; -} - -// Message/Login boxes - -/** -* Build Confirm box -* @param boolean $check True for checking if confirmed (without any additional parameters) and false for displaying the confirm box -* @param string $title Title/Message used for confirm box. -* message text is _CONFIRM appended to title. -* If title cannot be found in user->lang a default one is displayed -* If title_CONFIRM cannot be found in user->lang the text given is used. -* @param string $hidden Hidden variables -* @param string $html_body Template used for confirm box -* @param string $u_action Custom form action -*/ -function confirm_box($check, $title = '', $hidden = '', $html_body = 'confirm_body.html', $u_action = '') -{ - if (phpbb_request::is_set_post('cancel')) - { - return false; - } - - $confirm = false; - if (phpbb_request::is_set_post('confirm')) - { - // language frontier - if (request_var('confirm', '') === phpbb::$user->lang['YES']) - { - $confirm = true; - } - } - - if ($check && $confirm) - { - $user_id = request_var('user_id', 0); - $session_id = request_var('sess', ''); - $confirm_key = request_var('confirm_key', ''); - - if ($user_id != phpbb::$user->data['user_id'] || $session_id != phpbb::$user->session_id || !$confirm_key || !phpbb::$user->data['user_last_confirm_key'] || $confirm_key != phpbb::$user->data['user_last_confirm_key']) - { - return false; - } - - // Reset user_last_confirm_key - $sql = 'UPDATE ' . USERS_TABLE . " SET user_last_confirm_key = '' - WHERE user_id = " . phpbb::$user->data['user_id']; - phpbb::$db->sql_query($sql); - - return true; - } - else if ($check) - { - return false; - } - - $s_hidden_fields = build_hidden_fields(array( - 'user_id' => phpbb::$user->data['user_id'], - 'sess' => phpbb::$user->session_id, - 'sid' => phpbb::$user->session_id, - )); - - // generate activation key - $confirm_key = gen_rand_string(10); - - page_header((!isset(phpbb::$user->lang[$title])) ? phpbb::$user->lang['CONFIRM'] : phpbb::$user->lang[$title]); - - phpbb::$template->set_filenames(array( - 'body' => $html_body, - )); - - // If activation key already exist, we better do not re-use the key (something very strange is going on...) - if (request_var('confirm_key', '')) - { - // This should not occur, therefore we cancel the operation to safe the user - return false; - } - - // re-add sid / transform & to & for user->page (user->page is always using &) - $use_page = ($u_action) ? PHPBB_ROOT_PATH . $u_action : PHPBB_ROOT_PATH . str_replace('&', '&', phpbb::$user->page['page']); - $u_action = reapply_sid($use_page); - $u_action .= ((strpos($u_action, '?') === false) ? '?' : '&') . 'confirm_key=' . $confirm_key; - - phpbb::$template->assign_vars(array( - 'MESSAGE_TITLE' => (!isset(phpbb::$user->lang[$title])) ? phpbb::$user->lang['CONFIRM'] : phpbb::$user->lang[$title], - 'MESSAGE_TEXT' => (!isset(phpbb::$user->lang[$title . '_CONFIRM'])) ? $title : phpbb::$user->lang[$title . '_CONFIRM'], - - 'YES_VALUE' => phpbb::$user->lang['YES'], - 'S_CONFIRM_ACTION' => $u_action, - 'S_HIDDEN_FIELDS' => $hidden . $s_hidden_fields, - )); - - $sql = 'UPDATE ' . USERS_TABLE . " SET user_last_confirm_key = '" . phpbb::$db->sql_escape($confirm_key) . "' - WHERE user_id = " . phpbb::$user->data['user_id']; - phpbb::$db->sql_query($sql); - - page_footer(); -} - -/** -* Generate login box or verify password -*/ -function login_box($redirect = '', $l_explain = '', $l_success = '', $admin = false, $s_display = true) -{ - $err = ''; - - // Make sure user->setup() has been called - if (empty(phpbb::$user->lang)) - { - phpbb::$user->setup(); - } - - // Print out error if user tries to authenticate as an administrator without having the privileges... - if ($admin && !phpbb::$acl->acl_get('a_')) - { - // Not authd - // anonymous/inactive users are never able to go to the ACP even if they have the relevant permissions - if (phpbb::$user->is_registered) - { - add_log('admin', 'LOG_ADMIN_AUTH_FAIL'); - } - - $admin = false; - } - - if (phpbb_request::is_set_post('login')) - { - // Get credential - if ($admin) - { - $credential = request_var('credential', ''); - - if (strspn($credential, 'abcdef0123456789') !== strlen($credential) || strlen($credential) != 32) - { - if (phpbb::$user->is_registered) - { - add_log('admin', 'LOG_ADMIN_AUTH_FAIL'); - } - - trigger_error('NO_AUTH_ADMIN'); - } - - $password = request_var('password_' . $credential, '', true); - } - else - { - $password = request_var('password', '', true); - } - - $username = request_var('username', '', true); - $autologin = phpbb_request::variable('autologin', false, false, phpbb_request::POST); - $viewonline = (phpbb_request::variable('viewonline', false, false, phpbb_request::POST)) ? 0 : 1; - $admin = ($admin) ? 1 : 0; - $viewonline = ($admin) ? phpbb::$user->data['session_viewonline'] : $viewonline; - - // Check if the supplied username is equal to the one stored within the database if re-authenticating - if ($admin && utf8_clean_string($username) != utf8_clean_string(phpbb::$user->data['username'])) - { - // We log the attempt to use a different username... - add_log('admin', 'LOG_ADMIN_AUTH_FAIL'); - trigger_error('NO_AUTH_ADMIN_USER_DIFFER'); - } - - // If authentication is successful we redirect user to previous page - $result = phpbb::$user->login($username, $password, $autologin, $viewonline, $admin); - - // If admin authentication and login, we will log if it was a success or not... - // We also break the operation on the first non-success login - it could be argued that the user already knows - if ($admin) - { - if ($result['status'] == LOGIN_SUCCESS) - { - add_log('admin', 'LOG_ADMIN_AUTH_SUCCESS'); - } - else - { - // Only log the failed attempt if a real user tried to. - // anonymous/inactive users are never able to go to the ACP even if they have the relevant permissions - if (phpbb::$user->is_registered) - { - add_log('admin', 'LOG_ADMIN_AUTH_FAIL'); - } - } - } - - // The result parameter is always an array, holding the relevant information... - if ($result['status'] == LOGIN_SUCCESS) - { - $redirect = request_var('redirect', phpbb::$user->page['page']); - - $message = ($l_success) ? $l_success : phpbb::$user->lang['LOGIN_REDIRECT']; - $l_redirect = ($admin) ? phpbb::$user->lang['PROCEED_TO_ACP'] : (($redirect === PHPBB_ROOT_PATH . 'index.' . PHP_EXT || $redirect === 'index.' . PHP_EXT) ? phpbb::$user->lang['RETURN_INDEX'] : phpbb::$user->lang['RETURN_PAGE']); - - // append/replace SID (may change during the session for AOL users) - $redirect = phpbb::$url->reapply_sid($redirect); - - // Special case... the user is effectively banned, but we allow founders to login - if (defined('IN_CHECK_BAN') && $result['user_row']['user_type'] != phpbb::USER_FOUNDER) - { - return; - } - - // $redirect = phpbb::$url->meta_refresh(3, $redirect); - trigger_error($message . '<br /><br />' . sprintf($l_redirect, '<a href="' . $redirect . '">', '</a>')); - } - - // Something failed, determine what... - if ($result['status'] == LOGIN_BREAK) - { - trigger_error($result['error_msg']); - } - - // Special cases... determine - switch ($result['status']) - { - case LOGIN_ERROR_ATTEMPTS: - - $captcha = phpbb_captcha_factory::get_instance(phpbb::$config['captcha_plugin']); - $captcha->init(CONFIRM_LOGIN); - $captcha->reset(); - - phpbb::$template->assign_vars(array( - 'S_CONFIRM_CODE' => true, - 'CONFIRM' => $captcha->get_template(''), - )); - - $err = phpbb::$user->lang[$result['error_msg']]; - - break; - - case LOGIN_ERROR_PASSWORD_CONVERT: - $err = sprintf( - phpbb::$user->lang[$result['error_msg']], - (phpbb::$config['email_enable']) ? '<a href="' . append_sid('ucp', 'mode=sendpassword') . '">' : '', - (phpbb::$config['email_enable']) ? '</a>' : '', - (phpbb::$config['board_contact']) ? '<a href="mailto:' . utf8_htmlspecialchars(phpbb::$config['board_contact']) . '">' : '', - (phpbb::$config['board_contact']) ? '</a>' : '' - ); - break; - - // Username, password, etc... - default: - $err = phpbb::$user->lang[$result['error_msg']]; - - // Assign admin contact to some error messages - if ($result['error_msg'] == 'LOGIN_ERROR_USERNAME' || $result['error_msg'] == 'LOGIN_ERROR_PASSWORD') - { - $err = (!phpbb::$config['board_contact']) ? sprintf(phpbb::$user->lang[$result['error_msg']], '', '') : sprintf(phpbb::$user->lang[$result['error_msg']], '<a href="mailto:' . utf8_htmlspecialchars(phpbb::$config['board_contact']) . '">', '</a>'); - } - - break; - } - } - - if (!$redirect) - { - // We just use what the session code determined... - // If we are not within the admin directory we use the page dir... - $redirect = ''; - - if (!$admin && !defined('ADMIN_START')) - { - $redirect .= (phpbb::$user->page['page_dir']) ? phpbb::$user->page['page_dir'] . '/' : ''; - } - - $redirect .= phpbb::$user->page['page_name'] . ((phpbb::$user->page['query_string']) ? '?' . utf8_htmlspecialchars(phpbb::$user->page['query_string']) : ''); - } - - // Assign credential for username/password pair - $credential = ($admin) ? md5(phpbb::$security->unique_id()) : false; - - $s_hidden_fields = array( - 'redirect' => $redirect, - 'sid' => phpbb::$user->session_id, - ); - - if ($admin) - { - $s_hidden_fields['credential'] = $credential; - } - - $s_hidden_fields = build_hidden_fields($s_hidden_fields); - - phpbb::$template->assign_vars(array( - 'LOGIN_ERROR' => $err, - 'LOGIN_EXPLAIN' => $l_explain, - - 'U_SEND_PASSWORD' => (phpbb::$config['email_enable']) ? phpbb::$url->append_sid('ucp', 'mode=sendpassword') : '', - 'U_RESEND_ACTIVATION' => (phpbb::$config['require_activation'] != USER_ACTIVATION_NONE && phpbb::$config['email_enable']) ? phpbb::$url->append_sid('ucp', 'mode=resend_act') : '', - 'U_TERMS_USE' => phpbb::$url->append_sid('ucp', 'mode=terms'), - 'U_PRIVACY' => phpbb::$url->append_sid('ucp', 'mode=privacy'), - - 'S_DISPLAY_FULL_LOGIN' => ($s_display) ? true : false, - 'S_LOGIN_ACTION' => (!$admin && !defined('ADMIN_START')) ? phpbb::$url->append_sid('ucp', 'mode=login') : phpbb::$url->append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, false, true, phpbb::$user->session_id), - 'S_HIDDEN_FIELDS' => $s_hidden_fields, - - 'S_ADMIN_AUTH' => $admin, - 'S_ACP_LOGIN' => defined('ADMIN_START'), - 'USERNAME' => ($admin) ? phpbb::$user->data['username'] : '', - - 'USERNAME_CREDENTIAL' => 'username', - 'PASSWORD_CREDENTIAL' => ($admin) ? 'password_' . $credential : 'password', - )); - - phpbb::$template->set_filenames(array( - 'body' => 'login_body.html', - )); - - page_header(phpbb::$user->lang['LOGIN'], false); - make_jumpbox('viewforum'); - - page_footer(); -} - -/** -* Generate forum login box -*/ -function login_forum_box($forum_data) -{ - $password = request_var('password', '', true); - - $sql = 'SELECT forum_id - FROM ' . FORUMS_ACCESS_TABLE . ' - WHERE forum_id = ' . $forum_data['forum_id'] . ' - AND user_id = ' . phpbb::$user->data['user_id'] . " - AND session_id = '" . phpbb::$db->sql_escape(phpbb::$user->session_id) . "'"; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ($row) - { - return true; - } - - if ($password) - { - // Remove expired authorised sessions - $sql = 'SELECT f.session_id - FROM ' . FORUMS_ACCESS_TABLE . ' f - LEFT JOIN ' . SESSIONS_TABLE . ' s ON (f.session_id = s.session_id) - WHERE s.session_id IS NULL'; - $result = phpbb::$db->sql_query($sql); - - if ($row = phpbb::$db->sql_fetchrow($result)) - { - $sql_in = array(); - do - { - $sql_in[] = (string) $row['session_id']; - } - while ($row = phpbb::$db->sql_fetchrow($result)); - - // Remove expired sessions - $sql = 'DELETE FROM ' . FORUMS_ACCESS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('session_id', $sql_in); - phpbb::$db->sql_query($sql); - } - phpbb::$db->sql_freeresult($result); - - if (phpbb_check_hash($password, $forum_data['forum_password'])) - { - $sql_ary = array( - 'forum_id' => (int) $forum_data['forum_id'], - 'user_id' => (int) phpbb::$user->data['user_id'], - 'session_id' => (string) phpbb::$user->session_id, - ); - - phpbb::$db->sql_query('INSERT INTO ' . FORUMS_ACCESS_TABLE . ' ' . phpbb::$db->sql_build_array('INSERT', $sql_ary)); - - return true; - } - - phpbb::$template->assign_var('LOGIN_ERROR', phpbb::$user->lang['WRONG_PASSWORD']); - } - - page_header(phpbb::$user->lang['LOGIN']); - - phpbb::$template->assign_vars(array( - 'S_HIDDEN_FIELDS' => build_hidden_fields(array('f' => $forum_data['forum_id'])), - )); - - phpbb::$template->set_filenames(array( - 'body' => 'login_forum.html', - )); - - page_footer(); -} - -// Little helpers - -/** -* Little helper for the build_hidden_fields function -* @todo helper class or form builder ;) -*/ -function _build_hidden_fields($key, $value, $specialchar, $stripslashes) -{ - $hidden_fields = ''; - - if (!is_array($value)) - { - $value = ($stripslashes) ? stripslashes($value) : $value; - $value = ($specialchar) ? utf8_htmlspecialchars($value) : $value; - - $hidden_fields .= '<input type="hidden" name="' . $key . '" value="' . $value . '" />' . "\n"; - } - else - { - foreach ($value as $_key => $_value) - { - $_key = ($stripslashes) ? stripslashes($_key) : $_key; - $_key = ($specialchar) ? utf8_htmlspecialchars($_key) : $_key; - - $hidden_fields .= _build_hidden_fields($key . '[' . $_key . ']', $_value, $specialchar, $stripslashes); - } - } - - return $hidden_fields; -} - -/** -* Build simple hidden fields from array -* -* @param array $field_ary an array of values to build the hidden field from -* @param bool $specialchar if true, keys and values get specialchared -* @param bool $stripslashes if true, keys and values get stripslashed -* -* @return string the hidden fields -* @todo helper class or form builder? -*/ -function build_hidden_fields($field_ary, $specialchar = false, $stripslashes = false) -{ - $s_hidden_fields = ''; - - foreach ($field_ary as $name => $vars) - { - $name = ($stripslashes) ? stripslashes($name) : $name; - $name = ($specialchar) ? utf8_htmlspecialchars($name) : $name; - - $s_hidden_fields .= _build_hidden_fields($name, $vars, $specialchar, $stripslashes); - } - - return $s_hidden_fields; -} - -/** -* Parse cfg file -*/ -function parse_cfg_file($filename, $lines = false) -{ - $parsed_items = array(); - - if ($lines === false) - { - $lines = file($filename); - } - - foreach ($lines as $line) - { - $line = trim($line); - - if (!$line || $line[0] == '#' || ($delim_pos = strpos($line, '=')) === false) - { - continue; - } - - // Determine first occurrence, since in values the equal sign is allowed - $key = strtolower(trim(substr($line, 0, $delim_pos))); - $value = trim(substr($line, $delim_pos + 1)); - - if (in_array($value, array('off', 'false', '0'))) - { - $value = false; - } - else if (in_array($value, array('on', 'true', '1'))) - { - $value = true; - } - else if (!trim($value)) - { - $value = ''; - } - else if (($value[0] == "'" && $value[sizeof($value) - 1] == "'") || ($value[0] == '"' && $value[sizeof($value) - 1] == '"')) - { - $value = substr($value, 1, sizeof($value)-2); - } - - $parsed_items[$key] = $value; - } - - return $parsed_items; -} - -/** -* Add log event -* @todo phpbb::$log -*/ -function add_log() -{ - $args = func_get_args(); - - $mode = array_shift($args); - $reportee_id = ($mode == 'user') ? intval(array_shift($args)) : ''; - $forum_id = ($mode == 'mod') ? intval(array_shift($args)) : ''; - $topic_id = ($mode == 'mod') ? intval(array_shift($args)) : ''; - $action = array_shift($args); - $data = (!sizeof($args)) ? '' : serialize($args); - - $sql_ary = array( - 'user_id' => (empty(phpbb::$user->data)) ? ANONYMOUS : phpbb::$user->data['user_id'], - 'log_ip' => phpbb::$user->ip, - 'log_time' => time(), - 'log_operation' => $action, - 'log_data' => $data, - ); - - switch ($mode) - { - case 'admin': - $sql_ary['log_type'] = LOG_ADMIN; - break; - - case 'mod': - $sql_ary += array( - 'log_type' => LOG_MOD, - 'forum_id' => $forum_id, - 'topic_id' => $topic_id - ); - break; - - case 'user': - $sql_ary += array( - 'log_type' => LOG_USERS, - 'reportee_id' => $reportee_id - ); - break; - - case 'critical': - $sql_ary['log_type'] = LOG_CRITICAL; - break; - - default: - return false; - } - - phpbb::$db->sql_query('INSERT INTO ' . LOG_TABLE . ' ' . phpbb::$db->sql_build_array('INSERT', $sql_ary)); - - return phpbb::$db->sql_nextid(); -} - -/** -* Return a nicely formatted backtrace (parts from the php manual by diz at ysagoon dot com) -* @todo helper? -*/ -function get_backtrace() -{ - $output = '<div style="font-family: monospace;">'; - $backtrace = debug_backtrace(); - $path = phpbb::$url->realpath(PHPBB_ROOT_PATH); - - foreach ($backtrace as $number => $trace) - { - // We skip the first one, because it only shows this file/function - if ($number == 0) - { - continue; - } - - if (empty($trace['file']) && empty($trace['line'])) - { - continue; - } - - // Strip the current directory from path - if (empty($trace['file'])) - { - $trace['file'] = ''; - } - else - { - $trace['file'] = str_replace(array($path, '\\'), array('', '/'), $trace['file']); - $trace['file'] = substr($trace['file'], 1); - } - $args = array(); - - // If include/require/include_once is not called, do not show arguments - they may contain sensible information - if (!in_array($trace['function'], array('include', 'require', 'include_once'))) - { - unset($trace['args']); - } - else - { - // Path... - if (!empty($trace['args'][0])) - { - $argument = htmlspecialchars($trace['args'][0]); - $argument = str_replace(array($path, '\\'), array('', '/'), $argument); - $argument = substr($argument, 1); - $args[] = "'{$argument}'"; - } - } - - $trace['class'] = (!isset($trace['class'])) ? '' : $trace['class']; - $trace['type'] = (!isset($trace['type'])) ? '' : $trace['type']; - - $output .= '<br />'; - $output .= '<b>FILE:</b> ' . htmlspecialchars($trace['file']) . '<br />'; - $output .= '<b>LINE:</b> ' . ((!empty($trace['line'])) ? $trace['line'] : '') . '<br />'; - - $output .= '<b>CALL:</b> ' . htmlspecialchars($trace['class'] . $trace['type'] . $trace['function']) . '(' . ((sizeof($args)) ? implode(', ', $args) : '') . ')<br />'; - } - $output .= '</div>'; - return $output; -} - -/** -* This function returns a regular expression pattern for commonly used expressions -* Use with / as delimiter for email mode and # for url modes -* mode can be: email|bbcode_htm|url|url_inline|www_url|www_url_inline|relative_url|relative_url_inline|ipv4|ipv6 -* @todo helper? -*/ -function get_preg_expression($mode) -{ - switch ($mode) - { - case 'email': - return '(?:[a-z0-9\'\.\-_\+\|]++|&)+@[a-z0-9\-]+\.(?:[a-z0-9\-]+\.)*[a-z]+'; - break; - - case 'bbcode_htm': - return array( - '#<!\-\- e \-\-><a href="mailto:(.*?)">.*?</a><!\-\- e \-\->#', - '#<!\-\- l \-\-><a (?:class="[\w-]+" )?href="(.*?)(?:(&|\?)sid=[0-9a-f]{32})?">.*?</a><!\-\- l \-\->#', - '#<!\-\- ([mw]) \-\-><a (?:class="[\w-]+" )?href="(.*?)">.*?</a><!\-\- \1 \-\->#', - '#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/.*? \/><!\-\- s\1 \-\->#', - '#<!\-\- .*? \-\->#s', - '#<.*?>#s', - ); - break; - - // Whoa these look impressive! - // The code to generate the following two regular expressions which match valid IPv4/IPv6 addresses - // can be found in the develop directory - case 'ipv4': - return '#^(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$#'; - break; - - case 'ipv6': - return '#^(?:(?:(?:[\dA-F]{1,4}:){6}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:::(?:[\dA-F]{1,4}:){5}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:):(?:[\dA-F]{1,4}:){4}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,2}:(?:[\dA-F]{1,4}:){3}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,3}:(?:[\dA-F]{1,4}:){2}(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,4}:(?:[\dA-F]{1,4}:)(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,5}:(?:[\dA-F]{1,4}:[\dA-F]{1,4}|(?:(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.){3}(?:\d{1,2}|1\d\d|2[0-4]\d|25[0-5])))|(?:(?:[\dA-F]{1,4}:){1,6}:[\dA-F]{1,4})|(?:(?:[\dA-F]{1,4}:){1,7}:))$#i'; - break; - - case 'url': - case 'url_inline': - $inline = ($mode == 'url') ? ')' : ''; - $scheme = ($mode == 'url') ? '[a-z\d+\-.]' : '[a-z\d+]'; // avoid automatic parsing of "word" in "last word.http://..." - // generated with regex generation file in the develop folder - return "[a-z]$scheme*:/{2}(?:(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})+|[0-9.]+|\[[a-z0-9.]+:[a-z0-9.]+:[a-z0-9.:]+\])(?::\d*)?(?:/(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?"; - break; - - case 'www_url': - case 'www_url_inline': - $inline = ($mode == 'www_url') ? ')' : ''; - return "www\.(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})+(?::\d*)?(?:/(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?"; - break; - - case 'relative_url': - case 'relative_url_inline': - $inline = ($mode == 'relative_url') ? ')' : ''; - return "(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})*(?:/(?:[a-z0-9\-._~!$&'($inline*+,;=:@|]+|%[\dA-F]{2})*)*(?:\?(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?(?:\#(?:[a-z0-9\-._~!$&'($inline*+,;=:@/?|]+|%[\dA-F]{2})*)?"; - break; - } - - return ''; -} - -/** -* Returns the first block of the specified IPv6 address and as many additional -* ones as specified in the length paramater. -* If length is zero, then an empty string is returned. -* If length is greater than 3 the complete IP will be returned -* @todo helper? -*/ -function short_ipv6($ip, $length) -{ - if ($length < 1) - { - return ''; - } - - // extend IPv6 addresses - $blocks = substr_count($ip, ':') + 1; - if ($blocks < 9) - { - $ip = str_replace('::', ':' . str_repeat('0000:', 9 - $blocks), $ip); - } - if ($ip[0] == ':') - { - $ip = '0000' . $ip; - } - if ($length < 4) - { - $ip = implode(':', array_slice(explode(':', $ip), 0, 1 + $length)); - } - - return $ip; -} - -/** -* Wrapper for php's checkdnsrr function. -* -* The windows failover is from the php manual -* Please make sure to check the return value for === true and === false, since NULL could -* be returned too. -* -* @return true if entry found, false if not, NULL if this function is not supported by this environment -*/ -function phpbb_checkdnsrr($host, $type = '') -{ - $type = (!$type) ? 'MX' : $type; - - if (DIRECTORY_SEPARATOR == '\\') - { - if (!function_exists('exec')) - { - return NULL; - } - - // @exec('nslookup -retry=1 -timout=1 -type=' . escapeshellarg($type) . ' ' . escapeshellarg($host), $output); - @exec('nslookup -type=' . escapeshellarg($type) . ' ' . escapeshellarg($host) . '.', $output); - - // If output is empty, the nslookup failed - if (empty($output)) - { - return NULL; - } - - foreach ($output as $line) - { - if (!trim($line)) - { - continue; - } - - // Valid records begin with host name: - if (strpos($line, $host) === 0) - { - return true; - } - } - - return false; - } - else if (function_exists('checkdnsrr')) - { - // The dot indicates to search the DNS root (helps those having DNS prefixes on the same domain) - return (checkdnsrr($host . '.', $type)) ? true : false; - } - - return NULL; -} - -// Handler, header and footer - -/** -* Error and message handler, call with trigger_error if reqd -*/ -function msg_handler($errno, $msg_text, $errfile, $errline) -{ - global $msg_title, $msg_long_text; - - // Message handler is stripping text. In case we need it, we are able to define long text... - if (isset($msg_long_text) && $msg_long_text && !$msg_text) - { - $msg_text = $msg_long_text; - } - - // Store information for later use - phpbb::$last_notice = array( - 'file' => $errfile, - 'line' => $errline, - 'message' => $msg_text, - 'php_error' => (!empty($php_errormsg)) ? $php_errormsg : '', - 'errno' => $errno, - ); - - // Do not display notices if we suppress them via @ - if (error_reporting() == 0) - { - return; - } - - switch ($errno) - { - case E_NOTICE: - case E_WARNING: - case E_STRICT: - - // Check the error reporting level and return if the error level does not match - // If DEBUG is defined the default level is E_ALL - if (($errno & ((phpbb::$base_config['debug']) ? E_ALL | E_STRICT : error_reporting())) == 0) - { - return; - } - -// if (strpos($errfile, 'cache') === false && strpos($errfile, 'template.') === false) -// { - // flush the content, else we get a white page if output buffering is on - if ((int) @ini_get('output_buffering') === 1 || strtolower(@ini_get('output_buffering')) === 'on') - { - @ob_flush(); - } - - // Another quick fix for those having gzip compression enabled, but do not flush if the coder wants to catch "something". ;) - if (!empty(phpbb::$config['gzip_compress'])) - { - if (@extension_loaded('zlib') && !headers_sent() && !ob_get_level()) - { - @ob_flush(); - } - } - - // remove complete path to installation, with the risk of changing backslashes meant to be there - if (phpbb::registered('url')) - { - $errfile = str_replace(array(phpbb::$url->realpath(PHPBB_ROOT_PATH), '\\'), array('', '/'), $errfile); - $msg_text = str_replace(array(phpbb::$url->realpath(PHPBB_ROOT_PATH), '\\'), array('', '/'), $msg_text); - } - - echo '<b>[phpBB Debug] PHP Notice</b>: in file <b>' . $errfile . '</b> on line <b>' . $errline . '</b>: <b>' . $msg_text . '</b><br />' . "\n"; -// } - - return; - - break; - - case E_RECOVERABLE_ERROR: - case E_USER_ERROR: - - if (phpbb::registered('user')) - { - // Setup language - if (empty(phpbb::$user->lang)) - { - phpbb::$user->setup(); - } - - $msg_text = (!empty(phpbb::$user->lang[$msg_text])) ? phpbb::$user->lang[$msg_text] : $msg_text; - $msg_title = (!isset($msg_title)) ? phpbb::$user->lang['GENERAL_ERROR'] : ((!empty(phpbb::$user->lang[$msg_title])) ? phpbb::$user->lang[$msg_title] : $msg_title); - - $l_return_index = phpbb::$user->lang('RETURN_INDEX', '<a href="' . PHPBB_ROOT_PATH . '">', '</a>'); - $l_notify = ''; - - if (!empty(phpbb::$config['board_contact'])) - { - $l_notify = '<p>' . phpbb::$user->lang('NOTIFY_ADMIN_EMAIL', phpbb::$config['board_contact']) . '</p>'; - } - } - else - { - $msg_title = 'General Error'; - $l_return_index = '<a href="' . PHPBB_ROOT_PATH . '">Return to index page</a>'; - $l_notify = ''; - - if (!empty(phpbb::$config['board_contact'])) - { - $l_notify = '<p>Please notify the board administrator or webmaster: <a href="mailto:' . phpbb::$config['board_contact'] . '">' . phpbb::$config['board_contact'] . '</a></p>'; - } - } - - garbage_collection(); - - // Try to not call the adm page data... - // @todo put into failover template file - - echo '<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">'; - echo '<html xmlns="http://www.w3.org/1999/xhtml" dir="ltr">'; - echo '<head>'; - echo '<meta http-equiv="content-type" content="text/html; charset=utf-8" />'; - echo '<title>' . $msg_title . '</title>'; - echo '<style type="text/css">' . "\n" . '/* <![CDATA[ */' . "\n"; - echo '* { margin: 0; padding: 0; } html { font-size: 100%; height: 100%; margin-bottom: 1px; background-color: #E4EDF0; } body { font-family: "Lucida Grande", Verdana, Helvetica, Arial, sans-serif; color: #536482; background: #E4EDF0; font-size: 62.5%; margin: 0; } '; - echo 'a:link, a:active, a:visited { color: #006699; text-decoration: none; } a:hover { color: #DD6900; text-decoration: underline; } '; - echo '#wrap { padding: 0 20px 15px 20px; min-width: 615px; } #page-header { text-align: right; height: 40px; } #page-footer { clear: both; font-size: 1em; text-align: center; } '; - echo '.panel { margin: 4px 0; background-color: #FFFFFF; border: solid 1px #A9B8C2; } '; - echo '#errorpage #page-header a { font-weight: bold; line-height: 6em; } #errorpage #content { padding: 10px; } #errorpage #content h1 { line-height: 1.2em; margin-bottom: 0; color: #DF075C; } '; - echo '#errorpage #content div { margin-top: 20px; margin-bottom: 5px; border-bottom: 1px solid #CCCCCC; padding-bottom: 5px; color: #333333; font: bold 1.2em "Lucida Grande", Arial, Helvetica, sans-serif; text-decoration: none; line-height: 120%; text-align: left; } '; - echo "\n" . '/* ]]> */' . "\n"; - echo '</style>'; - echo '</head>'; - echo '<body id="errorpage">'; - echo '<div id="wrap">'; - echo ' <div id="page-header">'; - echo ' ' . $l_return_index; - echo ' </div>'; - echo ' <div id="acp">'; - echo ' <div class="panel">'; - echo ' <div id="content">'; - echo ' <h1>' . $msg_title . '</h1>'; - - echo ' <div>' . $msg_text; - - if ((phpbb::registered('acl') && phpbb::$acl->acl_get('a_')) || defined('IN_INSTALL') || phpbb::$base_config['debug_extra']) - { - echo ($backtrace = get_backtrace()) ? '<br /><br />BACKTRACE' . $backtrace : ''; - } - echo '</div>'; - - echo $l_notify; - - echo ' </div>'; - echo ' </div>'; - echo ' </div>'; - echo ' <div id="page-footer">'; - echo ' Powered by phpBB © 2000, 2002, 2005, 2007 <a href="http://www.phpbb.com/">phpBB Group</a>'; - echo ' </div>'; - echo '</div>'; - echo '</body>'; - echo '</html>'; - - exit_handler(); - - // On a fatal error (and E_USER_ERROR *is* fatal) we never want other scripts to continue and force an exit here. - exit; - break; - - case E_USER_WARNING: - case E_USER_NOTICE: - - define('IN_ERROR_HANDLER', true); - - if (empty(phpbb::$user->data)) - { - phpbb::$user->session_begin(); - } - - // We re-init the auth array to get correct results on login/logout - phpbb::$acl->init(phpbb::$user->data); - - if (empty(phpbb::$user->lang)) - { - phpbb::$user->setup(); - } - - $msg_text = (!empty(phpbb::$user->lang[$msg_text])) ? phpbb::$user->lang[$msg_text] : $msg_text; - $msg_title = (!isset($msg_title)) ? phpbb::$user->lang['INFORMATION'] : ((!empty(phpbb::$user->lang[$msg_title])) ? phpbb::$user->lang[$msg_title] : $msg_title); - - if (!defined('HEADER_INC')) - { - page_header($msg_title); - } - - phpbb::$template->set_filenames(array( - 'body' => 'message_body.html') - ); - - phpbb::$template->assign_vars(array( - 'MESSAGE_TITLE' => $msg_title, - 'MESSAGE_TEXT' => $msg_text, - 'S_USER_WARNING' => ($errno == E_USER_WARNING) ? true : false, - 'S_USER_NOTICE' => ($errno == E_USER_NOTICE) ? true : false) - ); - - // We do not want the cron script to be called on error messages - define('IN_CRON', true); - - page_footer(); - - exit_handler(); - break; - } - - // If we notice an error not handled here we pass this back to PHP by returning false - // This may not work for all php versions - return false; -} - -/** -* Generate page header -* @plugin-support override, default, return -*/ -function page_header($page_title = '', $display_online_list = true) -{ - if (phpbb::$plugins->function_override(__FUNCTION__)) return phpbb::$plugins->call_override(__FUNCTION__, $page_title, $display_online_list); - - if (defined('HEADER_INC')) - { - return; - } - - define('HEADER_INC', true); - - // gzip_compression - if (phpbb::$config['gzip_compress']) - { - if (@extension_loaded('zlib') && !headers_sent()) - { - ob_start('ob_gzhandler'); - } - } - - if (phpbb::$plugins->function_inject(__FUNCTION__)) phpbb::$plugins->call_inject(__FUNCTION__, array('default', &$page_title, &$display_online_list)); - - // Generate logged in/logged out status - if (!phpbb::$user->is_guest) - { - $u_login_logout = phpbb::$url->append_sid('ucp', 'mode=logout', true, phpbb::$user->session_id); - $l_login_logout = sprintf(phpbb::$user->lang['LOGOUT_USER'], phpbb::$user->data['username']); - } - else - { - $u_login_logout = phpbb::$url->append_sid('ucp', 'mode=login'); - $l_login_logout = phpbb::$user->lang['LOGIN']; - } - - // Last visit date/time - $s_last_visit = (!phpbb::$user->is_guest) ? phpbb::$user->format_date(phpbb::$user->data['session_last_visit']) : ''; - - // Get users online list ... if required - $online_userlist = array(); - $l_online_users = $l_online_record = ''; - $forum = request_var('f', 0); - - if (phpbb::$config['load_online'] && phpbb::$config['load_online_time'] && $display_online_list) - { - $logged_visible_online = $logged_hidden_online = $guests_online = $prev_user_id = 0; - $prev_session_ip = $reading_sql = ''; - - if ($forum) - { - $reading_sql = ' AND s.session_forum_id = ' . $forum; - } - - // Get number of online guests - if (!phpbb::$config['load_online_guests']) - { - if (phpbb::$db->features['count_distinct']) - { - $sql = 'SELECT COUNT(DISTINCT s.session_ip) as num_guests - FROM ' . SESSIONS_TABLE . ' s - WHERE s.session_user_id = ' . ANONYMOUS . ' - AND s.session_time >= ' . (time() - (phpbb::$config['load_online_time'] * 60)) . - $reading_sql; - } - else - { - $sql = 'SELECT COUNT(session_ip) as num_guests - FROM ( - SELECT DISTINCT s.session_ip - FROM ' . SESSIONS_TABLE . ' s - WHERE s.session_user_id = ' . ANONYMOUS . ' - AND s.session_time >= ' . (time() - (phpbb::$config['load_online_time'] * 60)) . - $reading_sql . - ')'; - } - $result = phpbb::$db->sql_query($sql); - $guests_online = (int) phpbb::$db->sql_fetchfield('num_guests'); - phpbb::$db->sql_freeresult($result); - } - - $sql = 'SELECT u.username, u.username_clean, u.user_id, u.user_type, u.user_allow_viewonline, u.user_colour, s.session_ip, s.session_viewonline - FROM ' . USERS_TABLE . ' u, ' . SESSIONS_TABLE . ' s - WHERE s.session_time >= ' . (time() - (intval(phpbb::$config['load_online_time']) * 60)) . - $reading_sql . - ((!phpbb::$config['load_online_guests']) ? ' AND s.session_user_id <> ' . ANONYMOUS : '') . ' - AND u.user_id = s.session_user_id - ORDER BY u.username_clean ASC, s.session_ip ASC'; - $result = phpbb::$db->sql_query($sql); - - $prev_user_id = false; - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - // User is logged in and therefore not a guest - if ($row['user_id'] != ANONYMOUS) - { - // Skip multiple sessions for one user - if ($row['user_id'] != $prev_user_id) - { - if ($row['session_viewonline']) - { - $logged_visible_online++; - } - else - { - $row['username'] = '<em>' . $row['username'] . '</em>'; - $logged_hidden_online++; - } - - if (($row['session_viewonline']) || phpbb::$acl->acl_get('u_viewonline')) - { - $user_online_link = get_username_string(($row['user_type'] <> phpbb::USER_IGNORE) ? 'full' : 'no_profile', $row['user_id'], $row['username'], $row['user_colour']); - $online_userlist[] = $user_online_link; - } - } - - $prev_user_id = $row['user_id']; - } - else - { - // Skip multiple sessions for one user - if ($row['session_ip'] != $prev_session_ip) - { - $guests_online++; - } - } - - $prev_session_ip = $row['session_ip']; - } - phpbb::$db->sql_freeresult($result); - - if (!sizeof($online_userlist)) - { - $online_userlist = phpbb::$user->lang['NO_ONLINE_USERS']; - } - else - { - $online_userlist = implode(', ', $online_userlist); - } - - if (!$forum) - { - $online_userlist = phpbb::$user->lang['REGISTERED_USERS'] . ' ' . $online_userlist; - } - else - { - $online_userlist = phpbb::$user->lang('BROWSING_FORUM_GUESTS', $online_userlist, $guests_online); - } - - $total_online_users = $logged_visible_online + $logged_hidden_online + $guests_online; - - if ($total_online_users > phpbb::$config['record_online_users']) - { - set_config('record_online_users', $total_online_users, true); - set_config('record_online_date', time(), true); - } - - $l_online_users = phpbb::$user->lang('ONLINE_USER_COUNT', $total_online_users); - $l_online_users .= phpbb::$user->lang('REG_USER_COUNT', $logged_visible_online); - $l_online_users .= phpbb::$user->lang('HIDDEN_USER_COUNT', $logged_hidden_online); - $l_online_users .= phpbb::$user->lang('GUEST_USER_COUNT', $guests_online); - - $l_online_record = phpbb::$user->lang('RECORD_ONLINE_USERS', phpbb::$config['record_online_users'], phpbb::$user->format_date(phpbb::$config['record_online_date'])); - $l_online_time = phpbb::$user->lang('VIEW_ONLINE_TIME', phpbb::$config['load_online_time']); - } - else - { - $l_online_time = ''; - } - - $l_privmsgs_text = $l_privmsgs_text_unread = ''; - $s_privmsg_new = false; - - // Obtain number of new private messages if user is logged in - if (!empty(phpbb::$user->is_registered)) - { - if (phpbb::$user->data['user_new_privmsg']) - { - $l_privmsgs_text = phpbb::$user->lang('NEW_PM', phpbb::$user->data['user_new_privmsg']); - - if (!phpbb::$user->data['user_last_privmsg'] || phpbb::$user->data['user_last_privmsg'] > phpbb::$user->data['session_last_visit']) - { - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_last_privmsg = ' . phpbb::$user->data['session_last_visit'] . ' - WHERE user_id = ' . phpbb::$user->data['user_id']; - phpbb::$db->sql_query($sql); - - $s_privmsg_new = true; - } - else - { - $s_privmsg_new = false; - } - } - else - { - $l_privmsgs_text = phpbb::$user->lang['NO_NEW_PM']; - $s_privmsg_new = false; - } - - $l_privmsgs_text_unread = ''; - - if (phpbb::$user->data['user_unread_privmsg'] && phpbb::$user->data['user_unread_privmsg'] != phpbb::$user->data['user_new_privmsg']) - { - $l_privmsgs_text_unread = phpbb::$user->lang('UNREAD_PM', phpbb::$user->data['user_unread_privmsg']); - } - } - - // Which timezone? - $tz = (!phpbb::$user->is_guest) ? strval(doubleval(phpbb::$user->data['user_timezone'])) : strval(doubleval(phpbb::$config['board_timezone'])); - - // Send a proper content-language to the output - $user_lang = phpbb::$user->lang['USER_LANG']; - if (strpos($user_lang, '-x-') !== false) - { - $user_lang = substr($user_lang, 0, strpos($user_lang, '-x-')); - } - - // The following assigns all _common_ variables that may be used at any point in a template. - phpbb::$template->assign_vars(array( - 'SITENAME' => phpbb::$config['sitename'], - 'SITE_DESCRIPTION' => phpbb::$config['site_desc'], - 'PAGE_TITLE' => $page_title, - 'SCRIPT_NAME' => str_replace('.' . PHP_EXT, '', phpbb::$user->page['page_name']), - 'LAST_VISIT_DATE' => phpbb::$user->lang('YOU_LAST_VISIT', $s_last_visit), - 'LAST_VISIT_YOU' => $s_last_visit, - 'CURRENT_TIME' => phpbb::$user->lang('CURRENT_TIME', phpbb::$user->format_date(time(), false, true)), - 'TOTAL_USERS_ONLINE' => $l_online_users, - 'LOGGED_IN_USER_LIST' => $online_userlist, - 'RECORD_USERS' => $l_online_record, - 'PRIVATE_MESSAGE_INFO' => $l_privmsgs_text, - 'PRIVATE_MESSAGE_INFO_UNREAD' => $l_privmsgs_text_unread, - - 'S_USER_NEW_PRIVMSG' => phpbb::$user->data['user_new_privmsg'], - 'S_USER_UNREAD_PRIVMSG' => phpbb::$user->data['user_unread_privmsg'], - - 'SESSION_ID' => phpbb::$user->session_id, - 'ROOT_PATH' => PHPBB_ROOT_PATH, - - 'L_LOGIN_LOGOUT' => $l_login_logout, - 'L_INDEX' => phpbb::$user->lang['FORUM_INDEX'], - 'L_ONLINE_EXPLAIN' => $l_online_time, - - 'U_PRIVATEMSGS' => phpbb::$url->append_sid('ucp', 'i=pm&folder=inbox'), - 'U_RETURN_INBOX' => phpbb::$url->append_sid('ucp', 'i=pm&folder=inbox'), - 'U_POPUP_PM' => phpbb::$url->append_sid('ucp', 'i=pm&mode=popup'), - 'UA_POPUP_PM' => addslashes(phpbb::$url->append_sid('ucp', 'i=pm&mode=popup')), - 'U_MEMBERLIST' => phpbb::$url->append_sid('memberlist'), - 'U_VIEWONLINE' => (phpbb::$acl->acl_gets('u_viewprofile', 'a_user', 'a_useradd', 'a_userdel')) ? phpbb::$url->append_sid('viewonline') : '', - 'U_LOGIN_LOGOUT' => $u_login_logout, - 'U_INDEX' => phpbb::$url->append_sid('index'), - 'U_SEARCH' => phpbb::$url->append_sid('search'), - 'U_REGISTER' => phpbb::$url->append_sid('ucp', 'mode=register'), - 'U_PROFILE' => phpbb::$url->append_sid('ucp'), - 'U_MODCP' => phpbb::$url->append_sid('mcp', false, true, phpbb::$user->session_id), - 'U_FAQ' => phpbb::$url->append_sid('faq'), - 'U_SEARCH_SELF' => phpbb::$url->append_sid('search', 'search_id=egosearch'), - 'U_SEARCH_NEW' => phpbb::$url->append_sid('search', 'search_id=newposts'), - 'U_SEARCH_UNANSWERED' => phpbb::$url->append_sid('search', 'search_id=unanswered'), - 'U_SEARCH_ACTIVE_TOPICS'=> phpbb::$url->append_sid('search', 'search_id=active_topics'), - 'U_DELETE_COOKIES' => phpbb::$url->append_sid('ucp', 'mode=delete_cookies'), - 'U_TEAM' => (!phpbb::$user->is_guest && !phpbb::$acl->acl_get('u_viewprofile')) ? '' : phpbb::$url->append_sid('memberlist', 'mode=leaders'), - 'U_RESTORE_PERMISSIONS' => (phpbb::$user->data['user_perm_from'] && phpbb::$acl->acl_get('a_switchperm')) ? phpbb::$url->append_sid('ucp', 'mode=restore_perm') : '', - - 'S_USER_LOGGED_IN' => (!phpbb::$user->is_guest) ? true : false, - 'S_AUTOLOGIN_ENABLED' => (phpbb::$config['allow_autologin']) ? true : false, - 'S_BOARD_DISABLED' => (phpbb::$config['board_disable']) ? true : false, - 'S_REGISTERED_USER' => (!empty(phpbb::$user->is_registered)) ? true : false, - 'S_IS_BOT' => (!empty(phpbb::$user->is_bot)) ? true : false, - 'S_USER_PM_POPUP' => phpbb::$user->optionget('popuppm'), - 'S_USER_LANG' => $user_lang, - 'S_USER_BROWSER' => (isset(phpbb::$user->data['session_browser'])) ? phpbb::$user->data['session_browser'] : phpbb::$user->lang['UNKNOWN_BROWSER'], - 'S_USERNAME' => phpbb::$user->data['username'], - 'S_CONTENT_DIRECTION' => phpbb::$user->lang['DIRECTION'], - 'S_CONTENT_FLOW_BEGIN' => (phpbb::$user->lang['DIRECTION'] == 'ltr') ? 'left' : 'right', - 'S_CONTENT_FLOW_END' => (phpbb::$user->lang['DIRECTION'] == 'ltr') ? 'right' : 'left', - 'S_CONTENT_ENCODING' => 'UTF-8', - 'S_TIMEZONE' => (phpbb::$user->data['user_dst'] || (phpbb::$user->is_guest && phpbb::$config['board_dst'])) ? sprintf(phpbb::$user->lang['ALL_TIMES'], phpbb::$user->lang['tz'][$tz], phpbb::$user->lang['tz']['dst']) : sprintf(phpbb::$user->lang['ALL_TIMES'], phpbb::$user->lang['tz'][$tz], ''), - 'S_DISPLAY_ONLINE_LIST' => ($l_online_time) ? 1 : 0, - 'S_DISPLAY_SEARCH' => (!phpbb::$config['load_search']) ? 0 : (phpbb::$acl->acl_get('u_search') && phpbb::$acl->acl_getf_global('f_search')), - 'S_DISPLAY_PM' => (phpbb::$config['allow_privmsg'] && !empty(phpbb::$user->is_registered) && (phpbb::$acl->acl_get('u_readpm') || phpbb::$acl->acl_get('u_sendpm'))) ? true : false, - 'S_DISPLAY_MEMBERLIST' => (isset($auth)) ? phpbb::$acl->acl_get('u_viewprofile') : 0, - 'S_NEW_PM' => ($s_privmsg_new) ? 1 : 0, - 'S_REGISTER_ENABLED' => (phpbb::$config['require_activation'] != USER_ACTIVATION_DISABLE) ? true : false, - - 'T_THEME_PATH' => PHPBB_ROOT_PATH . 'styles/' . phpbb::$user->theme['theme_path'] . '/theme', - 'T_TEMPLATE_PATH' => PHPBB_ROOT_PATH . 'styles/' . phpbb::$user->theme['template_path'] . '/template', - 'T_IMAGESET_PATH' => PHPBB_ROOT_PATH . 'styles/' . phpbb::$user->theme['imageset_path'] . '/imageset', - 'T_IMAGESET_LANG_PATH' => PHPBB_ROOT_PATH . 'styles/' . phpbb::$user->theme['imageset_path'] . '/imageset/' . phpbb::$user->data['user_lang'], - 'T_IMAGES_PATH' => PHPBB_ROOT_PATH . 'images/', - 'T_SMILIES_PATH' => PHPBB_ROOT_PATH . phpbb::$config['smilies_path'] . '/', - 'T_AVATAR_PATH' => PHPBB_ROOT_PATH . phpbb::$config['avatar_path'] . '/', - 'T_AVATAR_GALLERY_PATH' => PHPBB_ROOT_PATH . phpbb::$config['avatar_gallery_path'] . '/', - 'T_ICONS_PATH' => PHPBB_ROOT_PATH . phpbb::$config['icons_path'] . '/', - 'T_RANKS_PATH' => PHPBB_ROOT_PATH . phpbb::$config['ranks_path'] . '/', - 'T_UPLOAD_PATH' => PHPBB_ROOT_PATH . phpbb::$config['upload_path'] . '/', - 'T_STYLESHEET_LINK' => (!phpbb::$user->theme['theme_storedb']) ? PHPBB_ROOT_PATH . 'styles/' . phpbb::$user->theme['theme_path'] . '/theme/stylesheet.css' : phpbb::$url->get(PHPBB_ROOT_PATH . 'style.' . PHP_EXT . '?id=' . phpbb::$user->theme['style_id'] . '&lang=' . phpbb::$user->data['user_lang']), //PHPBB_ROOT_PATH . "store/{phpbb::$user->theme['theme_id']}_{phpbb::$user->theme['imageset_id']}_{phpbb::$user->lang_name}.css" - 'T_STYLESHEET_NAME' => phpbb::$user->theme['theme_name'], - - 'SITE_LOGO_IMG' => phpbb::$user->img('site_logo'), - - 'A_COOKIE_SETTINGS' => addslashes('; path=' . phpbb::$config['cookie_path'] . ((!phpbb::$config['cookie_domain'] || phpbb::$config['cookie_domain'] == 'localhost' || phpbb::$config['cookie_domain'] == '127.0.0.1') ? '' : '; domain=' . phpbb::$config['cookie_domain']) . ((!phpbb::$config['cookie_secure']) ? '' : '; secure')), - )); - - // application/xhtml+xml not used because of IE - header('Content-type: text/html; charset=UTF-8'); - - header('Cache-Control: private, no-cache="set-cookie"'); - header('Expires: 0'); - header('Pragma: no-cache'); - - if (phpbb::$plugins->function_inject(__FUNCTION__, 'return')) return phpbb::$plugins->call_inject(__FUNCTION__, 'return'); -} - -/** -* Generate page footer -*/ -function page_footer($run_cron = true) -{ - global $starttime; - - // Output page creation time - if (phpbb::$base_config['debug']) - { - $mtime = explode(' ', microtime()); - $totaltime = $mtime[0] + $mtime[1] - $starttime; - - if (phpbb_request::variable('explain', false) && /*phpbb::$acl->acl_get('a_') &&*/ phpbb::$base_config['debug_extra'] && method_exists(phpbb::$db, 'sql_report')) - { - phpbb::$db->sql_report('display'); - } - - $debug_output = sprintf('Time : %.3fs | ' . phpbb::$db->sql_num_queries() . ' Queries | GZIP : ' . ((phpbb::$config['gzip_compress']) ? 'On' : 'Off') . ((phpbb::$user->system['load']) ? ' | Load : ' . phpbb::$user->system['load'] : ''), $totaltime); - - if (/*phpbb::$acl->acl_get('a_') &&*/ phpbb::$base_config['debug_extra']) - { - if (function_exists('memory_get_usage')) - { - if ($memory_usage = memory_get_usage()) - { - $memory_usage -= phpbb::$base_config['memory_usage']; - $memory_usage = get_formatted_filesize($memory_usage); - - $debug_output .= ' | Memory Usage: ' . $memory_usage; - } - } - - $debug_output .= ' | <a href="' . phpbb::$url->build_url() . '&explain=1">Explain</a>'; - } - } - - phpbb::$template->assign_vars(array( - 'DEBUG_OUTPUT' => (phpbb::$base_config['debug']) ? $debug_output : '', - 'TRANSLATION_INFO' => (!empty(phpbb::$user->lang['TRANSLATION_INFO'])) ? phpbb::$user->lang['TRANSLATION_INFO'] : '', - - 'U_ACP' => (phpbb::$acl->acl_get('a_') && !empty(phpbb::$user->is_registered)) ? phpbb::$url->append_sid(phpbb::$base_config['admin_folder'] . '/index', false, true, phpbb::$user->session_id) : '', - )); - - // Call cron-type script - if (!defined('IN_CRON') && $run_cron && !phpbb::$config['board_disable']) - { - $cron_type = ''; - - if (time() - phpbb::$config['queue_interval'] > phpbb::$config['last_queue_run'] && !defined('IN_ADMIN') && file_exists(PHPBB_ROOT_PATH . 'cache/queue.' . PHP_EXT)) - { - // Process email queue - $cron_type = 'queue'; - } - else if (method_exists(phpbb::$acm, 'tidy') && time() - phpbb::$config['cache_gc'] > phpbb::$config['cache_last_gc']) - { - // Tidy the cache - $cron_type = 'tidy_cache'; - } - else if (time() - phpbb::$config['warnings_gc'] > phpbb::$config['warnings_last_gc']) - { - $cron_type = 'tidy_warnings'; - } - else if (time() - phpbb::$config['database_gc'] > phpbb::$config['database_last_gc']) - { - // Tidy the database - $cron_type = 'tidy_database'; - } - else if (time() - phpbb::$config['search_gc'] > phpbb::$config['search_last_gc']) - { - // Tidy the search - $cron_type = 'tidy_search'; - } - else if (time() - phpbb::$config['session_gc'] > phpbb::$config['session_last_gc']) - { - $cron_type = 'tidy_sessions'; - } - - if ($cron_type) - { - phpbb::$template->assign_var('RUN_CRON_TASK', '<img src="' . phpbb::$url->append_sid('cron', 'cron_type=' . $cron_type) . '" width="1" height="1" alt="cron" />'); - } - } - - phpbb::$template->display('body'); - - garbage_collection(); - exit_handler(); -} - -/** -* Closing the cache object and the database -* Cool function name, eh? We might want to add operations to it later -*/ -function garbage_collection() -{ - // Unload cache, must be done before the DB connection if closed - if (phpbb::registered('acm')) - { - phpbb::$acm->unload(); - } - - // Close our DB connection. - if (phpbb::registered('db')) - { - phpbb::$db->sql_close(); - } -} - -/** -* Handler for exit calls in phpBB. -* This function supports hooks. -* -* Note: This function is called after the template has been outputted. -*/ -function exit_handler() -{ - // needs to be run prior to the hook - if (phpbb_request::super_globals_disabled()) - { - phpbb_request::enable_super_globals(); - } - - // As a pre-caution... some setups display a blank page if the flush() is not there. - (empty(phpbb::$config['gzip_compress'])) ? @flush() : @ob_flush(); - - exit; -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/functions_admin.php b/phpBB/includes/functions_admin.php deleted file mode 100644 index dee0f82566..0000000000 --- a/phpBB/includes/functions_admin.php +++ /dev/null @@ -1,3251 +0,0 @@ -<?php -/** -* -* @package acp -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Recalculate Binary Tree -function recalc_btree($sql_id, $sql_table, $module_class = '') -{ - if (!$sql_id || !$sql_table) - { - return; - } - - $sql_where = ($module_class) ? " WHERE module_class = '" . phpbb::$db->sql_escape($module_class) . "'" : ''; - - // Reset to minimum possible left and right id - $sql = "SELECT MIN(left_id) as min_left_id, MIN(right_id) as min_right_id - FROM $sql_table - $sql_where"; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - $substract = (int) (min($row['min_left_id'], $row['min_right_id']) - 1); - - if ($substract > 0) - { - $sql = "UPDATE $sql_table - SET left_id = left_id - $substract, right_id = right_id - $substract - $sql_where"; - phpbb::$db->sql_query($sql); - } - - $sql = "SELECT $sql_id, parent_id, left_id, right_id - FROM $sql_table - $sql_where - ORDER BY left_id ASC, parent_id ASC, $sql_id ASC"; - $f_result = phpbb::$db->sql_query($sql); - - while ($item_data = phpbb::$db->sql_fetchrow($f_result)) - { - if ($item_data['parent_id']) - { - $sql = "SELECT left_id, right_id - FROM $sql_table - $sql_where " . (($sql_where) ? 'AND' : 'WHERE') . " - $sql_id = {$item_data['parent_id']}"; - $result = phpbb::$db->sql_query($sql); - - if (!$row = phpbb::$db->sql_fetchrow($result)) - { - $sql = "UPDATE $sql_table SET parent_id = 0 WHERE $sql_id = " . $item_data[$sql_id]; - phpbb::$db->sql_query($sql); - } - phpbb::$db->sql_freeresult($result); - - $sql = "UPDATE $sql_table - SET left_id = left_id + 2, right_id = right_id + 2 - $sql_where " . (($sql_where) ? 'AND' : 'WHERE') . " - left_id > {$row['right_id']}"; - phpbb::$db->sql_query($sql); - - $sql = "UPDATE $sql_table - SET right_id = right_id + 2 - $sql_where " . (($sql_where) ? 'AND' : 'WHERE') . " - {$row['left_id']} BETWEEN left_id AND right_id"; - phpbb::$db->sql_query($sql); - - $item_data['left_id'] = $row['right_id']; - $item_data['right_id'] = $row['right_id'] + 1; - } - else - { - $sql = "SELECT MAX(right_id) AS right_id - FROM $sql_table - $sql_where"; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - $item_data['left_id'] = $row['right_id'] + 1; - $item_data['right_id'] = $row['right_id'] + 2; - } - - $sql = "UPDATE $sql_table - SET left_id = {$item_data['left_id']}, right_id = {$item_data['right_id']} - WHERE $sql_id = " . $item_data[$sql_id]; - phpbb::$db->sql_query($sql); - } - phpbb::$db->sql_freeresult($f_result); -} -*/ - -/** -* Simple version of jumpbox, just lists authed forums -*/ -function make_forum_select($select_id = false, $ignore_id = false, $ignore_acl = false, $ignore_nonpost = false, $ignore_emptycat = true, $only_acl_post = false, $return_array = false) -{ - $acl = ($ignore_acl) ? '' : (($only_acl_post) ? 'f_post' : array('f_list', 'a_forum', 'a_forumadd', 'a_forumdel')); - - // This query is identical to the jumpbox one - $sql = 'SELECT forum_id, forum_name, parent_id, forum_type, left_id, right_id - FROM ' . FORUMS_TABLE . ' - ORDER BY left_id ASC'; - $result = phpbb::$db->sql_query($sql, 600); - - $right = 0; - $padding_store = array('0' => ''); - $padding = ''; - $forum_list = ($return_array) ? array() : ''; - - // Sometimes it could happen that forums will be displayed here not be displayed within the index page - // This is the result of forums not displayed at index, having list permissions and a parent of a forum with no permissions. - // If this happens, the padding could be "broken" - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($row['left_id'] < $right) - { - $padding .= ' '; - $padding_store[$row['parent_id']] = $padding; - } - else if ($row['left_id'] > $right + 1) - { - $padding = (isset($padding_store[$row['parent_id']])) ? $padding_store[$row['parent_id']] : ''; - } - - $right = $row['right_id']; - $disabled = false; - - if ($acl && !phpbb::$acl->acl_gets($acl, $row['forum_id'])) - { - // List permission? - if (phpbb::$acl->acl_get('f_list', $row['forum_id'])) - { - $disabled = true; - } - else - { - continue; - } - } - - if ( - ((is_array($ignore_id) && in_array($row['forum_id'], $ignore_id)) || $row['forum_id'] == $ignore_id) - || - // Non-postable forum with no subforums, don't display - ($row['forum_type'] == FORUM_CAT && ($row['left_id'] + 1 == $row['right_id']) && $ignore_emptycat) - || - ($row['forum_type'] != FORUM_POST && $ignore_nonpost) - ) - { - $disabled = true; - } - - if ($return_array) - { - // Include some more information... - $selected = (is_array($select_id)) ? ((in_array($row['forum_id'], $select_id)) ? true : false) : (($row['forum_id'] == $select_id) ? true : false); - $forum_list[$row['forum_id']] = array_merge(array('padding' => $padding, 'selected' => ($selected && !$disabled), 'disabled' => $disabled), $row); - } - else - { - $selected = (is_array($select_id)) ? ((in_array($row['forum_id'], $select_id)) ? ' selected="selected"' : '') : (($row['forum_id'] == $select_id) ? ' selected="selected"' : ''); - $forum_list .= '<option value="' . $row['forum_id'] . '"' . (($disabled) ? ' disabled="disabled" class="disabled-option"' : $selected) . '>' . $padding . $row['forum_name'] . '</option>'; - } - } - phpbb::$db->sql_freeresult($result); - unset($padding_store); - - return $forum_list; -} - -/** -* Generate size select options -*/ -function size_select_options($size_compare) -{ - $size_types_text = array(phpbb::$user->lang['BYTES'], phpbb::$user->lang['KIB'], phpbb::$user->lang['MIB']); - $size_types = array('b', 'kb', 'mb'); - - $s_size_options = ''; - - for ($i = 0, $size = sizeof($size_types_text); $i < $size; $i++) - { - $selected = ($size_compare == $size_types[$i]) ? ' selected="selected"' : ''; - $s_size_options .= '<option value="' . $size_types[$i] . '"' . $selected . '>' . $size_types_text[$i] . '</option>'; - } - - return $s_size_options; -} - -/** -* Generate list of groups (option fields without select) -* -* @param int $group_id The default group id to mark as selected -* @param array $exclude_ids The group ids to exclude from the list, false (default) if you whish to exclude no id -* @param int $manage_founder If set to false (default) all groups are returned, if 0 only those groups returned not being managed by founders only, if 1 only those groups returned managed by founders only. -* -* @return string The list of options. -*/ -function group_select_options($group_id, $exclude_ids = false, $manage_founder = false) -{ - $exclude_sql = ($exclude_ids !== false && sizeof($exclude_ids)) ? 'WHERE ' . phpbb::$db->sql_in_set('group_id', array_map('intval', $exclude_ids), true) : ''; - $sql_and = (!phpbb::$config['coppa_enable']) ? (($exclude_sql) ? ' AND ' : ' WHERE ') . "group_name <> 'REGISTERED_COPPA'" : ''; - $sql_founder = ($manage_founder !== false) ? (($exclude_sql || $sql_and) ? ' AND ' : ' WHERE ') . 'group_founder_manage = ' . (int) $manage_founder : ''; - - $sql = 'SELECT group_id, group_name, group_type - FROM ' . GROUPS_TABLE . " - $exclude_sql - $sql_and - $sql_founder - ORDER BY group_type DESC, group_name ASC"; - $result = phpbb::$db->sql_query($sql); - - $s_group_options = ''; - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $selected = ($row['group_id'] == $group_id) ? ' selected="selected"' : ''; - $s_group_options .= '<option' . (($row['group_type'] == GROUP_SPECIAL) ? ' class="sep"' : '') . ' value="' . $row['group_id'] . '"' . $selected . '>' . (($row['group_type'] == GROUP_SPECIAL) ? phpbb::$user->lang['G_' . $row['group_name']] : $row['group_name']) . '</option>'; - } - phpbb::$db->sql_freeresult($result); - - return $s_group_options; -} - -/** -* Obtain authed forums list -*/ -function get_forum_list($acl_list = 'f_list', $id_only = true, $postable_only = false, $no_cache = false) -{ - static $forum_rows; - - if (!isset($forum_rows)) - { - // This query is identical to the jumpbox one - $expire_time = ($no_cache) ? 0 : 600; - - $sql = 'SELECT forum_id, forum_name, parent_id, forum_type, left_id, right_id - FROM ' . FORUMS_TABLE . ' - ORDER BY left_id ASC'; - $result = phpbb::$db->sql_query($sql, $expire_time); - - $forum_rows = array(); - - $right = $padding = 0; - $padding_store = array('0' => 0); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($row['left_id'] < $right) - { - $padding++; - $padding_store[$row['parent_id']] = $padding; - } - else if ($row['left_id'] > $right + 1) - { - // Ok, if the $padding_store for this parent is empty there is something wrong. For now we will skip over it. - // @todo digging deep to find out "how" this can happen. - $padding = (isset($padding_store[$row['parent_id']])) ? $padding_store[$row['parent_id']] : $padding; - } - - $right = $row['right_id']; - $row['padding'] = $padding; - - $forum_rows[] = $row; - } - phpbb::$db->sql_freeresult($result); - unset($padding_store); - } - - $rowset = array(); - foreach ($forum_rows as $row) - { - if ($postable_only && $row['forum_type'] != FORUM_POST) - { - continue; - } - - if ($acl_list == '' || ($acl_list != '' && phpbb::$acl->acl_gets($acl_list, $row['forum_id']))) - { - $rowset[] = ($id_only) ? $row['forum_id'] : $row; - } - } - - return $rowset; -} - -/** -* Get forum branch -*/ -function get_forum_branch($forum_id, $type = 'all', $order = 'descending', $include_forum = true) -{ - switch ($type) - { - case 'parents': - $condition = 'f1.left_id BETWEEN f2.left_id AND f2.right_id'; - break; - - case 'children': - $condition = 'f2.left_id BETWEEN f1.left_id AND f1.right_id'; - break; - - default: - $condition = 'f2.left_id BETWEEN f1.left_id AND f1.right_id OR f1.left_id BETWEEN f2.left_id AND f2.right_id'; - break; - } - - $rows = array(); - - $sql = 'SELECT f2.* - FROM ' . FORUMS_TABLE . ' f1 - LEFT JOIN ' . FORUMS_TABLE . " f2 ON ($condition) - WHERE f1.forum_id = $forum_id - ORDER BY f2.left_id " . (($order == 'descending') ? 'ASC' : 'DESC'); - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if (!$include_forum && $row['forum_id'] == $forum_id) - { - continue; - } - - $rows[] = $row; - } - phpbb::$db->sql_freeresult($result); - - return $rows; -} - -/** -* Get physical file listing -*/ -function filelist($rootdir, $dir = '', $type = 'gif|jpg|jpeg|png') -{ - $matches = array(); - - // Remove initial / if present - $rootdir = (substr($rootdir, 0, 1) == '/') ? substr($rootdir, 1) : $rootdir; - // Add closing / if not present - $rootdir = ($rootdir && substr($rootdir, -1) != '/') ? $rootdir . '/' : $rootdir; - - // Remove initial / if present - $dir = (substr($dir, 0, 1) == '/') ? substr($dir, 1) : $dir; - // Add closing / if not present - $dir = ($dir && substr($dir, -1) != '/') ? $dir . '/' : $dir; - - if (!is_dir($rootdir . $dir)) - { - return $matches; - } - - $dh = @opendir($rootdir . $dir); - - if (!$dh) - { - return $matches; - } - - while (($fname = readdir($dh)) !== false) - { - if (is_file("$rootdir$dir$fname")) - { - if (filesize("$rootdir$dir$fname") && preg_match('#\.' . $type . '$#i', $fname)) - { - $matches[$dir][] = $fname; - } - } - else if ($fname[0] != '.' && is_dir("$rootdir$dir$fname")) - { - $matches += filelist($rootdir, "$dir$fname", $type); - } - } - closedir($dh); - - return $matches; -} - -/** -* Move topic(s) -*/ -function move_topics($topic_ids, $forum_id, $auto_sync = true) -{ - if (empty($topic_ids)) - { - return; - } - - $forum_ids = array($forum_id); - - if (!is_array($topic_ids)) - { - $topic_ids = array($topic_ids); - } - - $sql = 'DELETE FROM ' . TOPICS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('topic_moved_id', $topic_ids) . ' - AND forum_id = ' . $forum_id; - phpbb::$db->sql_query($sql); - - if ($auto_sync) - { - $sql = 'SELECT DISTINCT forum_id - FROM ' . TOPICS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('topic_id', $topic_ids); - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $forum_ids[] = $row['forum_id']; - } - phpbb::$db->sql_freeresult($result); - } - - $table_ary = array(TOPICS_TABLE, POSTS_TABLE, LOG_TABLE, DRAFTS_TABLE, TOPICS_TRACK_TABLE); - foreach ($table_ary as $table) - { - $sql = "UPDATE $table - SET forum_id = $forum_id - WHERE " . phpbb::$db->sql_in_set('topic_id', $topic_ids); - phpbb::$db->sql_query($sql); - } - unset($table_ary); - - if ($auto_sync) - { - sync('forum', 'forum_id', $forum_ids, true, true); - unset($forum_ids); - } -} - -/** -* Move post(s) -*/ -function move_posts($post_ids, $topic_id, $auto_sync = true) -{ - if (!is_array($post_ids)) - { - $post_ids = array($post_ids); - } - - $forum_ids = array(); - $topic_ids = array($topic_id); - - $sql = 'SELECT DISTINCT topic_id, forum_id - FROM ' . POSTS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('post_id', $post_ids); - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $forum_ids[] = $row['forum_id']; - $topic_ids[] = $row['topic_id']; - } - phpbb::$db->sql_freeresult($result); - - $sql = 'SELECT forum_id - FROM ' . TOPICS_TABLE . ' - WHERE topic_id = ' . $topic_id; - $result = phpbb::$db->sql_query($sql); - $forum_row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if (!$forum_row) - { - trigger_error('NO_TOPIC'); - } - - $sql = 'UPDATE ' . POSTS_TABLE . ' - SET forum_id = ' . $forum_row['forum_id'] . ", topic_id = $topic_id - WHERE " . phpbb::$db->sql_in_set('post_id', $post_ids); - phpbb::$db->sql_query($sql); - - $sql = 'UPDATE ' . ATTACHMENTS_TABLE . " - SET topic_id = $topic_id, in_message = 0 - WHERE " . phpbb::$db->sql_in_set('post_msg_id', $post_ids); - phpbb::$db->sql_query($sql); - - if ($auto_sync) - { - $forum_ids[] = $forum_row['forum_id']; - - sync('topic_reported', 'topic_id', $topic_ids); - sync('topic_attachment', 'topic_id', $topic_ids); - sync('topic', 'topic_id', $topic_ids, true); - sync('forum', 'forum_id', $forum_ids, true, true); - } - - // Update posted information - update_posted_info($topic_ids); -} - -/** -* Remove topic(s) -*/ -function delete_topics($where_type, $where_ids, $auto_sync = true, $post_count_sync = true, $call_delete_posts = true) -{ - $approved_topics = 0; - $forum_ids = $topic_ids = array(); - - if ($where_type === 'range') - { - $where_clause = $where_ids; - } - else - { - $where_ids = (is_array($where_ids)) ? array_unique($where_ids) : array($where_ids); - - if (!sizeof($where_ids)) - { - return array('topics' => 0, 'posts' => 0); - } - - $where_clause = phpbb::$db->sql_in_set($where_type, $where_ids); - } - - // Making sure that delete_posts does not call delete_topics again... - $return = array( - 'posts' => ($call_delete_posts) ? delete_posts($where_type, $where_ids, false, true, $post_count_sync, false) : 0, - ); - - $sql = 'SELECT topic_id, forum_id, topic_approved, topic_moved_id - FROM ' . TOPICS_TABLE . ' - WHERE ' . $where_clause; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $forum_ids[] = $row['forum_id']; - $topic_ids[] = $row['topic_id']; - - if ($row['topic_approved'] && !$row['topic_moved_id']) - { - $approved_topics++; - } - } - phpbb::$db->sql_freeresult($result); - - $return['topics'] = sizeof($topic_ids); - - if (!sizeof($topic_ids)) - { - return $return; - } - - phpbb::$db->sql_transaction('begin'); - - $table_ary = array(TOPICS_TRACK_TABLE, TOPICS_POSTED_TABLE, POLL_VOTES_TABLE, POLL_OPTIONS_TABLE, TOPICS_WATCH_TABLE, TOPICS_TABLE); - - foreach ($table_ary as $table) - { - $sql = "DELETE FROM $table - WHERE " . phpbb::$db->sql_in_set('topic_id', $topic_ids); - phpbb::$db->sql_query($sql); - } - unset($table_ary); - - $moved_topic_ids = array(); - - // update the other forums - $sql = 'SELECT topic_id, forum_id - FROM ' . TOPICS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('topic_moved_id', $topic_ids); - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $forum_ids[] = $row['forum_id']; - $moved_topic_ids[] = $row['topic_id']; - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($moved_topic_ids)) - { - $sql = 'DELETE FROM ' . TOPICS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('topic_id', $moved_topic_ids); - phpbb::$db->sql_query($sql); - } - - phpbb::$db->sql_transaction('commit'); - - if ($auto_sync) - { - sync('forum', 'forum_id', array_unique($forum_ids), true, true); - sync('topic_reported', $where_type, $where_ids); - } - - if ($approved_topics) - { - set_config_count('num_topics', $approved_topics * (-1), true); - } - - return $return; -} - -/** -* Remove post(s) -*/ -function delete_posts($where_type, $where_ids, $auto_sync = true, $posted_sync = true, $post_count_sync = true, $call_delete_topics = true) -{ - if ($where_type === 'range') - { - $where_clause = $where_ids; - } - else - { - if (is_array($where_ids)) - { - $where_ids = array_unique($where_ids); - } - else - { - $where_ids = array($where_ids); - } - - if (!sizeof($where_ids)) - { - return false; - } - - $where_ids = array_map('intval', $where_ids); - - // Split post deletion into chunks to overcome database limitations - if (sizeof($where_ids) >= 1001) - { - // Split into chunks of 1000 - $chunks = array_chunk($where_ids, 1000); - $removed_posts = 0; - - foreach ($chunks as $_where_ids) - { - $removed_posts += delete_posts($where_type, $_where_ids, $auto_sync, $posted_sync, $post_count_sync, $call_delete_topics); - } - - return $removed_posts; - } - - $where_clause = phpbb::$db->sql_in_set($where_type, $where_ids); - } - - $approved_posts = 0; - $post_ids = $topic_ids = $forum_ids = $post_counts = $remove_topics = array(); - - $sql = 'SELECT post_id, poster_id, post_approved, post_postcount, topic_id, forum_id - FROM ' . POSTS_TABLE . ' - WHERE ' . $where_clause; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $post_ids[] = (int) $row['post_id']; - $poster_ids[] = (int) $row['poster_id']; - $topic_ids[] = (int) $row['topic_id']; - $forum_ids[] = (int) $row['forum_id']; - - if ($row['post_postcount'] && $post_count_sync && $row['post_approved']) - { - $post_counts[$row['poster_id']] = (!empty($post_counts[$row['poster_id']])) ? $post_counts[$row['poster_id']] + 1 : 1; - } - - if ($row['post_approved']) - { - $approved_posts++; - } - } - phpbb::$db->sql_freeresult($result); - - if (!sizeof($post_ids)) - { - return false; - } - - phpbb::$db->sql_transaction('begin'); - - $table_ary = array(POSTS_TABLE, REPORTS_TABLE); - - foreach ($table_ary as $table) - { - $sql = "DELETE FROM $table - WHERE " . phpbb::$db->sql_in_set('post_id', $post_ids); - phpbb::$db->sql_query($sql); - } - unset($table_ary); - - // Adjust users post counts - if (sizeof($post_counts) && $post_count_sync) - { - foreach ($post_counts as $poster_id => $substract) - { - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_posts = 0 - WHERE user_id = ' . $poster_id . ' - AND user_posts < ' . $substract; - phpbb::$db->sql_query($sql); - - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_posts = user_posts - ' . $substract . ' - WHERE user_id = ' . $poster_id . ' - AND user_posts >= ' . $substract; - phpbb::$db->sql_query($sql); - } - } - - // Remove topics now having no posts? - if (sizeof($topic_ids)) - { - $sql = 'SELECT topic_id - FROM ' . POSTS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('topic_id', $topic_ids) . ' - GROUP BY topic_id'; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $remove_topics[] = $row['topic_id']; - } - phpbb::$db->sql_freeresult($result); - - // Actually, those not within remove_topics should be removed. ;) - $remove_topics = array_diff($topic_ids, $remove_topics); - } - - // Remove the message from the search index - $search_type = basename(phpbb::$config['search_type']); - - if (!file_exists(PHPBB_ROOT_PATH . 'includes/search/' . $search_type . '.' . PHP_EXT)) - { - trigger_error('NO_SUCH_SEARCH_MODULE'); - } - - include_once(PHPBB_ROOT_PATH . "includes/search/$search_type." . PHP_EXT); - - $error = false; - $search = new $search_type($error); - - if ($error) - { - trigger_error($error); - } - - $search->index_remove($post_ids, $poster_ids, $forum_ids); - - delete_attachments('post', $post_ids, false); - - phpbb::$db->sql_transaction('commit'); - - // Resync topics_posted table - if ($posted_sync) - { - update_posted_info($topic_ids); - } - - if ($auto_sync) - { - sync('topic_reported', 'topic_id', $topic_ids); - sync('topic', 'topic_id', $topic_ids, true); - sync('forum', 'forum_id', $forum_ids, true, true); - } - - if ($approved_posts) - { - set_config_count('num_posts', $approved_posts * (-1), true); - } - - // We actually remove topics now to not be inconsistent (the delete_topics function calls this function too) - if (sizeof($remove_topics) && $call_delete_topics) - { - delete_topics('topic_id', $remove_topics, $auto_sync, $post_count_sync, false); - } - - return sizeof($post_ids); -} - -/** -* Delete Attachments -* -* @param string $mode can be: post|message|topic|attach|user -* @param mixed $ids can be: post_ids, message_ids, topic_ids, attach_ids, user_ids -* @param bool $resync set this to false if you are deleting posts or topics -*/ -function delete_attachments($mode, $ids, $resync = true) -{ - if (is_array($ids) && sizeof($ids)) - { - $ids = array_unique($ids); - $ids = array_map('intval', $ids); - } - else - { - $ids = array((int) $ids); - } - - if (!sizeof($ids)) - { - return false; - } - - $sql_where = ''; - - switch ($mode) - { - case 'post': - case 'message': - $sql_id = 'post_msg_id'; - $sql_where = ' AND in_message = ' . ($mode == 'message' ? 1 : 0); - break; - - case 'topic': - $sql_id = 'topic_id'; - break; - - case 'user': - $sql_id = 'poster_id'; - break; - - case 'attach': - default: - $sql_id = 'attach_id'; - $mode = 'attach'; - break; - } - - $post_ids = $message_ids = $topic_ids = $physical = array(); - - // Collect post and topic ids for later use if we need to touch remaining entries (if resync is enabled) - $sql = 'SELECT post_msg_id, topic_id, in_message, physical_filename, thumbnail, filesize, is_orphan - FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set($sql_id, $ids); - - $sql .= $sql_where; - - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - // We only need to store post/message/topic ids if resync is enabled and the file is not orphaned - if ($resync && !$row['is_orphan']) - { - if (!$row['in_message']) - { - $post_ids[] = $row['post_msg_id']; - $topic_ids[] = $row['topic_id']; - } - else - { - $message_ids[] = $row['post_msg_id']; - } - } - - $physical[] = array('filename' => $row['physical_filename'], 'thumbnail' => $row['thumbnail'], 'filesize' => $row['filesize'], 'is_orphan' => $row['is_orphan']); - } - phpbb::$db->sql_freeresult($result); - - // Delete attachments - $sql = 'DELETE FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set($sql_id, $ids); - - $sql .= $sql_where; - - phpbb::$db->sql_query($sql); - $num_deleted = phpbb::$db->sql_affectedrows(); - - if (!$num_deleted) - { - return 0; - } - - // Delete attachments from filesystem - $space_removed = $files_removed = 0; - foreach ($physical as $file_ary) - { - if (phpbb_unlink($file_ary['filename'], 'file', true) && !$file_ary['is_orphan']) - { - // Only non-orphaned files count to the file size - $space_removed += $file_ary['filesize']; - $files_removed++; - } - - if ($file_ary['thumbnail']) - { - phpbb_unlink($file_ary['filename'], 'thumbnail', true); - } - } - - if ($space_removed || $files_removed) - { - set_config_count('upload_dir_size', $space_removed * (-1), true); - set_config_count('num_files', $files_removed * (-1), true); - } - - // If we do not resync, we do not need to adjust any message, post, topic or user entries - if (!$resync) - { - return $num_deleted; - } - - // No more use for the original ids - unset($ids); - - // Now, we need to resync posts, messages, topics. We go through every one of them - $post_ids = array_unique($post_ids); - $message_ids = array_unique($message_ids); - $topic_ids = array_unique($topic_ids); - - // Update post indicators for posts now no longer having attachments - if (sizeof($post_ids)) - { - $sql = 'UPDATE ' . POSTS_TABLE . ' - SET post_attachment = 0 - WHERE ' . phpbb::$db->sql_in_set('post_id', $post_ids); - phpbb::$db->sql_query($sql); - } - - // Update message table if messages are affected - if (sizeof($message_ids)) - { - $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' - SET message_attachment = 0 - WHERE ' . phpbb::$db->sql_in_set('msg_id', $message_ids); - phpbb::$db->sql_query($sql); - } - - // Now update the topics. This is a bit trickier, because there could be posts still having attachments within the topic - if (sizeof($topic_ids)) - { - // Just check which topics are still having an assigned attachment not orphaned by querying the attachments table (much less entries expected) - $sql = 'SELECT topic_id - FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('topic_id', $topic_ids) . ' - AND is_orphan = 0'; - $result = phpbb::$db->sql_query($sql); - - $remaining_ids = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $remaining_ids[] = $row['topic_id']; - } - phpbb::$db->sql_freeresult($result); - - // Now only unset those ids remaining - $topic_ids = array_diff($topic_ids, $remaining_ids); - - if (sizeof($topic_ids)) - { - $sql = 'UPDATE ' . TOPICS_TABLE . ' - SET topic_attachment = 0 - WHERE ' . phpbb::$db->sql_in_set('topic_id', $topic_ids); - phpbb::$db->sql_query($sql); - } - } - - return $num_deleted; -} - -/** -* Remove topic shadows -*/ -function delete_topic_shadows($max_age, $forum_id = '', $auto_sync = true) -{ - $where = (is_array($forum_id)) ? 'AND ' . phpbb::$db->sql_in_set('t.forum_id', array_map('intval', $forum_id)) : (($forum_id) ? 'AND t.forum_id = ' . (int) $forum_id : ''); - - if (phpbb::$db->features['multi_table_deletion']) - { - $sql = 'DELETE FROM ' . TOPICS_TABLE . ' t - USING ' . TOPICS_TABLE . ' t2 - WHERE t.topic_moved_id = t2.topic_id - AND t.topic_time < ' . (time() - $max_age) - . $where; - phpbb::$db->sql_query($sql); - } - else - { - $sql = 'SELECT t.topic_id - FROM ' . TOPICS_TABLE . ' t, ' . TOPICS_TABLE . ' t2 - WHERE t.topic_moved_id = t2.topic_id - AND t.topic_time < ' . (time() - $max_age) - . $where; - $result = phpbb::$db->sql_query($sql); - - $topic_ids = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $topic_ids[] = $row['topic_id']; - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($topic_ids)) - { - $sql = 'DELETE FROM ' . TOPICS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('topic_id', $topic_ids); - phpbb::$db->sql_query($sql); - } - } - - if ($auto_sync) - { - $where_type = ($forum_id) ? 'forum_id' : ''; - sync('forum', $where_type, $forum_id, true, true); - } -} - -/** -* Update/Sync posted information for topics -*/ -function update_posted_info(&$topic_ids) -{ - if (empty($topic_ids) || !phpbb::$config['load_db_track']) - { - return; - } - - // First of all, let us remove any posted information for these topics - $sql = 'DELETE FROM ' . TOPICS_POSTED_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('topic_id', $topic_ids); - phpbb::$db->sql_query($sql); - - // Now, let us collect the user/topic combos for rebuilding the information - $sql = 'SELECT poster_id, topic_id - FROM ' . POSTS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('topic_id', $topic_ids) . ' - AND poster_id <> ' . ANONYMOUS . ' - GROUP BY poster_id, topic_id'; - $result = phpbb::$db->sql_query($sql); - - $posted = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - // Add as key to make them unique (grouping by) and circumvent empty keys on array_unique - $posted[$row['poster_id']][] = $row['topic_id']; - } - phpbb::$db->sql_freeresult($result); - - // Now add the information... - $sql_ary = array(); - foreach ($posted as $user_id => $topic_row) - { - foreach ($topic_row as $topic_id) - { - $sql_ary[] = array( - 'user_id' => (int) $user_id, - 'topic_id' => (int) $topic_id, - 'topic_posted' => 1, - ); - } - } - unset($posted); - - phpbb::$db->sql_multi_insert(TOPICS_POSTED_TABLE, $sql_ary); -} - -/** -* Delete attached file -*/ -function phpbb_unlink($filename, $mode = 'file', $entry_removed = false) -{ - // Because of copying topics or modifications a physical filename could be assigned more than once. If so, do not remove the file itself. - $sql = 'SELECT COUNT(attach_id) AS num_entries - FROM ' . ATTACHMENTS_TABLE . " - WHERE physical_filename = '" . phpbb::$db->sql_escape(basename($filename)) . "'"; - $result = phpbb::$db->sql_query($sql); - $num_entries = (int) phpbb::$db->sql_fetchfield('num_entries'); - phpbb::$db->sql_freeresult($result); - - // Do not remove file if at least one additional entry with the same name exist. - if (($entry_removed && $num_entries > 0) || (!$entry_removed && $num_entries > 1)) - { - return false; - } - - $filename = ($mode == 'thumbnail') ? 'thumb_' . basename($filename) : basename($filename); - return @unlink(PHPBB_ROOT_PATH . phpbb::$config['upload_path'] . '/' . $filename); -} - -/** -* All-encompasing sync function -* -* Exaples: -* <code> -* sync('topic', 'topic_id', 123); // resync topic #123 -* sync('topic', 'forum_id', array(2, 3)); // resync topics from forum #2 and #3 -* sync('topic'); // resync all topics -* sync('topic', 'range', 'topic_id BETWEEN 1 AND 60'); // resync a range of topics/forums (only available for 'topic' and 'forum' modes) -* </code> -* -* Modes: -* - forum Resync complete forum -* - topic Resync topics -* - topic_moved Removes topic shadows that would be in the same forum as the topic they link to -* - topic_approved Resyncs the topic_approved flag according to the status of the first post -* - post_reported Resyncs the post_reported flag, relying on actual reports -* - topic_reported Resyncs the topic_reported flag, relying on post_reported flags -* - post_attachement Same as post_reported, but with attachment flags -* - topic_attachement Same as topic_reported, but with attachment flags -*/ -function sync($mode, $where_type = '', $where_ids = '', $resync_parents = false, $sync_extra = false) -{ - if (is_array($where_ids)) - { - $where_ids = array_unique($where_ids); - $where_ids = array_map('intval', $where_ids); - } - else if ($where_type != 'range') - { - $where_ids = ($where_ids) ? array((int) $where_ids) : array(); - } - - if ($mode == 'forum' || $mode == 'topic' || $mode == 'topic_approved' || $mode == 'topic_reported' || $mode == 'post_reported') - { - if (!$where_type) - { - $where_sql = ''; - $where_sql_and = 'WHERE'; - } - else if ($where_type == 'range') - { - // Only check a range of topics/forums. For instance: 'topic_id BETWEEN 1 AND 60' - $where_sql = 'WHERE (' . $mode[0] . ".$where_ids)"; - $where_sql_and = $where_sql . "\n\tAND"; - } - else - { - // Do not sync the "global forum" - $where_ids = array_diff($where_ids, array(0)); - - if (!sizeof($where_ids)) - { - // Empty array with IDs. This means that we don't have any work to do. Just return. - return; - } - - // Limit the topics/forums we are syncing, use specific topic/forum IDs. - // $where_type contains the field for the where clause (forum_id, topic_id) - $where_sql = 'WHERE ' . phpbb::$db->sql_in_set($mode[0] . '.' . $where_type, $where_ids); - $where_sql_and = $where_sql . "\n\tAND"; - } - } - else - { - if (!sizeof($where_ids)) - { - return; - } - - // $where_type contains the field for the where clause (forum_id, topic_id) - $where_sql = 'WHERE ' . phpbb::$db->sql_in_set($mode[0] . '.' . $where_type, $where_ids); - $where_sql_and = $where_sql . "\n\tAND"; - } - - switch ($mode) - { - case 'topic_moved': - if (phpbb::$db->features['multi_table_deletion']) - { - $sql = 'DELETE FROM ' . TOPICS_TABLE . ' - USING ' . TOPICS_TABLE . ' t1, ' . TOPICS_TABLE . " t2 - WHERE t1.topic_moved_id = t2.topic_id - AND t1.forum_id = t2.forum_id"; - phpbb::$db->sql_query($sql); - } - else - { - $sql = 'SELECT t1.topic_id - FROM ' .TOPICS_TABLE . ' t1, ' . TOPICS_TABLE . " t2 - WHERE t1.topic_moved_id = t2.topic_id - AND t1.forum_id = t2.forum_id"; - $result = phpbb::$db->sql_query($sql); - - $topic_id_ary = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $topic_id_ary[] = $row['topic_id']; - } - phpbb::$db->sql_freeresult($result); - - if (!sizeof($topic_id_ary)) - { - return; - } - - $sql = 'DELETE FROM ' . TOPICS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('topic_id', $topic_id_ary); - phpbb::$db->sql_query($sql); - } - break; - - case 'topic_approved': - if (phpbb::$db->dbms_type == 'mysql') - { - $sql = 'UPDATE ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p - SET t.topic_approved = p.post_approved - $where_sql_and t.topic_first_post_id = p.post_id"; - phpbb::$db->sql_query($sql); - } - else - { - $sql = 'SELECT t.topic_id, p.post_approved - FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p - $where_sql_and p.post_id = t.topic_first_post_id - AND p.post_approved <> t.topic_approved"; - $result = phpbb::$db->sql_query($sql); - - $topic_ids = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $topic_ids[] = $row['topic_id']; - } - phpbb::$db->sql_freeresult($result); - - if (!sizeof($topic_ids)) - { - return; - } - - $sql = 'UPDATE ' . TOPICS_TABLE . ' - SET topic_approved = 1 - topic_approved - WHERE ' . phpbb::$db->sql_in_set('topic_id', $topic_ids); - phpbb::$db->sql_query($sql); - } - break; - - case 'post_reported': - $post_ids = $post_reported = array(); - - $sql = 'SELECT p.post_id, p.post_reported - FROM ' . POSTS_TABLE . " p - $where_sql - GROUP BY p.post_id, p.post_reported"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $post_ids[$row['post_id']] = $row['post_id']; - if ($row['post_reported']) - { - $post_reported[$row['post_id']] = 1; - } - } - phpbb::$db->sql_freeresult($result); - - $sql = 'SELECT DISTINCT(post_id) - FROM ' . REPORTS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('post_id', $post_ids) . ' - AND report_closed = 0'; - $result = phpbb::$db->sql_query($sql); - - $post_ids = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if (!isset($post_reported[$row['post_id']])) - { - $post_ids[] = $row['post_id']; - } - else - { - unset($post_reported[$row['post_id']]); - } - } - phpbb::$db->sql_freeresult($result); - - // $post_reported should be empty by now, if it's not it contains - // posts that are falsely flagged as reported - foreach ($post_reported as $post_id => $void) - { - $post_ids[] = $post_id; - } - - if (sizeof($post_ids)) - { - $sql = 'UPDATE ' . POSTS_TABLE . ' - SET post_reported = 1 - post_reported - WHERE ' . phpbb::$db->sql_in_set('post_id', $post_ids); - phpbb::$db->sql_query($sql); - } - break; - - case 'topic_reported': - if ($sync_extra) - { - sync('post_reported', $where_type, $where_ids); - } - - $topic_ids = $topic_reported = array(); - - $sql = 'SELECT DISTINCT(t.topic_id) - FROM ' . POSTS_TABLE . " t - $where_sql_and t.post_reported = 1"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $topic_reported[$row['topic_id']] = 1; - } - phpbb::$db->sql_freeresult($result); - - $sql = 'SELECT t.topic_id, t.topic_reported - FROM ' . TOPICS_TABLE . " t - $where_sql"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($row['topic_reported'] ^ isset($topic_reported[$row['topic_id']])) - { - $topic_ids[] = $row['topic_id']; - } - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($topic_ids)) - { - $sql = 'UPDATE ' . TOPICS_TABLE . ' - SET topic_reported = 1 - topic_reported - WHERE ' . phpbb::$db->sql_in_set('topic_id', $topic_ids); - phpbb::$db->sql_query($sql); - } - break; - - case 'post_attachment': - $post_ids = $post_attachment = array(); - - $sql = 'SELECT p.post_id, p.post_attachment - FROM ' . POSTS_TABLE . " p - $where_sql - GROUP BY p.post_id, p.post_attachment"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $post_ids[$row['post_id']] = $row['post_id']; - if ($row['post_attachment']) - { - $post_attachment[$row['post_id']] = 1; - } - } - phpbb::$db->sql_freeresult($result); - - $sql = 'SELECT DISTINCT(post_msg_id) - FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('post_msg_id', $post_ids) . ' - AND in_message = 0'; - $result = phpbb::$db->sql_query($sql); - - $post_ids = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if (!isset($post_attachment[$row['post_msg_id']])) - { - $post_ids[] = $row['post_msg_id']; - } - else - { - unset($post_attachment[$row['post_msg_id']]); - } - } - phpbb::$db->sql_freeresult($result); - - // $post_attachment should be empty by now, if it's not it contains - // posts that are falsely flagged as having attachments - foreach ($post_attachment as $post_id => $void) - { - $post_ids[] = $post_id; - } - - if (sizeof($post_ids)) - { - $sql = 'UPDATE ' . POSTS_TABLE . ' - SET post_attachment = 1 - post_attachment - WHERE ' . phpbb::$db->sql_in_set('post_id', $post_ids); - phpbb::$db->sql_query($sql); - } - break; - - case 'topic_attachment': - if ($sync_extra) - { - sync('post_attachment', $where_type, $where_ids); - } - - $topic_ids = $topic_attachment = array(); - - $sql = 'SELECT DISTINCT(t.topic_id) - FROM ' . POSTS_TABLE . " t - $where_sql_and t.post_attachment = 1"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $topic_attachment[$row['topic_id']] = 1; - } - phpbb::$db->sql_freeresult($result); - - $sql = 'SELECT t.topic_id, t.topic_attachment - FROM ' . TOPICS_TABLE . " t - $where_sql"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($row['topic_attachment'] ^ isset($topic_attachment[$row['topic_id']])) - { - $topic_ids[] = $row['topic_id']; - } - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($topic_ids)) - { - $sql = 'UPDATE ' . TOPICS_TABLE . ' - SET topic_attachment = 1 - topic_attachment - WHERE ' . phpbb::$db->sql_in_set('topic_id', $topic_ids); - phpbb::$db->sql_query($sql); - } - break; - - case 'forum': - - // 1: Get the list of all forums - $sql = 'SELECT f.* - FROM ' . FORUMS_TABLE . " f - $where_sql"; - $result = phpbb::$db->sql_query($sql); - - $forum_data = $forum_ids = $post_ids = $last_post_id = $post_info = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($row['forum_type'] == FORUM_LINK) - { - continue; - } - - $forum_id = (int) $row['forum_id']; - $forum_ids[$forum_id] = $forum_id; - - $forum_data[$forum_id] = $row; - if ($sync_extra) - { - $forum_data[$forum_id]['posts'] = 0; - $forum_data[$forum_id]['topics'] = 0; - $forum_data[$forum_id]['topics_real'] = 0; - } - $forum_data[$forum_id]['last_post_id'] = 0; - $forum_data[$forum_id]['last_post_subject'] = ''; - $forum_data[$forum_id]['last_post_time'] = 0; - $forum_data[$forum_id]['last_poster_id'] = 0; - $forum_data[$forum_id]['last_poster_name'] = ''; - $forum_data[$forum_id]['last_poster_colour'] = ''; - } - phpbb::$db->sql_freeresult($result); - - if (!sizeof($forum_ids)) - { - break; - } - - $forum_ids = array_values($forum_ids); - - // 2: Get topic counts for each forum (optional) - if ($sync_extra) - { - $sql = 'SELECT forum_id, topic_approved, COUNT(topic_id) AS forum_topics - FROM ' . TOPICS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('forum_id', $forum_ids) . ' - GROUP BY forum_id, topic_approved'; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $forum_id = (int) $row['forum_id']; - $forum_data[$forum_id]['topics_real'] += $row['forum_topics']; - - if ($row['topic_approved']) - { - $forum_data[$forum_id]['topics'] = $row['forum_topics']; - } - } - phpbb::$db->sql_freeresult($result); - } - - // 3: Get post count for each forum (optional) - if ($sync_extra) - { - if (sizeof($forum_ids) == 1) - { - $sql = 'SELECT SUM(t.topic_replies + 1) AS forum_posts - FROM ' . TOPICS_TABLE . ' t - WHERE ' . phpbb::$db->sql_in_set('t.forum_id', $forum_ids) . ' - AND t.topic_approved = 1 - AND t.topic_status <> ' . ITEM_MOVED; - } - else - { - $sql = 'SELECT t.forum_id, SUM(t.topic_replies + 1) AS forum_posts - FROM ' . TOPICS_TABLE . ' t - WHERE ' . phpbb::$db->sql_in_set('t.forum_id', $forum_ids) . ' - AND t.topic_approved = 1 - AND t.topic_status <> ' . ITEM_MOVED . ' - GROUP BY t.forum_id'; - } - - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $forum_id = (sizeof($forum_ids) == 1) ? (int) $forum_ids[0] : (int) $row['forum_id']; - - $forum_data[$forum_id]['posts'] = (int) $row['forum_posts']; - } - phpbb::$db->sql_freeresult($result); - } - - // 4: Get last_post_id for each forum - if (sizeof($forum_ids) == 1) - { - $sql = 'SELECT MAX(t.topic_last_post_id) as last_post_id - FROM ' . TOPICS_TABLE . ' t - WHERE ' . phpbb::$db->sql_in_set('t.forum_id', $forum_ids) . ' - AND t.topic_approved = 1'; - } - else - { - $sql = 'SELECT t.forum_id, MAX(t.topic_last_post_id) as last_post_id - FROM ' . TOPICS_TABLE . ' t - WHERE ' . phpbb::$db->sql_in_set('t.forum_id', $forum_ids) . ' - AND t.topic_approved = 1 - GROUP BY t.forum_id'; - } - - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $forum_id = (sizeof($forum_ids) == 1) ? (int) $forum_ids[0] : (int) $row['forum_id']; - - $forum_data[$forum_id]['last_post_id'] = (int) $row['last_post_id']; - - $post_ids[] = $row['last_post_id']; - } - phpbb::$db->sql_freeresult($result); - - // 5: Retrieve last_post infos - if (sizeof($post_ids)) - { - $sql = 'SELECT p.post_id, p.poster_id, p.post_subject, p.post_time, p.post_username, u.username, u.user_colour - FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u - WHERE ' . phpbb::$db->sql_in_set('p.post_id', $post_ids) . ' - AND p.poster_id = u.user_id'; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $post_info[$row['post_id']] = $row; - } - phpbb::$db->sql_freeresult($result); - - foreach ($forum_data as $forum_id => $data) - { - if ($data['last_post_id']) - { - if (isset($post_info[$data['last_post_id']])) - { - $forum_data[$forum_id]['last_post_subject'] = $post_info[$data['last_post_id']]['post_subject']; - $forum_data[$forum_id]['last_post_time'] = $post_info[$data['last_post_id']]['post_time']; - $forum_data[$forum_id]['last_poster_id'] = $post_info[$data['last_post_id']]['poster_id']; - $forum_data[$forum_id]['last_poster_name'] = ($post_info[$data['last_post_id']]['poster_id'] != ANONYMOUS) ? $post_info[$data['last_post_id']]['username'] : $post_info[$data['last_post_id']]['post_username']; - $forum_data[$forum_id]['last_poster_colour'] = $post_info[$data['last_post_id']]['user_colour']; - } - else - { - // For some reason we did not find the post in the db - $forum_data[$forum_id]['last_post_id'] = 0; - $forum_data[$forum_id]['last_post_subject'] = ''; - $forum_data[$forum_id]['last_post_time'] = 0; - $forum_data[$forum_id]['last_poster_id'] = 0; - $forum_data[$forum_id]['last_poster_name'] = ''; - $forum_data[$forum_id]['last_poster_colour'] = ''; - } - } - } - unset($post_info); - } - - // 6: Now do that thing - $fieldnames = array('last_post_id', 'last_post_subject', 'last_post_time', 'last_poster_id', 'last_poster_name', 'last_poster_colour'); - - if ($sync_extra) - { - array_push($fieldnames, 'posts', 'topics', 'topics_real'); - } - - foreach ($forum_data as $forum_id => $row) - { - $sql_ary = array(); - - foreach ($fieldnames as $fieldname) - { - if ($row['forum_' . $fieldname] != $row[$fieldname]) - { - if (preg_match('#(name|colour|subject)$#', $fieldname)) - { - $sql_ary['forum_' . $fieldname] = (string) $row[$fieldname]; - } - else - { - $sql_ary['forum_' . $fieldname] = (int) $row[$fieldname]; - } - } - } - - if (sizeof($sql_ary)) - { - $sql = 'UPDATE ' . FORUMS_TABLE . ' - SET ' . phpbb::$db->sql_build_array('UPDATE', $sql_ary) . ' - WHERE forum_id = ' . $forum_id; - phpbb::$db->sql_query($sql); - } - } - break; - - case 'topic': - $topic_data = $post_ids = $approved_unapproved_ids = $resync_forums = $delete_topics = $delete_posts = $moved_topics = array(); - - $sql = 'SELECT t.topic_id, t.forum_id, t.topic_moved_id, t.topic_approved, ' . (($sync_extra) ? 't.topic_attachment, t.topic_reported, ' : '') . 't.topic_poster, t.topic_time, t.topic_replies, t.topic_replies_real, t.topic_first_post_id, t.topic_first_poster_name, t.topic_first_poster_colour, t.topic_last_post_id, t.topic_last_post_subject, t.topic_last_poster_id, t.topic_last_poster_name, t.topic_last_poster_colour, t.topic_last_post_time - FROM ' . TOPICS_TABLE . " t - $where_sql"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($row['topic_moved_id']) - { - $moved_topics[] = $row['topic_id']; - continue; - } - - $topic_id = (int) $row['topic_id']; - $topic_data[$topic_id] = $row; - $topic_data[$topic_id]['replies_real'] = -1; - $topic_data[$topic_id]['replies'] = 0; - $topic_data[$topic_id]['first_post_id'] = 0; - $topic_data[$topic_id]['last_post_id'] = 0; - unset($topic_data[$topic_id]['topic_id']); - - // This array holds all topic_ids - $delete_topics[$topic_id] = ''; - - if ($sync_extra) - { - $topic_data[$topic_id]['reported'] = 0; - $topic_data[$topic_id]['attachment'] = 0; - } - } - phpbb::$db->sql_freeresult($result); - - // Use "t" as table alias because of the $where_sql clause - // NOTE: 't.post_approved' in the GROUP BY is causing a major slowdown. - $sql = 'SELECT t.topic_id, t.post_approved, COUNT(t.post_id) AS total_posts, MIN(t.post_id) AS first_post_id, MAX(t.post_id) AS last_post_id - FROM ' . POSTS_TABLE . " t - $where_sql - GROUP BY t.topic_id, t.post_approved"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $topic_id = (int) $row['topic_id']; - - $row['first_post_id'] = (int) $row['first_post_id']; - $row['last_post_id'] = (int) $row['last_post_id']; - - if (!isset($topic_data[$topic_id])) - { - // Hey, these posts come from a topic that does not exist - $delete_posts[$topic_id] = ''; - } - else - { - // Unset the corresponding entry in $delete_topics - // When we'll be done, only topics with no posts will remain - unset($delete_topics[$topic_id]); - - $topic_data[$topic_id]['replies_real'] += $row['total_posts']; - $topic_data[$topic_id]['first_post_id'] = (!$topic_data[$topic_id]['first_post_id']) ? $row['first_post_id'] : min($topic_data[$topic_id]['first_post_id'], $row['first_post_id']); - - if ($row['post_approved'] || !$topic_data[$topic_id]['last_post_id']) - { - $topic_data[$topic_id]['replies'] = $row['total_posts'] - 1; - $topic_data[$topic_id]['last_post_id'] = $row['last_post_id']; - } - } - } - phpbb::$db->sql_freeresult($result); - - foreach ($topic_data as $topic_id => $row) - { - $post_ids[] = $row['first_post_id']; - if ($row['first_post_id'] != $row['last_post_id']) - { - $post_ids[] = $row['last_post_id']; - } - } - - // Now we delete empty topics and orphan posts - if (sizeof($delete_posts)) - { - delete_posts('topic_id', array_keys($delete_posts), false); - unset($delete_posts); - } - - if (!sizeof($topic_data)) - { - // If we get there, topic ids were invalid or topics did not contain any posts - delete_topics($where_type, $where_ids, true); - return; - } - - if (sizeof($delete_topics)) - { - $delete_topic_ids = array(); - foreach ($delete_topics as $topic_id => $void) - { - unset($topic_data[$topic_id]); - $delete_topic_ids[] = $topic_id; - } - - delete_topics('topic_id', $delete_topic_ids, false); - unset($delete_topics, $delete_topic_ids); - } - - $sql = 'SELECT p.post_id, p.topic_id, p.post_approved, p.poster_id, p.post_subject, p.post_username, p.post_time, u.username, u.user_colour - FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u - WHERE ' . phpbb::$db->sql_in_set('p.post_id', $post_ids) . ' - AND u.user_id = p.poster_id'; - $result = phpbb::$db->sql_query($sql); - - $post_ids = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $topic_id = intval($row['topic_id']); - - if ($row['post_id'] == $topic_data[$topic_id]['first_post_id']) - { - if ($topic_data[$topic_id]['topic_approved'] != $row['post_approved']) - { - $approved_unapproved_ids[] = $topic_id; - } - $topic_data[$topic_id]['time'] = $row['post_time']; - $topic_data[$topic_id]['poster'] = $row['poster_id']; - $topic_data[$topic_id]['first_poster_name'] = ($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']; - $topic_data[$topic_id]['first_poster_colour'] = $row['user_colour']; - } - - if ($row['post_id'] == $topic_data[$topic_id]['last_post_id']) - { - $topic_data[$topic_id]['last_poster_id'] = $row['poster_id']; - $topic_data[$topic_id]['last_post_subject'] = $row['post_subject']; - $topic_data[$topic_id]['last_post_time'] = $row['post_time']; - $topic_data[$topic_id]['last_poster_name'] = ($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']; - $topic_data[$topic_id]['last_poster_colour'] = $row['user_colour']; - } - } - phpbb::$db->sql_freeresult($result); - - // Make sure shadow topics do link to existing topics - if (sizeof($moved_topics)) - { - $delete_topics = array(); - - $sql = 'SELECT t1.topic_id, t1.topic_moved_id - FROM ' . TOPICS_TABLE . ' t1 - LEFT JOIN ' . TOPICS_TABLE . ' t2 ON (t2.topic_id = t1.topic_moved_id) - WHERE ' . phpbb::$db->sql_in_set('t1.topic_id', $moved_topics) . ' - AND t2.topic_id IS NULL'; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $delete_topics[] = $row['topic_id']; - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($delete_topics)) - { - delete_topics('topic_id', $delete_topics, false); - } - unset($delete_topics); - - // Make sure shadow topics having no last post data being updated (this only rarely happens...) - $sql = 'SELECT topic_id, topic_moved_id, topic_last_post_id, topic_first_post_id - FROM ' . TOPICS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('topic_id', $moved_topics) . ' - AND topic_last_post_time = 0'; - $result = phpbb::$db->sql_query($sql); - - $shadow_topic_data = $post_ids = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $shadow_topic_data[$row['topic_moved_id']] = $row; - $post_ids[] = $row['topic_last_post_id']; - $post_ids[] = $row['topic_first_post_id']; - } - phpbb::$db->sql_freeresult($result); - - $sync_shadow_topics = array(); - if (sizeof($post_ids)) - { - $sql = 'SELECT p.post_id, p.topic_id, p.post_approved, p.poster_id, p.post_subject, p.post_username, p.post_time, u.username, u.user_colour - FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u - WHERE ' . phpbb::$db->sql_in_set('p.post_id', $post_ids) . ' - AND u.user_id = p.poster_id'; - $result = phpbb::$db->sql_query($sql); - - $post_ids = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $topic_id = (int) $row['topic_id']; - - // Ok, there should be a shadow topic. If there isn't, then there's something wrong with the db. - // However, there's not much we can do about it. - if (!empty($shadow_topic_data[$topic_id])) - { - if ($row['post_id'] == $shadow_topic_data[$topic_id]['topic_first_post_id']) - { - $orig_topic_id = $shadow_topic_data[$topic_id]['topic_id']; - - if (!isset($sync_shadow_topics[$orig_topic_id])) - { - $sync_shadow_topics[$orig_topic_id] = array(); - } - - $sync_shadow_topics[$orig_topic_id]['topic_time'] = $row['post_time']; - $sync_shadow_topics[$orig_topic_id]['topic_poster'] = $row['poster_id']; - $sync_shadow_topics[$orig_topic_id]['topic_first_poster_name'] = ($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']; - $sync_shadow_topics[$orig_topic_id]['topic_first_poster_colour'] = $row['user_colour']; - } - - if ($row['post_id'] == $shadow_topic_data[$topic_id]['topic_last_post_id']) - { - $orig_topic_id = $shadow_topic_data[$topic_id]['topic_id']; - - if (!isset($sync_shadow_topics[$orig_topic_id])) - { - $sync_shadow_topics[$orig_topic_id] = array(); - } - - $sync_shadow_topics[$orig_topic_id]['topic_last_poster_id'] = $row['poster_id']; - $sync_shadow_topics[$orig_topic_id]['topic_last_post_subject'] = $row['post_subject']; - $sync_shadow_topics[$orig_topic_id]['topic_last_post_time'] = $row['post_time']; - $sync_shadow_topics[$orig_topic_id]['topic_last_poster_name'] = ($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']; - $sync_shadow_topics[$orig_topic_id]['topic_last_poster_colour'] = $row['user_colour']; - } - } - } - phpbb::$db->sql_freeresult($result); - - $shadow_topic_data = array(); - - // Update the information we collected - if (sizeof($sync_shadow_topics)) - { - foreach ($sync_shadow_topics as $sync_topic_id => $sql_ary) - { - $sql = 'UPDATE ' . TOPICS_TABLE . ' - SET ' . phpbb::$db->sql_build_array('UPDATE', $sql_ary) . ' - WHERE topic_id = ' . $sync_topic_id; - phpbb::$db->sql_query($sql); - } - } - } - - unset($sync_shadow_topics, $shadow_topic_data); - } - - // approved becomes unapproved, and vice-versa - if (sizeof($approved_unapproved_ids)) - { - $sql = 'UPDATE ' . TOPICS_TABLE . ' - SET topic_approved = 1 - topic_approved - WHERE ' . phpbb::$db->sql_in_set('topic_id', $approved_unapproved_ids); - phpbb::$db->sql_query($sql); - } - unset($approved_unapproved_ids); - - // These are fields that will be synchronised - $fieldnames = array('time', 'replies', 'replies_real', 'poster', 'first_post_id', 'first_poster_name', 'first_poster_colour', 'last_post_id', 'last_post_subject', 'last_post_time', 'last_poster_id', 'last_poster_name', 'last_poster_colour'); - - if ($sync_extra) - { - // This routine assumes that post_reported values are correct - // if they are not, use sync('post_reported') first - $sql = 'SELECT t.topic_id, p.post_id - FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p - $where_sql_and p.topic_id = t.topic_id - AND p.post_reported = 1 - GROUP BY t.topic_id, p.post_id"; - $result = phpbb::$db->sql_query($sql); - - $fieldnames[] = 'reported'; - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $topic_data[intval($row['topic_id'])]['reported'] = 1; - } - phpbb::$db->sql_freeresult($result); - - // This routine assumes that post_attachment values are correct - // if they are not, use sync('post_attachment') first - $sql = 'SELECT t.topic_id, p.post_id - FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p - $where_sql_and p.topic_id = t.topic_id - AND p.post_attachment = 1 - GROUP BY t.topic_id, p.post_id"; - $result = phpbb::$db->sql_query($sql); - - $fieldnames[] = 'attachment'; - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $topic_data[intval($row['topic_id'])]['attachment'] = 1; - } - phpbb::$db->sql_freeresult($result); - } - - foreach ($topic_data as $topic_id => $row) - { - $sql_ary = array(); - - foreach ($fieldnames as $fieldname) - { - if (isset($row[$fieldname]) && isset($row['topic_' . $fieldname]) && $row['topic_' . $fieldname] != $row[$fieldname]) - { - $sql_ary['topic_' . $fieldname] = $row[$fieldname]; - } - } - - if (sizeof($sql_ary)) - { - $sql = 'UPDATE ' . TOPICS_TABLE . ' - SET ' . phpbb::$db->sql_build_array('UPDATE', $sql_ary) . ' - WHERE topic_id = ' . $topic_id; - phpbb::$db->sql_query($sql); - - $resync_forums[$row['forum_id']] = $row['forum_id']; - } - } - unset($topic_data); - - // if some topics have been resync'ed then resync parent forums - // except when we're only syncing a range, we don't want to sync forums during - // batch processing. - if ($resync_parents && sizeof($resync_forums) && $where_type != 'range') - { - sync('forum', 'forum_id', array_values($resync_forums), true, true); - } - break; - } - - return; -} - -/** -* Prune function -*/ -function prune($forum_id, $prune_mode, $prune_date, $prune_flags = 0, $auto_sync = true) -{ - if (!is_array($forum_id)) - { - $forum_id = array($forum_id); - } - - if (!sizeof($forum_id)) - { - return; - } - - $sql_and = ''; - - if (!($prune_flags & FORUM_FLAG_PRUNE_ANNOUNCE)) - { - $sql_and .= ' AND topic_type <> ' . POST_ANNOUNCE; - } - - if (!($prune_flags & FORUM_FLAG_PRUNE_STICKY)) - { - $sql_and .= ' AND topic_type <> ' . POST_STICKY; - } - - if ($prune_mode == 'posted') - { - $sql_and .= " AND topic_last_post_time < $prune_date"; - } - - if ($prune_mode == 'viewed') - { - $sql_and .= " AND topic_last_view_time < $prune_date"; - } - - $sql = 'SELECT topic_id - FROM ' . TOPICS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('forum_id', $forum_id) . " - AND poll_start = 0 - $sql_and"; - $result = phpbb::$db->sql_query($sql); - - $topic_list = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $topic_list[] = $row['topic_id']; - } - phpbb::$db->sql_freeresult($result); - - if ($prune_flags & FORUM_FLAG_PRUNE_POLL) - { - $sql = 'SELECT topic_id - FROM ' . TOPICS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('forum_id', $forum_id) . " - AND poll_start > 0 - AND poll_last_vote < $prune_date - $sql_and"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $topic_list[] = $row['topic_id']; - } - phpbb::$db->sql_freeresult($result); - - $topic_list = array_unique($topic_list); - } - - return delete_topics('topic_id', $topic_list, $auto_sync, false); -} - -/** -* Function auto_prune(), this function now relies on passed vars -*/ -function auto_prune($forum_id, $prune_mode, $prune_flags, $prune_days, $prune_freq) -{ - $sql = 'SELECT forum_name - FROM ' . FORUMS_TABLE . " - WHERE forum_id = $forum_id"; - $result = phpbb::$db->sql_query($sql, 3600); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ($row) - { - $prune_date = time() - ($prune_days * 86400); - $next_prune = time() + ($prune_freq * 86400); - - prune($forum_id, $prune_mode, $prune_date, $prune_flags, true); - - $sql = 'UPDATE ' . FORUMS_TABLE . " - SET prune_next = $next_prune - WHERE forum_id = $forum_id"; - phpbb::$db->sql_query($sql); - - add_log('admin', 'LOG_AUTO_PRUNE', $row['forum_name']); - } - - return; -} - -/** -* remove_comments will strip the sql comment lines out of an uploaded sql file -* specifically for mssql and postgres type files in the install.... -*/ -function remove_comments(&$output) -{ - $lines = explode("\n", $output); - $output = ''; - - // try to keep mem. use down - $linecount = sizeof($lines); - - $in_comment = false; - for ($i = 0; $i < $linecount; $i++) - { - if (trim($lines[$i]) == '/*') - { - $in_comment = true; - } - - if (!$in_comment) - { - $output .= $lines[$i] . "\n"; - } - - if (trim($lines[$i]) == '*/') - { - $in_comment = false; - } - } - - unset($lines); - return $output; -} - -/** -* Cache moderators, called whenever permissions are changed via admin_permissions. Changes of username -* and group names must be carried through for the moderators table -*/ -function cache_moderators() -{ - // Remove cached sql results - phpbb::$acm->destroy_sql(MODERATOR_CACHE_TABLE); - - // Clear table - if (phpbb::$db->features['truncate']) - { - phpbb::$db->sql_query('TRUNCATE TABLE ' . MODERATOR_CACHE_TABLE); - } - else - { - phpbb::$db->sql_query('DELETE FROM ' . MODERATOR_CACHE_TABLE); - } - - // We add moderators who have forum moderator permissions without an explicit ACL_NEVER setting - $hold_ary = $ug_id_ary = $sql_ary = array(); - - // Grab all users having moderative options... - $hold_ary = phpbb::$acl->acl_user_raw_data(false, 'm_%', false); - - // Add users? - if (sizeof($hold_ary)) - { - // At least one moderative option warrants a display - $ug_id_ary = array_keys($hold_ary); - - // Remove users who have group memberships with DENY moderator permissions - $sql = phpbb::$db->sql_build_query('SELECT', array( - 'SELECT' => 'a.forum_id, ug.user_id', - - 'FROM' => array( - ACL_OPTIONS_TABLE => 'o', - USER_GROUP_TABLE => 'ug', - ACL_GROUPS_TABLE => 'a' - ), - - 'LEFT_JOIN' => array( - array( - 'FROM' => array(ACL_ROLES_DATA_TABLE => 'r'), - 'ON' => 'a.auth_role_id = r.role_id' - ) - ), - - 'WHERE' => '(o.auth_option_id = a.auth_option_id OR o.auth_option_id = r.auth_option_id) - AND ((a.auth_setting = ' . phpbb::ACL_NEVER . ' AND r.auth_setting IS NULL) - OR r.auth_setting = ' . phpbb::ACL_NEVER . ') - AND a.group_id = ug.group_id - AND ' . phpbb::$db->sql_in_set('ug.user_id', $ug_id_ary) . " - AND ug.user_pending = 0 - AND o.auth_option " . phpbb::$db->sql_like_expression('m_' . phpbb::$db->any_char), - )); - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if (isset($hold_ary[$row['user_id']][$row['forum_id']])) - { - unset($hold_ary[$row['user_id']][$row['forum_id']]); - } - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($hold_ary)) - { - // Get usernames... - $sql = 'SELECT user_id, username - FROM ' . USERS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('user_id', array_keys($hold_ary)); - $result = phpbb::$db->sql_query($sql); - - $usernames_ary = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $usernames_ary[$row['user_id']] = $row['username']; - } - - foreach ($hold_ary as $user_id => $forum_id_ary) - { - // Do not continue if user does not exist - if (!isset($usernames_ary[$user_id])) - { - continue; - } - - foreach ($forum_id_ary as $forum_id => $auth_ary) - { - $sql_ary[] = array( - 'forum_id' => (int) $forum_id, - 'user_id' => (int) $user_id, - 'username' => (string) $usernames_ary[$user_id], - 'group_id' => 0, - 'group_name' => '' - ); - } - } - } - } - - // Now to the groups... - $hold_ary = phpbb::$acl->acl_group_raw_data(false, 'm_%', false); - - if (sizeof($hold_ary)) - { - $ug_id_ary = array_keys($hold_ary); - - // Make sure not hidden or special groups are involved... - $sql = 'SELECT group_name, group_id, group_type - FROM ' . GROUPS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('group_id', $ug_id_ary); - $result = phpbb::$db->sql_query($sql); - - $groupnames_ary = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($row['group_type'] == GROUP_HIDDEN || $row['group_type'] == GROUP_SPECIAL) - { - unset($hold_ary[$row['group_id']]); - } - - $groupnames_ary[$row['group_id']] = $row['group_name']; - } - phpbb::$db->sql_freeresult($result); - - foreach ($hold_ary as $group_id => $forum_id_ary) - { - // If there is no group, we do not assign it... - if (!isset($groupnames_ary[$group_id])) - { - continue; - } - - foreach ($forum_id_ary as $forum_id => $auth_ary) - { - $flag = false; - foreach ($auth_ary as $auth_option => $setting) - { - // Make sure at least one ACL_YES option is set... - if ($setting == phpbb::ACL_YES) - { - $flag = true; - break; - } - } - - if (!$flag) - { - continue; - } - - $sql_ary[] = array( - 'forum_id' => (int) $forum_id, - 'user_id' => 0, - 'username' => '', - 'group_id' => (int) $group_id, - 'group_name' => (string) $groupnames_ary[$group_id] - ); - } - } - } - - phpbb::$db->sql_multi_insert(MODERATOR_CACHE_TABLE, $sql_ary); -} - -/** -* View log -*/ -function view_log($mode, &$log, &$log_count, $limit = 0, $offset = 0, $forum_id = 0, $topic_id = 0, $user_id = 0, $limit_days = 0, $sort_by = 'l.log_time DESC') -{ - $topic_id_list = $reportee_id_list = $is_auth = $is_mod = array(); - - $profile_url = (defined('IN_ADMIN')) ? phpbb::$url->append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, 'i=users&mode=overview') : phpbb::$url->append_sid('memberlist', 'mode=viewprofile'); - - switch ($mode) - { - case 'admin': - $log_type = LOG_ADMIN; - $sql_forum = ''; - break; - - case 'mod': - $log_type = LOG_MOD; - - if ($topic_id) - { - $sql_forum = 'AND l.topic_id = ' . intval($topic_id); - } - else if (is_array($forum_id)) - { - $sql_forum = 'AND ' . phpbb::$db->sql_in_set('l.forum_id', array_map('intval', $forum_id)); - } - else - { - $sql_forum = ($forum_id) ? 'AND l.forum_id = ' . intval($forum_id) : ''; - } - break; - - case 'user': - $log_type = LOG_USERS; - $sql_forum = 'AND l.reportee_id = ' . (int) $user_id; - break; - - case 'users': - $log_type = LOG_USERS; - $sql_forum = ''; - break; - - case 'critical': - $log_type = LOG_CRITICAL; - $sql_forum = ''; - break; - - default: - return; - } - - $sql = "SELECT l.*, u.username, u.username_clean, u.user_colour - FROM " . LOG_TABLE . " l, " . USERS_TABLE . " u - WHERE l.log_type = $log_type - AND u.user_id = l.user_id - " . (($limit_days) ? "AND l.log_time >= $limit_days" : '') . " - $sql_forum - ORDER BY $sort_by"; - $result = phpbb::$db->sql_query_limit($sql, $limit, $offset); - - $i = 0; - $log = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($row['topic_id']) - { - $topic_id_list[] = $row['topic_id']; - } - - if ($row['reportee_id']) - { - $reportee_id_list[] = $row['reportee_id']; - } - - $log[$i] = array( - 'id' => $row['log_id'], - - 'reportee_id' => $row['reportee_id'], - 'reportee_username' => '', - 'reportee_username_full'=> '', - - 'user_id' => $row['user_id'], - 'username' => $row['username'], - 'username_full' => get_username_string('full', $row['user_id'], $row['username'], $row['user_colour'], false, $profile_url), - - 'ip' => $row['log_ip'], - 'time' => $row['log_time'], - 'forum_id' => $row['forum_id'], - 'topic_id' => $row['topic_id'], - - 'viewforum' => ($row['forum_id'] && phpbb::$acl->acl_get('f_read', $row['forum_id'])) ? phpbb::$url->append_sid('viewforum', 'f=' . $row['forum_id']) : false, - 'action' => (isset(phpbb::$user->lang[$row['log_operation']])) ? phpbb::$user->lang[$row['log_operation']] : '{' . ucfirst(str_replace('_', ' ', $row['log_operation'])) . '}', - ); - - if (!empty($row['log_data'])) - { - $log_data_ary = unserialize($row['log_data']); - - if (isset(phpbb::$user->lang[$row['log_operation']])) - { - // Check if there are more occurrences of % than arguments, if there are we fill out the arguments array - // It doesn't matter if we add more arguments than placeholders - if ((substr_count($log[$i]['action'], '%') - sizeof($log_data_ary)) > 0) - { - $log_data_ary = array_merge($log_data_ary, array_fill(0, substr_count($log[$i]['action'], '%') - sizeof($log_data_ary), '')); - } - - $log[$i]['action'] = vsprintf($log[$i]['action'], $log_data_ary); - - // If within the admin panel we do not censor text out - if (defined('IN_ADMIN')) - { - $log[$i]['action'] = bbcode_nl2br($log[$i]['action']); - } - else - { - $log[$i]['action'] = bbcode_nl2br(censor_text($log[$i]['action'])); - } - } - else - { - $log[$i]['action'] .= '<br />' . implode('', $log_data_ary); - } - - /* Apply make_clickable... has to be seen if it is for good. :/ - // Seems to be not for the moment, reconsider later... - $log[$i]['action'] = make_clickable($log[$i]['action']); - */ - } - - $i++; - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($topic_id_list)) - { - $topic_id_list = array_unique($topic_id_list); - - // This query is not really needed if move_topics() updates the forum_id field, - // although it's also used to determine if the topic still exists in the database - $sql = 'SELECT topic_id, forum_id - FROM ' . TOPICS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('topic_id', array_map('intval', $topic_id_list)); - $result = phpbb::$db->sql_query($sql); - - $default_forum_id = 0; - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if (!$row['forum_id']) - { - if (phpbb::$acl->acl_getf_global('f_read')) - { - if (!$default_forum_id) - { - $sql = 'SELECT forum_id - FROM ' . FORUMS_TABLE . ' - WHERE forum_type = ' . FORUM_POST; - $f_result = phpbb::$db->sql_query_limit($sql, 1); - $default_forum_id = (int) phpbb::$db->sql_fetchfield('forum_id', $f_result); - phpbb::$db->sql_freeresult($f_result); - } - - $is_auth[$row['topic_id']] = $default_forum_id; - } - } - else - { - if (phpbb::$acl->acl_get('f_read', $row['forum_id'])) - { - $is_auth[$row['topic_id']] = $row['forum_id']; - } - } - - if (phpbb::$acl->acl_gets('a_', 'm_', $row['forum_id'])) - { - $is_mod[$row['topic_id']] = $row['forum_id']; - } - } - phpbb::$db->sql_freeresult($result); - - foreach ($log as $key => $row) - { - $log[$key]['viewtopic'] = (isset($is_auth[$row['topic_id']])) ? phpbb::$url->append_sid('viewtopic', 'f=' . $is_auth[$row['topic_id']] . '&t=' . $row['topic_id']) : false; - $log[$key]['viewlogs'] = (isset($is_mod[$row['topic_id']])) ? phpbb::$url->append_sid('mcp', 'i=logs&mode=topic_logs&t=' . $row['topic_id'], true, phpbb::$user->session_id) : false; - } - } - - if (sizeof($reportee_id_list)) - { - $reportee_id_list = array_unique($reportee_id_list); - $reportee_names_list = array(); - - $sql = 'SELECT user_id, username, user_colour - FROM ' . USERS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('user_id', $reportee_id_list); - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $reportee_names_list[$row['user_id']] = $row; - } - phpbb::$db->sql_freeresult($result); - - foreach ($log as $key => $row) - { - if (!isset($reportee_names_list[$row['reportee_id']])) - { - continue; - } - - $log[$key]['reportee_username'] = $reportee_names_list[$row['reportee_id']]['username']; - $log[$key]['reportee_username_full'] = get_username_string('full', $row['reportee_id'], $reportee_names_list[$row['reportee_id']]['username'], $reportee_names_list[$row['reportee_id']]['user_colour'], false, $profile_url); - } - } - - $sql = 'SELECT COUNT(l.log_id) AS total_entries - FROM ' . LOG_TABLE . " l - WHERE l.log_type = $log_type - AND l.log_time >= $limit_days - $sql_forum"; - $result = phpbb::$db->sql_query($sql); - $log_count = (int) phpbb::$db->sql_fetchfield('total_entries'); - phpbb::$db->sql_freeresult($result); - - return; -} - -/** -* Update foes - remove moderators and administrators from foe lists... -*/ -function update_foes($group_id = false, $user_id = false) -{ - // update foes for some user - if (is_array($user_id) && sizeof($user_id)) - { - $sql = 'DELETE FROM ' . ZEBRA_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('zebra_id', $user_id) . ' - AND foe = 1'; - phpbb::$db->sql_query($sql); - return; - } - - // update foes for some group - if (is_array($group_id) && sizeof($group_id)) - { - // Grab group settings... - $sql = phpbb::$db->sql_build_query('SELECT', array( - 'SELECT' => 'a.group_id', - - 'FROM' => array( - ACL_OPTIONS_TABLE => 'ao', - ACL_GROUPS_TABLE => 'a' - ), - - 'LEFT_JOIN' => array( - array( - 'FROM' => array(ACL_ROLES_DATA_TABLE => 'r'), - 'ON' => 'a.auth_role_id = r.role_id' - ), - ), - - 'WHERE' => '(ao.auth_option_id = a.auth_option_id OR ao.auth_option_id = r.auth_option_id) - AND ' . phpbb::$db->sql_in_set('a.group_id', $group_id) . " - AND ao.auth_option IN ('a_', 'm_')", - - 'GROUP_BY' => 'a.group_id' - )); - $result = phpbb::$db->sql_query($sql); - - $groups = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $groups[] = (int) $row['group_id']; - } - phpbb::$db->sql_freeresult($result); - - if (!sizeof($groups)) - { - return; - } - - if (phpbb::$db->features['multi_table_deletion']) - { - $sql = 'DELETE FROM' . ZEBRA_TABLE . ' z - USING ' . USER_GROUP_TABLE . ' ug - WHERE z.zebra_id = ug.user_id - AND z.foe = 1 - AND ' . phpbb::$db->sql_in_set('ug.group_id', $groups); - phpbb::$db->sql_query($sql); - } - else - { - $sql = 'SELECT user_id - FROM ' . USER_GROUP_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('group_id', $groups); - $result = phpbb::$db->sql_query($sql); - - $users = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $users[] = (int) $row['user_id']; - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($users)) - { - $sql = 'DELETE FROM ' . ZEBRA_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('zebra_id', $users) . ' - AND foe = 1'; - phpbb::$db->sql_query($sql); - } - } - - return; - } - - // update foes for everyone - $perms = array(); - foreach (phpbb::$acl->acl_get_list(false, array('a_', 'm_'), false) as $forum_id => $forum_ary) - { - foreach ($forum_ary as $auth_option => $user_ary) - { - $perms = array_merge($perms, $user_ary); - } - } - - if (sizeof($perms)) - { - $sql = 'DELETE FROM ' . ZEBRA_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('zebra_id', array_unique($perms)) . ' - AND foe = 1'; - phpbb::$db->sql_query($sql); - } - unset($perms); -} - -/** -* Lists inactive users -*/ -function view_inactive_users(&$users, &$user_count, $limit = 0, $offset = 0, $limit_days = 0, $sort_by = 'user_inactive_time DESC') -{ - $sql = 'SELECT COUNT(user_id) AS user_count - FROM ' . USERS_TABLE . ' - WHERE user_type = ' . phpbb::USER_INACTIVE . - (($limit_days) ? " AND user_inactive_time >= $limit_days" : ''); - $result = phpbb::$db->sql_query($sql); - $user_count = (int) phpbb::$db->sql_fetchfield('user_count'); - phpbb::$db->sql_freeresult($result); - - if ($offset >= $user_count) - { - $offset = ($offset - $limit < 0) ? 0 : $offset - $limit; - } - - $sql = 'SELECT user_id, username, user_regdate, user_lastvisit, user_inactive_time, user_inactive_reason - FROM ' . USERS_TABLE . ' - WHERE user_type = ' . phpbb::USER_INACTIVE . - (($limit_days) ? " AND user_inactive_time >= $limit_days" : '') . " - ORDER BY $sort_by"; - $result = phpbb::$db->sql_query_limit($sql, $limit, $offset); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $row['inactive_reason'] = phpbb::$user->lang['INACTIVE_REASON_UNKNOWN']; - switch ($row['user_inactive_reason']) - { - case INACTIVE_REGISTER: - $row['inactive_reason'] = phpbb::$user->lang['INACTIVE_REASON_REGISTER']; - break; - - case INACTIVE_PROFILE: - $row['inactive_reason'] = phpbb::$user->lang['INACTIVE_REASON_PROFILE']; - break; - - case INACTIVE_MANUAL: - $row['inactive_reason'] = phpbb::$user->lang['INACTIVE_REASON_MANUAL']; - break; - - case INACTIVE_REMIND: - $row['inactive_reason'] = phpbb::$user->lang['INACTIVE_REASON_REMIND']; - break; - } - - $users[] = $row; - } - - return $offset; -} - -/** -* Lists warned users -*/ -function view_warned_users(&$users, &$user_count, $limit = 0, $offset = 0, $limit_days = 0, $sort_by = 'user_warnings DESC') -{ - $sql = 'SELECT user_id, username, user_colour, user_warnings, user_last_warning - FROM ' . USERS_TABLE . ' - WHERE user_warnings > 0 - ' . (($limit_days) ? "AND user_last_warning >= $limit_days" : '') . " - ORDER BY $sort_by"; - $result = phpbb::$db->sql_query_limit($sql, $limit, $offset); - $users = phpbb::$db->sql_fetchrowset($result); - phpbb::$db->sql_freeresult($result); - - $sql = 'SELECT count(user_id) AS user_count - FROM ' . USERS_TABLE . ' - WHERE user_warnings > 0 - ' . (($limit_days) ? "AND user_last_warning >= $limit_days" : ''); - $result = phpbb::$db->sql_query($sql); - $user_count = (int) phpbb::$db->sql_fetchfield('user_count'); - phpbb::$db->sql_freeresult($result); - - return; -} - -/** -* Get database size -*/ -function get_database_size() -{ - $database_size = false; - - // This code is heavily influenced by a similar routine in phpMyAdmin 2.2.0 - switch (phpbb::$db->dbms_type) - { - case 'mysql': - $sql = 'SELECT VERSION() AS mysql_version'; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ($row) - { - $version = $row['mysql_version']; - - if (preg_match('#(3\.23|[45]\.)#', $version)) - { - $db_name = (preg_match('#^(?:3\.23\.(?:[6-9]|[1-9]{2}))|[45]\.#', $version)) ? "`" . phpbb::$db->dbname . "`" : phpbb::$db->dbname; - - $sql = 'SHOW TABLE STATUS - FROM ' . $db_name; - $result = phpbb::$db->sql_query($sql, 7200); - - $database_size = 0; - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ((isset($row['Type']) && $row['Type'] != 'MRG_MyISAM') || (isset($row['Engine']) && ($row['Engine'] == 'MyISAM' || $row['Engine'] == 'InnoDB'))) - { - if (phpbb::$base_config['table_prefix'] != '') - { - if (strpos($row['Name'], phpbb::$base_config['table_prefix']) !== false) - { - $database_size += $row['Data_length'] + $row['Index_length']; - } - } - else - { - $database_size += $row['Data_length'] + $row['Index_length']; - } - } - } - phpbb::$db->sql_freeresult($result); - } - } - break; - - case 'firebird': - global $dbname; - - // if it on the local machine, we can get lucky - if (file_exists($dbname)) - { - $database_size = filesize($dbname); - } - - break; - - case 'sqlite': - global $dbhost; - - if (file_exists($dbhost)) - { - $database_size = filesize($dbhost); - } - - break; - - case 'mssql': - $sql = 'SELECT ((SUM(size) * 8.0) * 1024.0) as dbsize - FROM sysfiles'; - $result = phpbb::$db->sql_query($sql, 7200); - $database_size = ($row = phpbb::$db->sql_fetchrow($result)) ? $row['dbsize'] : false; - phpbb::$db->sql_freeresult($result); - break; - - case 'postgres': - $sql = "SELECT proname - FROM pg_proc - WHERE proname = 'pg_database_size'"; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ($row['proname'] == 'pg_database_size') - { - $database = phpbb::$db->dbname; - if (strpos($database, '.') !== false) - { - list($database, ) = explode('.', $database); - } - - $sql = "SELECT oid - FROM pg_database - WHERE datname = '$database'"; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - $oid = $row['oid']; - - $sql = 'SELECT pg_database_size(' . $oid . ') as size'; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - $database_size = $row['size']; - } - break; - - case 'oracle': - $sql = 'SELECT SUM(bytes) as dbsize - FROM user_segments'; - $result = phpbb::$db->sql_query($sql, 7200); - $database_size = ($row = phpbb::$db->sql_fetchrow($result)) ? $row['dbsize'] : false; - phpbb::$db->sql_freeresult($result); - break; - } - - $database_size = ($database_size !== false) ? get_formatted_filesize($database_size) : phpbb::$user->lang['NOT_AVAILABLE']; - - return $database_size; -} - -/** -* Retrieve contents from remotely stored file -*/ -function get_remote_file($host, $directory, $filename, &$errstr, &$errno, $port = 80, $timeout = 10) -{ - if ($fsock = @fsockopen($host, $port, $errno, $errstr, $timeout)) - { - @fputs($fsock, "GET $directory/$filename HTTP/1.1\r\n"); - @fputs($fsock, "HOST: $host\r\n"); - @fputs($fsock, "Connection: close\r\n\r\n"); - - $file_info = ''; - $get_info = false; - - while (!@feof($fsock)) - { - if ($get_info) - { - $file_info .= @fread($fsock, 1024); - } - else - { - $line = @fgets($fsock, 1024); - if ($line == "\r\n") - { - $get_info = true; - } - else if (stripos($line, '404 not found') !== false) - { - $errstr = phpbb::$user->lang['FILE_NOT_FOUND'] . ': ' . $filename; - return false; - } - } - } - @fclose($fsock); - } - else - { - if ($errstr) - { - $errstr = utf8_convert_message($errstr); - return false; - } - else - { - $errstr = phpbb::$user->lang['FSOCK_DISABLED']; - return false; - } - } - - return $file_info; -} - -/** -* Tidy Warnings -* Remove all warnings which have now expired from the database -* The duration of a warning can be defined by the administrator -* This only removes the warning and reduces the associated count, -* it does not remove the user note recording the contents of the warning -*/ -function tidy_warnings() -{ - $expire_date = time() - (phpbb::$config['warnings_expire_days'] * 86400); - $warning_list = $user_list = array(); - - $sql = 'SELECT * FROM ' . WARNINGS_TABLE . " - WHERE warning_time < $expire_date"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $warning_list[] = $row['warning_id']; - $user_list[$row['user_id']] = isset($user_list[$row['user_id']]) ? ++$user_list[$row['user_id']] : 1; - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($warning_list)) - { - phpbb::$db->sql_transaction('begin'); - - $sql = 'DELETE FROM ' . WARNINGS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('warning_id', $warning_list); - phpbb::$db->sql_query($sql); - - foreach ($user_list as $user_id => $value) - { - $sql = 'UPDATE ' . USERS_TABLE . " SET user_warnings = user_warnings - $value - WHERE user_id = $user_id"; - phpbb::$db->sql_query($sql); - } - - phpbb::$db->sql_transaction('commit'); - } - - set_config('warnings_last_gc', time(), true); -} - -/** -* Tidy database, doing some maintanance tasks -*/ -function tidy_database() -{ - // Here we check permission consistency - - // Sometimes, it can happen permission tables having forums listed which do not exist - $sql = 'SELECT forum_id - FROM ' . FORUMS_TABLE; - $result = phpbb::$db->sql_query($sql); - - $forum_ids = array(0); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $forum_ids[] = $row['forum_id']; - } - phpbb::$db->sql_freeresult($result); - - // Delete those rows from the acl tables not having listed the forums above - $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('forum_id', $forum_ids, true); - phpbb::$db->sql_query($sql); - - $sql = 'DELETE FROM ' . ACL_USERS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('forum_id', $forum_ids, true); - phpbb::$db->sql_query($sql); - - set_config('database_last_gc', time(), true); -} - -/** -* Add permission language - this will make sure custom files will be included -*/ -function add_permission_language() -{ - // First of all, our own file. We need to include it as the first file because it presets all relevant variables. - phpbb::$user->add_lang('acp/permissions_phpbb'); - - $files_to_add = array(); - - // Now search in acp and mods folder for permissions_ files. - foreach (array('acp/', 'mods/') as $path) - { - $dh = @opendir(phpbb::$user->lang_path . phpbb::$user->lang_name . '/' . $path); - - if ($dh) - { - while (($file = readdir($dh)) !== false) - { - if ($file !== 'permissions_phpbb.' . PHP_EXT && strpos($file, 'permissions_') === 0 && substr($file, -(strlen(PHP_EXT) + 1)) === '.' . PHP_EXT) - { - $files_to_add[] = $path . substr($file, 0, -(strlen(PHP_EXT) + 1)); - } - } - closedir($dh); - } - } - - if (!sizeof($files_to_add)) - { - return false; - } - - phpbb::$user->add_lang($files_to_add); - return true; -} - -/** -* Upload files or let the user download them as appropriate -*/ -function process_transfer($module_url, $update_list, $new_location, $download_filename) -{ - // todo: add $s_hidden_fields as a parameter to this function - $s_hidden_fields = ''; - - if (request_var('download', false)) - { - $use_method = request_var('use_method', ''); - $methods = array('.tar'); - - $available_methods = array('.tar.gz' => 'zlib', '.tar.bz2' => 'bz2', '.zip' => 'zlib'); - foreach ($available_methods as $type => $module) - { - if (!@extension_loaded($module)) - { - continue; - } - - $methods[] = $type; - } - - // Let the user decide in which format he wants to have the pack - if (!$use_method) - { - $radio_buttons = ''; - foreach ($methods as $method) - { - $radio_buttons .= '<label><input type="radio"' . ((!$radio_buttons) ? ' id="use_method"' : '') . ' class="radio" value="' . $method . '" name="use_method" /> ' . $method . '</label>'; - } - - phpbb::$template->assign_vars(array( - 'S_DOWNLOAD_FILES' => true, - 'U_ACTION' => append_sid($module_url), - 'RADIO_BUTTONS' => $radio_buttons, - 'S_HIDDEN_FIELDS' => $s_hidden_fields) - ); - - // To ease the update process create a file location map - $script_path = (phpbb::$config['force_server_vars']) ? ((phpbb::$config['script_path'] == '/') ? '/' : phpbb::$config['script_path'] . '/') : phpbb::$user->page['root_script_path']; - - foreach ($update_list as $status => $files) - { - if ($status == 'up_to_date' || $status == 'no_update' || $status == 'status') - { - continue; - } - - foreach ($files as $file_struct) - { - phpbb::$template->assign_block_vars('location', array( - 'SOURCE' => htmlspecialchars($file_struct['filename']), - 'DESTINATION' => $script_path . htmlspecialchars($file_struct['filename']), - )); - } - } - return 'SELECT_DOWNLOAD_FORMAT'; - } - - if (!in_array($use_method, $methods)) - { - $use_method = '.tar'; - } - - $update_mode = 'download'; - } - else - { - // Choose FTP, if not available use fsock... - $method = basename(request_var('method', '')); - $submit = phpbb_request::is_set_post('update'); - $test_ftp_connection = request_var('test_connection', ''); - - if (!$method || !class_exists($method)) - { - $method = 'ftp'; - $methods = transfer::methods(); - - if (!in_array('ftp', $methods)) - { - $method = $methods[0]; - } - } - - $test_connection = false; - if ($test_ftp_connection || $submit) - { - $transfer = new $method(request_var('host', ''), request_var('username', ''), request_var('password', ''), request_var('root_path', ''), request_var('port', ''), request_var('timeout', '')); - $test_connection = $transfer->open_session(); - - // Make sure that the directory is correct by checking for the existence of common.php - if ($test_connection === true) - { - // Check for common.php file - if (!$transfer->file_exists(PHPBB_ROOT_PATH, 'common.' . PHP_EXT)) - { - $test_connection = 'ERR_WRONG_PATH_TO_PHPBB'; - } - } - - $transfer->close_session(); - - // Make sure the login details are correct before continuing - if ($submit && $test_connection !== true) - { - $submit = false; - $test_ftp_connection = true; - } - } - - $s_hidden_fields .= build_hidden_fields(array('method' => $method)); - - if (!$submit) - { - if (!class_exists($method)) - { - trigger_error('Method does not exist.', E_USER_ERROR); - } - - $requested_data = call_user_func(array($method, 'data')); - foreach ($requested_data as $data => $default) - { - phpbb::$template->assign_block_vars('data', array( - 'DATA' => $data, - 'NAME' => phpbb::$user->lang[strtoupper($method . '_' . $data)], - 'EXPLAIN' => phpbb::$user->lang[strtoupper($method . '_' . $data) . '_EXPLAIN'], - 'DEFAULT' => (request_var($data, false)) ? request_var($data, '') : $default - )); - } - - phpbb::$template->assign_vars(array( - 'S_CONNECTION_SUCCESS' => ($test_ftp_connection && $test_connection === true) ? true : false, - 'S_CONNECTION_FAILED' => ($test_ftp_connection && $test_connection !== true) ? true : false, - 'ERROR_MSG' => ($test_ftp_connection && $test_connection !== true) ? phpbb::$user->lang[$test_connection] : '', - - 'S_FTP_UPLOAD' => true, - 'UPLOAD_METHOD' => $method, - 'U_ACTION' => $module_url, - 'U_DOWNLOAD_METHOD' => $module_url . '&download=1', - 'S_HIDDEN_FIELDS' => $s_hidden_fields, - )); - - return 'SELECT_FTP_SETTINGS'; - } - - $update_mode = 'upload'; - } - - // Now init the connection - if ($update_mode == 'download') - { - // Now update the installation or download the archive... - $archive_filename = $download_filename . '_' . time() . '_' . unique_id(); - - if ($use_method == '.zip') - { - $compress = new compress_zip('w', PHPBB_ROOT_PATH . 'store/' . $archive_filename . $use_method); - } - else - { - $compress = new compress_tar('w', PHPBB_ROOT_PATH . 'store/' . $archive_filename . $use_method, $use_method); - } - } - else - { - $transfer = new $method(request_var('host', ''), request_var('username', ''), request_var('password', ''), request_var('root_path', ''), request_var('port', ''), request_var('timeout', '')); - $transfer->open_session(); - } - - // Ok, go through the update list and do the operations based on their status - foreach ($update_list as $status => $files) - { - if (!is_array($files)) - { - continue; - } - - foreach ($files as $file_struct) - { - $original_filename = ($file_struct['custom']) ? $file_struct['original'] : $file_struct['filename']; - - switch ($status) - { - case 'new': - case 'new_conflict': - case 'not_modified': - - if ($update_mode == 'download') - { - $compress->add_custom_file($new_location . $original_filename, $file_struct['filename']); - } - else - { - if ($status != 'new') - { - $transfer->rename($file_struct['filename'], $file_struct['filename'] . '.bak'); - } - - // New directory too? - $dirname = dirname($file_struct['filename']); - - if ($dirname && !file_exists(PHPBB_ROOT_PATH . $dirname)) - { - $transfer->make_dir($dirname); - } - - $transfer->copy_file($new_location . $original_filename, $file_struct['filename']); - } - break; - - case 'modified': - - $contents = base64_decode($cache->get($file_list[$file_struct['filename']])); - - if ($update_mode == 'download') - { - $compress->add_data($contents, $file_struct['filename']); - } - else - { - // @todo add option to specify if a backup file should be created? - $transfer->rename($file_struct['filename'], $file_struct['filename'] . '.bak'); - $transfer->write_file($file_struct['filename'], $contents); - } - break; - - case 'conflict': - - $contents = base64_decode($cache->get($file_list[$file_struct['filename']])); - - if ($update_mode == 'download') - { - $compress->add_data($contents, $file_struct['filename']); - } - else - { - $transfer->rename($file_struct['filename'], $file_struct['filename'] . '.bak'); - $transfer->write_file($file_struct['filename'], $contents); - } - break; - } - } - } - - if ($update_mode == 'download') - { - $compress->close(); - - $compress->download($archive_filename, $download_filename); - @unlink(PHPBB_ROOT_PATH . 'store/' . $archive_filename . $use_method); - - exit; - } - else - { - $transfer->close_session(); - - phpbb::$template->assign_var('S_UPLOAD_SUCCESS', true); - return; - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/functions_compress.php b/phpBB/includes/functions_compress.php deleted file mode 100644 index eebc82b9d0..0000000000 --- a/phpBB/includes/functions_compress.php +++ /dev/null @@ -1,712 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Class for handling archives (compression/decompression) -* @package phpBB3 -*/ -class compress -{ - protected $fp = 0; - - /** - * Add file to archive - */ - public function add_file($src, $src_rm_prefix = '', $src_add_prefix = '', $skip_files = '') - { - $skip_files = explode(',', $skip_files); - - // Remove rm prefix from src path - $src_path = ($src_rm_prefix) ? preg_replace('#^(' . preg_quote($src_rm_prefix, '#') . ')#', '', $src) : $src; - // Add src prefix - $src_path = ($src_add_prefix) ? ($src_add_prefix . ((substr($src_add_prefix, -1) != '/') ? '/' : '') . $src_path) : $src_path; - // Remove initial "/" if present - $src_path = (substr($src_path, 0, 1) == '/') ? substr($src_path, 1) : $src_path; - - if (is_file(PHPBB_ROOT_PATH . $src)) - { - $this->data($src_path, file_get_contents(PHPBB_ROOT_PATH . $src), false, stat(PHPBB_ROOT_PATH . $src)); - } - else if (is_dir(PHPBB_ROOT_PATH . $src)) - { - // Clean up path, add closing / if not present - $src_path = ($src_path && substr($src_path, -1) != '/') ? $src_path . '/' : $src_path; - - $filelist = array(); - $filelist = filelist(PHPBB_ROOT_PATH . $src, '', '*'); - krsort($filelist); - - if ($src_path) - { - $this->data($src_path, '', true, stat(PHPBB_ROOT_PATH . $src)); - } - - foreach ($filelist as $path => $file_ary) - { - if ($path) - { - // Same as for src_path - $path = (substr($path, 0, 1) == '/') ? substr($path, 1) : $path; - $path = ($path && substr($path, -1) != '/') ? $path . '/' : $path; - - $this->data("$src_path$path", '', true, stat(PHPBB_ROOT_PATH . $src . $path)); - } - - foreach ($file_ary as $file) - { - if (in_array($path . $file, $skip_files)) - { - continue; - } - - $this->data("$src_path$path$file", file_get_contents(PHPBB_ROOT_PATH . $src . $path . $file), false, stat(PHPBB_ROOT_PATH . $src . $path . $file)); - } - } - } - - return true; - } - - /** - * Add custom file (the filepath will not be adjusted) - */ - public function add_custom_file($src, $filename) - { - $this->data($filename, file_get_contents($src), false, stat($src)); - return true; - } - - /** - * Add file data - */ - public function add_data($src, $name) - { - $stat = array(); - $stat[2] = 436; //384 - $stat[4] = $stat[5] = 0; - $stat[7] = strlen($src); - $stat[9] = time(); - $this->data($name, $src, false, $stat); - return true; - } - - /** - * Return available methods - */ - public static function methods() - { - $methods = array('.tar'); - $available_methods = array('.tar.gz' => 'zlib', '.tar.bz2' => 'bz2', '.zip' => 'zlib'); - - foreach ($available_methods as $type => $module) - { - if (!@extension_loaded($module)) - { - continue; - } - $methods[] = $type; - } - - return $methods; - } -} - -/** -* Zip creation class from phpMyAdmin 2.3.0 (c) Tobias Ratschiller, Olivier Müller, Loïc Chapeaux, -* Marc Delisle, http://www.phpmyadmin.net/ -* -* Zip extraction function by Alexandre Tedeschi, alexandrebr at gmail dot com -* -* Modified extensively by psoTFX and DavidMJ, (c) phpBB Group, 2003 -* -* Based on work by Eric Mueller and Denis125 -* Official ZIP file format: http://www.pkware.com/appnote.txt -* -* @package phpBB3 -*/ -class compress_zip extends compress -{ - private $datasec = array(); - private $ctrl_dir = array(); - const eof_cdh = "\x50\x4b\x05\x06\x00\x00\x00\x00"; - - private $old_offset = 0; - private $datasec_len = 0; - - /** - * Constructor - */ - function __construct($mode, $file) - { - return $this->fp = @fopen($file, $mode . 'b'); - } - - /** - * Convert unix to dos time - */ - private static function unix_to_dos_time($time) - { - $timearray = (!$time) ? getdate() : getdate($time); - - if ($timearray['year'] < 1980) - { - $timearray['year'] = 1980; - $timearray['mon'] = $timearray['mday'] = 1; - $timearray['hours'] = $timearray['minutes'] = $timearray['seconds'] = 0; - } - - return (($timearray['year'] - 1980) << 25) | ($timearray['mon'] << 21) | ($timearray['mday'] << 16) | ($timearray['hours'] << 11) | ($timearray['minutes'] << 5) | ($timearray['seconds'] >> 1); - } - - /** - * Extract archive - */ - public function extract($dst) - { - // Loop the file, looking for files and folders - $dd_try = false; - rewind($this->fp); - - while (!feof($this->fp)) - { - // Check if the signature is valid... - $signature = fread($this->fp, 4); - - switch ($signature) - { - // 'Local File Header' - case "\x50\x4b\x03\x04": - // Lets get everything we need. - // We don't store the version needed to extract, the general purpose bit flag or the date and time fields - $data = unpack("@4/vc_method/@10/Vcrc/Vc_size/Vuc_size/vname_len/vextra_field", fread($this->fp, 26)); - $file_name = fread($this->fp, $data['name_len']); // filename - - if ($data['extra_field']) - { - fread($this->fp, $data['extra_field']); // extra field - } - - $target_filename = "$dst$file_name"; - - if (!$data['uc_size'] && !$data['crc'] && substr($file_name, -1, 1) == '/') - { - if (!is_dir($target_filename)) - { - $str = ''; - $folders = explode('/', $target_filename); - - // Create and folders and subfolders if they do not exist - foreach ($folders as $folder) - { - $folder = trim($folder); - if (!$folder) - { - continue; - } - - $str = (!empty($str)) ? $str . '/' . $folder : $folder; - if (!is_dir($str)) - { - if (!@mkdir($str, 0777)) - { - trigger_error("Could not create directory $folder"); - } - phpbb::$system->chmod($str, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); - } - } - } - // This is a directory, we are not writting files - continue; - } - else - { - // Some archivers are punks, they don't include folders in their archives! - $str = ''; - $folders = explode('/', pathinfo($target_filename, PATHINFO_DIRNAME)); - - // Create and folders and subfolders if they do not exist - foreach ($folders as $folder) - { - $folder = trim($folder); - if (!$folder) - { - continue; - } - - $str = (!empty($str)) ? $str . '/' . $folder : $folder; - if (!is_dir($str)) - { - if (!@mkdir($str, 0777)) - { - trigger_error("Could not create directory $folder"); - } - phpbb::$system->chmod($str, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); - } - } - } - - if (!$data['uc_size']) - { - $content = ''; - } - else - { - $content = fread($this->fp, $data['c_size']); - } - - $fp = fopen($target_filename, "w"); - - switch ($data['c_method']) - { - case 0: - // Not compressed - fwrite($fp, $content); - break; - - case 8: - // Deflate - fwrite($fp, gzinflate($content, $data['uc_size'])); - break; - - case 12: - // Bzip2 - fwrite($fp, bzdecompress($content)); - break; - } - - fclose($fp); - break; - - // We hit the 'Central Directory Header', we can stop because nothing else in here requires our attention - // or we hit the end of the central directory record, we can safely end the loop as we are totally finished with looking for files and folders - case "\x50\x4b\x01\x02": - // This case should simply never happen.. but it does exist.. - case "\x50\x4b\x05\x06": - break 2; - - // 'Packed to Removable Disk', ignore it and look for the next signature... - case 'PK00': - continue 2; - - // We have encountered a header that is weird. Lets look for better data... - default: - if (!$dd_try) - { - // Unexpected header. Trying to detect wrong placed 'Data Descriptor'; - $dd_try = true; - fseek($this->fp, 8, SEEK_CUR); // Jump over 'crc-32'(4) 'compressed-size'(4), 'uncompressed-size'(4) - continue 2; - } - trigger_error("Unexpected header, ending loop"); - break 2; - } - - $dd_try = false; - } - } - - /** - * Close archive - */ - public function close() - { - // Write out central file directory and footer ... if it exists - if (sizeof($this->ctrl_dir)) - { - fwrite($this->fp, $this->file()); - } - fclose($this->fp); - } - - /** - * Create the structures ... note we assume version made by is MSDOS - */ - protected function data($name, $data, $is_dir = false, $stat) - { - $name = str_replace('\\', '/', $name); - - $hexdtime = pack('V', self::unix_to_dos_time($stat[9])); - - if ($is_dir) - { - $unc_len = $c_len = $crc = 0; - $zdata = ''; - $var_ext = 10; - } - else - { - $unc_len = strlen($data); - $crc = crc32($data); - $zdata = gzdeflate($data); - $c_len = strlen($zdata); - $var_ext = 20; - - // Did we compress? No, then use data as is - if ($c_len >= $unc_len) - { - $zdata = $data; - $c_len = $unc_len; - $var_ext = 10; - } - } - unset($data); - - // If we didn't compress set method to store, else deflate - $c_method = ($c_len == $unc_len) ? "\x00\x00" : "\x08\x00"; - - // Are we a file or a directory? Set archive for file - $attrib = ($is_dir) ? 16 : 32; - - // File Record Header - $fr = "\x50\x4b\x03\x04"; // Local file header 4bytes - $fr .= pack('v', $var_ext); // ver needed to extract 2bytes - $fr .= "\x00\x00"; // gen purpose bit flag 2bytes - $fr .= $c_method; // compression method 2bytes - $fr .= $hexdtime; // last mod time and date 2+2bytes - $fr .= pack('V', $crc); // crc32 4bytes - $fr .= pack('V', $c_len); // compressed filesize 4bytes - $fr .= pack('V', $unc_len); // uncompressed filesize 4bytes - $fr .= pack('v', strlen($name));// length of filename 2bytes - - $fr .= pack('v', 0); // extra field length 2bytes - $fr .= $name; - $fr .= $zdata; - unset($zdata); - - $this->datasec_len += strlen($fr); - - // Add data to file ... by writing data out incrementally we save some memory - fwrite($this->fp, $fr); - unset($fr); - - // Central Directory Header - $cdrec = "\x50\x4b\x01\x02"; // header 4bytes - $cdrec .= "\x00\x00"; // version made by - $cdrec .= pack('v', $var_ext); // version needed to extract - $cdrec .= "\x00\x00"; // gen purpose bit flag - $cdrec .= $c_method; // compression method - $cdrec .= $hexdtime; // last mod time & date - $cdrec .= pack('V', $crc); // crc32 - $cdrec .= pack('V', $c_len); // compressed filesize - $cdrec .= pack('V', $unc_len); // uncompressed filesize - $cdrec .= pack('v', strlen($name)); // length of filename - $cdrec .= pack('v', 0); // extra field length - $cdrec .= pack('v', 0); // file comment length - $cdrec .= pack('v', 0); // disk number start - $cdrec .= pack('v', 0); // internal file attributes - $cdrec .= pack('V', $attrib); // external file attributes - $cdrec .= pack('V', $this->old_offset); // relative offset of local header - $cdrec .= $name; - - // Save to central directory - $this->ctrl_dir[] = $cdrec; - - $this->old_offset = $this->datasec_len; - } - - /** - * file - */ - private function file() - { - $ctrldir = implode('', $this->ctrl_dir); - - return $ctrldir . self::eof_cdh . - pack('v', sizeof($this->ctrl_dir)) . // total # of entries "on this disk" - pack('v', sizeof($this->ctrl_dir)) . // total # of entries overall - pack('V', strlen($ctrldir)) . // size of central dir - pack('V', $this->datasec_len) . // offset to start of central dir - "\x00\x00"; // .zip file comment length - } - - /** - * Download archive - */ - public function download($filename, $download_name = false) - { - if ($download_name === false) - { - $download_name = $filename; - } - - $mimetype = 'application/zip'; - - header('Pragma: no-cache'); - header("Content-Type: $mimetype; name=\"$download_name.zip\""); - header("Content-disposition: attachment; filename=$download_name.zip"); - - $fp = @fopen(PHPBB_ROOT_PATH . "store/$filename.zip", 'rb'); - if ($fp) - { - while ($buffer = fread($fp, 1024)) - { - echo $buffer; - } - fclose($fp); - } - } -} - -/** -* Tar/tar.gz compression routine -* Header/checksum creation derived from tarfile.pl, (c) Tom Horsley, 1994 -* -* @package phpBB3 -*/ -class compress_tar extends compress -{ - private $isgz = false; - private $isbz = false; - private $filename = ''; - private $mode = ''; - private $type = ''; - private $wrote = false; - - /** - * Constructor - */ - function __construct($mode, $file, $type = '') - { - $type = (!$type) ? $file : $type; - $this->isgz = (strpos($type, '.tar.gz') !== false || strpos($type, '.tgz') !== false) ? true : false; - $this->isbz = (strpos($type, '.tar.bz2') !== false) ? true : false; - - $this->mode = &$mode; - $this->file = &$file; - $this->type = &$type; - $this->open(); - } - - /** - * Extract archive - */ - public function extract($dst) - { - $fzread = ($this->isbz && function_exists('bzread')) ? 'bzread' : (($this->isgz && @extension_loaded('zlib')) ? 'gzread' : 'fread'); - - // Run through the file and grab directory entries - while ($buffer = $fzread($this->fp, 512)) - { - $tmp = unpack('A6magic', substr($buffer, 257, 6)); - - if (trim($tmp['magic']) == 'ustar') - { - $tmp = unpack('A100name', $buffer); - $filename = trim($tmp['name']); - - $tmp = unpack('Atype', substr($buffer, 156, 1)); - $filetype = (int) trim($tmp['type']); - - $tmp = unpack('A12size', substr($buffer, 124, 12)); - $filesize = octdec((int) trim($tmp['size'])); - - $target_filename = "$dst$filename"; - - if ($filetype == 5) - { - if (!is_dir($target_filename)) - { - $str = ''; - $folders = explode('/', $target_filename); - - // Create and folders and subfolders if they do not exist - foreach ($folders as $folder) - { - $folder = trim($folder); - if (!$folder) - { - continue; - } - - $str = (!empty($str)) ? $str . '/' . $folder : $folder; - if (!is_dir($str)) - { - if (!@mkdir($str, 0777)) - { - trigger_error("Could not create directory $folder"); - } - phpbb::$system->chmod($str, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); - } - } - } - } - else if ($filesize >= 0 && ($filetype == 0 || $filetype == "\0")) - { - // Some archivers are punks, they don't properly order the folders in their archives! - $str = ''; - $folders = explode('/', pathinfo($target_filename, PATHINFO_DIRNAME)); - - // Create and folders and subfolders if they do not exist - foreach ($folders as $folder) - { - $folder = trim($folder); - if (!$folder) - { - continue; - } - - $str = (!empty($str)) ? $str . '/' . $folder : $folder; - if (!is_dir($str)) - { - if (!@mkdir($str, 0777)) - { - trigger_error("Could not create directory $folder"); - } - phpbb::$system->chmod($str, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); - } - } - - // Write out the files - if (!($fp = fopen($target_filename, 'wb'))) - { - trigger_error("Couldn't create file $filename"); - } - phpbb::$system->chmod($target_filename, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); - - // Grab the file contents - fwrite($fp, ($filesize) ? $fzread($this->fp, ($filesize + 511) &~ 511) : '', $filesize); - fclose($fp); - } - } - } - } - - /** - * Close archive - */ - public function close() - { - $fzclose = ($this->isbz && function_exists('bzclose')) ? 'bzclose' : (($this->isgz && @extension_loaded('zlib')) ? 'gzclose' : 'fclose'); - - if ($this->wrote) - { - $fzwrite = ($this->isbz && function_exists('bzwrite')) ? 'bzwrite' : (($this->isgz && @extension_loaded('zlib')) ? 'gzwrite' : 'fwrite'); - - // The end of a tar archive ends in two records of all NULLs (1024 bytes of \0) - $fzwrite($this->fp, str_repeat("\0", 1024)); - } - - $fzclose($this->fp); - } - - /** - * Create the structures - */ - protected function data($name, $data, $is_dir = false, $stat) - { - $this->wrote = true; - $fzwrite = ($this->isbz && function_exists('bzwrite')) ? 'bzwrite' : (($this->isgz && @extension_loaded('zlib')) ? 'gzwrite' : 'fwrite'); - - $typeflag = ($is_dir) ? '5' : ''; - - // This is the header data, it contains all the info we know about the file or folder that we are about to archive - $header = ''; - $header .= pack('a100', $name); // file name - $header .= pack('a8', sprintf("%07o", $stat[2])); // file mode - $header .= pack('a8', sprintf("%07o", $stat[4])); // owner id - $header .= pack('a8', sprintf("%07o", $stat[5])); // group id - $header .= pack('a12', sprintf("%011o", $stat[7])); // file size - $header .= pack('a12', sprintf("%011o", $stat[9])); // last mod time - - // Checksum - $checksum = 0; - for ($i = 0; $i < 148; $i++) - { - $checksum += ord($header[$i]); - } - - // We precompute the rest of the hash, this saves us time in the loop and allows us to insert our hash without resorting to string functions - $checksum += 2415 + (($is_dir) ? 53 : 0); - - $header .= pack('a8', sprintf("%07o", $checksum)); // checksum - $header .= pack('a1', $typeflag); // link indicator - $header .= pack('a100', ''); // name of linked file - $header .= pack('a6', 'ustar'); // ustar indicator - $header .= pack('a2', '00'); // ustar version - $header .= pack('a32', 'Unknown'); // owner name - $header .= pack('a32', 'Unknown'); // group name - $header .= pack('a8', ''); // device major number - $header .= pack('a8', ''); // device minor number - $header .= pack('a155', ''); // filename prefix - $header .= pack('a12', ''); // end - - // This writes the entire file in one shot. Header, followed by data and then null padded to a multiple of 512 - $fzwrite($this->fp, $header . (($stat[7] !== 0 && !$is_dir) ? $data . str_repeat("\0", (($stat[7] + 511) &~ 511) - $stat[7]) : '')); - unset($data); - } - - /** - * Open archive - */ - private function open() - { - $fzopen = ($this->isbz && function_exists('bzopen')) ? 'bzopen' : (($this->isgz && @extension_loaded('zlib')) ? 'gzopen' : 'fopen'); - $this->fp = @$fzopen($this->file, $this->mode . (($fzopen == 'bzopen') ? '' : 'b') . (($fzopen == 'gzopen') ? '9' : '')); - - if (!$this->fp) - { - trigger_error('Unable to open file ' . $this->file . ' [' . $fzopen . ' - ' . $this->mode . 'b]'); - } - } - - /** - * Download archive - */ - public function download($filename, $download_name = false) - { - if ($download_name === false) - { - $download_name = $filename; - } - - switch ($this->type) - { - case '.tar': - $mimetype = 'application/x-tar'; - break; - - case '.tar.gz': - $mimetype = 'application/x-gzip'; - break; - - case '.tar.bz2': - $mimetype = 'application/x-bzip2'; - break; - - default: - $mimetype = 'application/octet-stream'; - break; - } - - header('Pragma: no-cache'); - header("Content-Type: $mimetype; name=\"$download_name$this->type\""); - header("Content-disposition: attachment; filename=$download_name$this->type"); - - $fp = @fopen(PHPBB_ROOT_PATH . "store/$filename$this->type", 'rb'); - if ($fp) - { - while ($buffer = fread($fp, 1024)) - { - echo $buffer; - } - fclose($fp); - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/functions_content.php b/phpBB/includes/functions_content.php deleted file mode 100644 index 64c915b7dd..0000000000 --- a/phpBB/includes/functions_content.php +++ /dev/null @@ -1,1317 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* gen_sort_selects() -* make_jumpbox() -* bump_topic_allowed() -* get_context() -* decode_message() -* strip_bbcode() -* generate_text_for_display() -* generate_text_for_storage() -* generate_text_for_edit() -* make_clickable_callback() -* make_clickable() -* censor_text() -* bbcode_nl2br() -* smiley_text() -* parse_attachments() -* extension_allowed() -* truncate_string() -* get_username_string() -* class bitfield -*/ - -/** -* Generate sort selection fields -* @todo phpbb_api::new('sort') -*/ -function gen_sort_selects(&$limit_days, &$sort_by_text, &$sort_days, &$sort_key, &$sort_dir, &$s_limit_days, &$s_sort_key, &$s_sort_dir, &$u_sort_param, $def_st = false, $def_sk = false, $def_sd = false) -{ - $sort_dir_text = array('a' => phpbb::$user->lang['ASCENDING'], 'd' => phpbb::$user->lang['DESCENDING']); - - $sorts = array( - 'st' => array( - 'key' => 'sort_days', - 'default' => $def_st, - 'options' => $limit_days, - 'output' => &$s_limit_days, - ), - - 'sk' => array( - 'key' => 'sort_key', - 'default' => $def_sk, - 'options' => $sort_by_text, - 'output' => &$s_sort_key, - ), - - 'sd' => array( - 'key' => 'sort_dir', - 'default' => $def_sd, - 'options' => $sort_dir_text, - 'output' => &$s_sort_dir, - ), - ); - $u_sort_param = ''; - - foreach ($sorts as $name => $sort_ary) - { - $key = $sort_ary['key']; - $selected = $$sort_ary['key']; - - // Check if the key is selectable. If not, we reset to the default or first key found. - // This ensures the values are always valid. We also set $sort_dir/sort_key/etc. to the - // correct value, else the protection is void. ;) - if (!isset($sort_ary['options'][$selected])) - { - if ($sort_ary['default'] !== false) - { - $selected = $$key = $sort_ary['default']; - } - else - { - @reset($sort_ary['options']); - $selected = $$key = key($sort_ary['options']); - } - } - - $sort_ary['output'] = '<select name="' . $name . '" id="' . $name . '">'; - foreach ($sort_ary['options'] as $option => $text) - { - $sort_ary['output'] .= '<option value="' . $option . '"' . (($selected == $option) ? ' selected="selected"' : '') . '>' . $text . '</option>'; - } - $sort_ary['output'] .= '</select>'; - - $u_sort_param .= ($selected !== $sort_ary['default']) ? ((strlen($u_sort_param)) ? '&' : '') . "{$name}={$selected}" : ''; - } - - return; -} - -/** -* Generate Jumpbox -*/ -function make_jumpbox($action, $forum_id = false, $select_all = false, $acl_list = false, $force_display = false) -{ - // We only return if the jumpbox is not forced to be displayed (in case it is needed for functionality) - if (!phpbb::$config['load_jumpbox'] && $force_display === false) - { - return; - } - - $sql = 'SELECT forum_id, forum_name, parent_id, forum_type, left_id, right_id - FROM ' . FORUMS_TABLE . ' - ORDER BY left_id ASC'; - $result = phpbb::$db->sql_query($sql, 600); - - $right = $padding = 0; - $padding_store = array('0' => 0); - $display_jumpbox = false; - $iteration = 0; - - // Sometimes it could happen that forums will be displayed here not be displayed within the index page - // This is the result of forums not displayed at index, having list permissions and a parent of a forum with no permissions. - // If this happens, the padding could be "broken" - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($row['left_id'] < $right) - { - $padding++; - $padding_store[$row['parent_id']] = $padding; - } - else if ($row['left_id'] > $right + 1) - { - // Ok, if the $padding_store for this parent is empty there is something wrong. For now we will skip over it. - // @todo digging deep to find out "how" this can happen. - $padding = (isset($padding_store[$row['parent_id']])) ? $padding_store[$row['parent_id']] : $padding; - } - - $right = $row['right_id']; - - if ($row['forum_type'] == FORUM_CAT && ($row['left_id'] + 1 == $row['right_id'])) - { - // Non-postable forum with no subforums, don't display - continue; - } - - if (!phpbb::$acl->acl_get('f_list', $row['forum_id'])) - { - // if the user does not have permissions to list this forum skip - continue; - } - - if ($acl_list && !phpbb::$acl->acl_gets($acl_list, $row['forum_id'])) - { - continue; - } - - if (!$display_jumpbox) - { - phpbb::$template->assign_block_vars('jumpbox_forums', array( - 'FORUM_ID' => ($select_all) ? 0 : -1, - 'FORUM_NAME' => ($select_all) ? phpbb::$user->lang['ALL_FORUMS'] : phpbb::$user->lang['SELECT_FORUM'], - 'S_FORUM_COUNT' => $iteration) - ); - - $iteration++; - $display_jumpbox = true; - } - - phpbb::$template->assign_block_vars('jumpbox_forums', array( - 'FORUM_ID' => $row['forum_id'], - 'FORUM_NAME' => $row['forum_name'], - 'SELECTED' => ($row['forum_id'] == $forum_id) ? ' selected="selected"' : '', - 'S_FORUM_COUNT' => $iteration, - 'S_IS_CAT' => ($row['forum_type'] == FORUM_CAT) ? true : false, - 'S_IS_LINK' => ($row['forum_type'] == FORUM_LINK) ? true : false, - 'S_IS_POST' => ($row['forum_type'] == FORUM_POST) ? true : false) - ); - - for ($i = 0; $i < $padding; $i++) - { - phpbb::$template->assign_block_vars('jumpbox_forums.level', array()); - } - $iteration++; - } - phpbb::$db->sql_freeresult($result); - unset($padding_store); - - phpbb::$template->assign_vars(array( - 'S_DISPLAY_JUMPBOX' => $display_jumpbox, - 'S_JUMPBOX_ACTION' => phpbb::$url->append_sid($action), - )); - - return; -} - -/** -* Bump Topic Check - used by posting and viewtopic -*/ -function bump_topic_allowed($forum_id, $topic_bumped, $last_post_time, $topic_poster, $last_topic_poster) -{ - // Check permission and make sure the last post was not already bumped - if (!phpbb::$acl->acl_get('f_bump', $forum_id) || $topic_bumped) - { - return false; - } - - // Check bump time range, is the user really allowed to bump the topic at this time? - $bump_time = (phpbb::$config['bump_type'] == 'm') ? phpbb::$config['bump_interval'] * 60 : ((phpbb::$config['bump_type'] == 'h') ? phpbb::$config['bump_interval'] * 3600 : phpbb::$config['bump_interval'] * 86400); - - // Check bump time - if ($last_post_time + $bump_time > time()) - { - return false; - } - - // Check bumper, only topic poster and last poster are allowed to bump - if ($topic_poster != phpbb::$user->data['user_id'] && $last_topic_poster != phpbb::$user->data['user_id']) - { - return false; - } - - // A bump time of 0 will completely disable the bump feature... not intended but might be useful. - return $bump_time; -} - -/** -* Generates a text with approx. the specified length which contains the specified words and their context -* -* @param string $text The full text from which context shall be extracted -* @param string $words An array of words which should be contained in the result, has to be a valid part of a PCRE pattern (escape with preg_quote!) -* @param int $length The desired length of the resulting text, however the result might be shorter or longer than this value -* -* @return string Context of the specified words separated by "..." -*/ -function get_context($text, $words, $length = 400) -{ - // first replace all whitespaces with single spaces - $text = preg_replace('/ +/', ' ', strtr($text, "\t\n\r\x0C ", ' ')); - - $word_indizes = array(); - if (sizeof($words)) - { - $match = ''; - // find the starting indizes of all words - foreach ($words as $word) - { - if ($word) - { - if (preg_match('#(?:[^\w]|^)(' . $word . ')(?:[^\w]|$)#i', $text, $match)) - { - $pos = utf8_strpos($text, $match[1]); - if ($pos !== false) - { - $word_indizes[] = $pos; - } - } - } - } - unset($match); - - if (sizeof($word_indizes)) - { - $word_indizes = array_unique($word_indizes); - sort($word_indizes); - - $wordnum = sizeof($word_indizes); - // number of characters on the right and left side of each word - $sequence_length = (int) ($length / (2 * $wordnum)) - 2; - $final_text = ''; - $word = $j = 0; - $final_text_index = -1; - - // cycle through every character in the original text - for ($i = $word_indizes[$word], $n = utf8_strlen($text); $i < $n; $i++) - { - // if the current position is the start of one of the words then append $sequence_length characters to the final text - if (isset($word_indizes[$word]) && ($i == $word_indizes[$word])) - { - if ($final_text_index < $i - $sequence_length - 1) - { - $final_text .= '... ' . preg_replace('#^([^ ]*)#', '', utf8_substr($text, $i - $sequence_length, $sequence_length)); - } - else - { - // if the final text is already nearer to the current word than $sequence_length we only append the text - // from its current index on and distribute the unused length to all other sequenes - $sequence_length += (int) (($final_text_index - $i + $sequence_length + 1) / (2 * $wordnum)); - $final_text .= utf8_substr($text, $final_text_index + 1, $i - $final_text_index - 1); - } - $final_text_index = $i - 1; - - // add the following characters to the final text (see below) - $word++; - $j = 1; - } - - if ($j > 0) - { - // add the character to the final text and increment the sequence counter - $final_text .= utf8_substr($text, $i, 1); - $final_text_index++; - $j++; - - // if this is a whitespace then check whether we are done with this sequence - if (utf8_substr($text, $i, 1) == ' ') - { - // only check whether we have to exit the context generation completely if we haven't already reached the end anyway - if ($i + 4 < $n) - { - if (($j > $sequence_length && $word >= $wordnum) || utf8_strlen($final_text) > $length) - { - $final_text .= ' ...'; - break; - } - } - else - { - // make sure the text really reaches the end - $j -= 4; - } - - // stop context generation and wait for the next word - if ($j > $sequence_length) - { - $j = 0; - } - } - } - } - return $final_text; - } - } - - if (!sizeof($words) || !sizeof($word_indizes)) - { - return (utf8_strlen($text) >= $length + 3) ? utf8_substr($text, 0, $length) . '...' : $text; - } -} - -/** -* Decode text whereby text is coming from the db and expected to be pre-parsed content -* We are placing this outside of the message parser because we are often in need of it... -*/ -function decode_message(&$message, $bbcode_uid = '') -{ - if ($bbcode_uid) - { - $match = array('<br />', "[/*:m:$bbcode_uid]", ":u:$bbcode_uid", ":o:$bbcode_uid", ":$bbcode_uid"); - $replace = array("\n", '', '', '', ''); - } - else - { - $match = array('<br />'); - $replace = array("\n"); - } - - $message = str_replace($match, $replace, $message); - - $match = get_preg_expression('bbcode_htm'); - $replace = array('\1', '\1', '\2', '\1', '', ''); - - $message = preg_replace($match, $replace, $message); -} - -/** -* Strips all bbcode from a text and returns the plain content -*/ -function strip_bbcode(&$text, $uid = '') -{ - if (!$uid) - { - $uid = '[0-9a-z]{5,}'; - } - - $text = preg_replace("#\[\/?[a-z0-9\*\+\-]+(?:=(?:".*"|[^\]]*))?(?::[a-z])?(\:$uid)\]#", ' ', $text); - - $match = get_preg_expression('bbcode_htm'); - $replace = array('\1', '\1', '\2', '\1', '', ''); - - $text = preg_replace($match, $replace, $text); -} - -/** -* For display of custom parsed text on user-facing pages -* Expects $text to be the value directly from the database (stored value) -*/ -function generate_text_for_display($text, $uid, $bitfield, $flags) -{ - static $bbcode; - - if (!$text) - { - return ''; - } - - $text = censor_text($text); - - // Parse bbcode if bbcode uid stored and bbcode enabled - if ($uid && ($flags & OPTION_FLAG_BBCODE)) - { - if (!class_exists('bbcode')) - { - include(PHPBB_ROOT_PATH . 'includes/bbcode.' . PHP_EXT); - } - - if (empty($bbcode)) - { - $bbcode = new bbcode($bitfield); - } - else - { - $bbcode->bbcode($bitfield); - } - - $bbcode->bbcode_second_pass($text, $uid); - } - - $text = bbcode_nl2br($text); - $text = smiley_text($text, !($flags & OPTION_FLAG_SMILIES)); - - return $text; -} - -/** -* For parsing custom parsed text to be stored within the database. -* This function additionally returns the uid and bitfield that needs to be stored. -* Expects $text to be the value directly from request_var() and in it's non-parsed form -*/ -function generate_text_for_storage(&$text, &$uid, &$bitfield, &$flags, $allow_bbcode = false, $allow_urls = false, $allow_smilies = false) -{ - $uid = $bitfield = ''; - $flags = (($allow_bbcode) ? OPTION_FLAG_BBCODE : 0) + (($allow_smilies) ? OPTION_FLAG_SMILIES : 0) + (($allow_urls) ? OPTION_FLAG_LINKS : 0); - - if (!$text) - { - return; - } - - if (!class_exists('parse_message')) - { - include(PHPBB_ROOT_PATH . 'includes/message_parser.' . PHP_EXT); - } - - $message_parser = new parse_message($text); - $message_parser->parse($allow_bbcode, $allow_urls, $allow_smilies); - - $text = $message_parser->message; - $uid = $message_parser->bbcode_uid; - - // If the bbcode_bitfield is empty, there is no need for the uid to be stored. - if (!$message_parser->bbcode_bitfield) - { - $uid = ''; - } - - $bitfield = $message_parser->bbcode_bitfield; - - return; -} - -/** -* For decoding custom parsed text for edits as well as extracting the flags -* Expects $text to be the value directly from the database (pre-parsed content) -*/ -function generate_text_for_edit($text, $uid, $flags) -{ - decode_message($text, $uid); - - return array( - 'allow_bbcode' => ($flags & OPTION_FLAG_BBCODE) ? 1 : 0, - 'allow_smilies' => ($flags & OPTION_FLAG_SMILIES) ? 1 : 0, - 'allow_urls' => ($flags & OPTION_FLAG_LINKS) ? 1 : 0, - 'text' => $text - ); -} - -/** -* A subroutine of make_clickable used with preg_replace -* It places correct HTML around an url, shortens the displayed text -* and makes sure no entities are inside URLs -*/ -function make_clickable_callback($type, $whitespace, $url, $relative_url, $class) -{ - $orig_url = $url; - $orig_relative = $relative_url; - $append = ''; - $url = htmlspecialchars_decode($url); - $relative_url = htmlspecialchars_decode($relative_url); - - // make sure no HTML entities were matched - $chars = array('<', '>', '"'); - $split = false; - - foreach ($chars as $char) - { - $next_split = strpos($url, $char); - if ($next_split !== false) - { - $split = ($split !== false) ? min($split, $next_split) : $next_split; - } - } - - if ($split !== false) - { - // an HTML entity was found, so the URL has to end before it - $append = substr($url, $split) . $relative_url; - $url = substr($url, 0, $split); - $relative_url = ''; - } - else if ($relative_url) - { - // same for $relative_url - $split = false; - foreach ($chars as $char) - { - $next_split = strpos($relative_url, $char); - if ($next_split !== false) - { - $split = ($split !== false) ? min($split, $next_split) : $next_split; - } - } - - if ($split !== false) - { - $append = substr($relative_url, $split); - $relative_url = substr($relative_url, 0, $split); - } - } - - // if the last character of the url is a punctuation mark, exclude it from the url - $last_char = ($relative_url) ? $relative_url[strlen($relative_url) - 1] : $url[strlen($url) - 1]; - - switch ($last_char) - { - case '.': - case '?': - case '!': - case ':': - case ',': - $append = $last_char; - if ($relative_url) - { - $relative_url = substr($relative_url, 0, -1); - } - else - { - $url = substr($url, 0, -1); - } - break; - - // set last_char to empty here, so the variable can be used later to - // check whether a character was removed - default: - $last_char = ''; - break; - } - - $short_url = (strlen($url) > 55) ? substr($url, 0, 39) . ' ... ' . substr($url, -10) : $url; - - switch ($type) - { - case MAGIC_URL_LOCAL: - $tag = 'l'; - $relative_url = preg_replace('/[&?]sid=[0-9a-f]{32}$/', '', preg_replace('/([&?])sid=[0-9a-f]{32}&/', '$1', $relative_url)); - $url = $url . '/' . $relative_url; - $text = $relative_url; - - // this url goes to http://domain.tld/path/to/board/ which - // would result in an empty link if treated as local so - // don't touch it and let MAGIC_URL_FULL take care of it. - if (!$relative_url) - { - return $whitespace . $orig_url . '/' . $orig_relative; // slash is taken away by relative url pattern - } - break; - - case MAGIC_URL_FULL: - $tag = 'm'; - $text = $short_url; - break; - - case MAGIC_URL_WWW: - $tag = 'w'; - $url = 'http://' . $url; - $text = $short_url; - break; - - case MAGIC_URL_EMAIL: - $tag = 'e'; - $text = $short_url; - $url = 'mailto:' . $url; - break; - } - - $url = htmlspecialchars($url); - $text = htmlspecialchars($text); - $append = htmlspecialchars($append); - - $html = "$whitespace<!-- $tag --><a$class href=\"$url\">$text</a><!-- $tag -->$append"; - - return $html; -} - -/** -* make_clickable function -* -* Replace magic urls of form http://xxx.xxx., www.xxx. and xxx@xxx.xxx. -* Cuts down displayed size of link if over 50 chars, turns absolute links -* into relative versions when the server/script path matches the link -*/ -function make_clickable($text, $server_url = false, $class = 'postlink') -{ - if ($server_url === false) - { - $server_url = generate_board_url(); - } - - static $magic_url_match; - static $magic_url_replace; - static $static_class; - - if (!is_array($magic_url_match) || $static_class != $class) - { - $static_class = $class; - $class = ($static_class) ? ' class="' . $static_class . '"' : ''; - $local_class = ($static_class) ? ' class="' . $static_class . '-local"' : ''; - - $magic_url_match = $magic_url_replace = array(); - // Be sure to not let the matches cross over. ;) - - // relative urls for this board - $magic_url_match[] = '#(^|[\n\t (>.])(' . preg_quote($server_url, '#') . ')/(' . get_preg_expression('relative_url_inline') . ')#ie'; - $magic_url_replace[] = "make_clickable_callback(MAGIC_URL_LOCAL, '\$1', '\$2', '\$3', '$local_class')"; - - // matches a xxxx://aaaaa.bbb.cccc. ... - $magic_url_match[] = '#(^|[\n\t (>.])(' . get_preg_expression('url_inline') . ')#ie'; - $magic_url_replace[] = "make_clickable_callback(MAGIC_URL_FULL, '\$1', '\$2', '', '$class')"; - - // matches a "www.xxxx.yyyy[/zzzz]" kinda lazy URL thing - $magic_url_match[] = '#(^|[\n\t (>])(' . get_preg_expression('www_url_inline') . ')#ie'; - $magic_url_replace[] = "make_clickable_callback(MAGIC_URL_WWW, '\$1', '\$2', '', '$class')"; - - // matches an email@domain type address at the start of a line, or after a space or after what might be a BBCode. - $magic_url_match[] = '/(^|[\n\t (>])(' . get_preg_expression('email') . ')/ie'; - $magic_url_replace[] = "make_clickable_callback(MAGIC_URL_EMAIL, '\$1', '\$2', '', '')"; - } - - return preg_replace($magic_url_match, $magic_url_replace, $text); -} - -/** -* Censoring -*/ -function censor_text($text) -{ - static $censors; - - // We moved the word censor checks in here because we call this function quite often - and then only need to do the check once - if (!isset($censors) || !is_array($censors)) - { - // We check here if the user is having viewing censors disabled (and also allowed to do so). - if (!phpbb::$user->optionget('viewcensors') && phpbb::$config['allow_nocensors'] && phpbb::$acl->acl_get('u_chgcensors')) - { - $censors = array(); - } - else - { - $censors = phpbb_cache::obtain_word_list(); - } - } - - if (sizeof($censors)) - { - return preg_replace($censors['match'], $censors['replace'], $text); - } - - return $text; -} - -/** -* custom version of nl2br which takes custom BBCodes into account -*/ -function bbcode_nl2br($text) -{ - // custom BBCodes might contain carriage returns so they - // are not converted into <br /> so now revert that - $text = str_replace(array("\n", "\r"), array('<br />', "\n"), $text); - return $text; -} - -/** -* Smiley processing -*/ -function smiley_text($text, $force_option = false) -{ - if ($force_option || !phpbb::$config['allow_smilies'] || !phpbb::$user->optionget('viewsmilies')) - { - return preg_replace('#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/.*? \/><!\-\- s\1 \-\->#', '\1', $text); - } - else - { - return preg_replace('#<!\-\- s(.*?) \-\-><img src="\{SMILIES_PATH\}\/(.*?) \/><!\-\- s\1 \-\->#', '<img src="' . PHPBB_ROOT_PATH . phpbb::$config['smilies_path'] . '/\2 />', $text); - } -} - -/** -* General attachment parsing -* -* @param mixed $forum_id The forum id the attachments are displayed in (false if in private message) -* @param string &$message The post/private message -* @param array &$attachments The attachments to parse for (inline) display. The attachments array will hold templated data after parsing. -* @param array &$update_count The attachment counts to be updated - will be filled -* @param bool $preview If set to true the attachments are parsed for preview. Within preview mode the comments are fetched from the given $attachments array and not fetched from the database. -*/ -function parse_attachments($forum_id, &$message, &$attachments, &$update_count, $preview = false) -{ - if (!sizeof($attachments)) - { - return; - } - - global $extensions; - - // - $compiled_attachments = array(); - - // @todo: do we really need this check? - if (!isset(phpbb::$template->filename['attachment_tpl'])) - { - phpbb::$template->set_filenames(array( - 'attachment_tpl' => 'attachment.html') - ); - } - - if (empty($extensions) || !is_array($extensions)) - { - $extensions = phpbb_cache::obtain_extensions_forum($forum_id); - } - - // Look for missing attachment information... - $attach_ids = array(); - foreach ($attachments as $pos => $attachment) - { - // If is_orphan is set, we need to retrieve the attachments again... - if (!isset($attachment['extension']) && !isset($attachment['physical_filename'])) - { - $attach_ids[(int) $attachment['attach_id']] = $pos; - } - } - - // Grab attachments (security precaution) - if (sizeof($attach_ids)) - { - $new_attachment_data = array(); - - $sql = 'SELECT * - FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('attach_id', array_keys($attach_ids)); - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if (!isset($attach_ids[$row['attach_id']])) - { - continue; - } - - // If we preview attachments we will set some retrieved values here - if ($preview) - { - $row['attach_comment'] = $attachments[$attach_ids[$row['attach_id']]]['attach_comment']; - } - - $new_attachment_data[$attach_ids[$row['attach_id']]] = $row; - } - phpbb::$db->sql_freeresult($result); - - $attachments = $new_attachment_data; - unset($new_attachment_data); - } - - // Sort correctly - if (phpbb::$config['display_order']) - { - // Ascending sort - krsort($attachments); - } - else - { - // Descending sort - ksort($attachments); - } - - foreach ($attachments as $attachment) - { - if (!sizeof($attachment)) - { - continue; - } - - // We need to reset/empty the _file block var, because this function might be called more than once - phpbb::$template->destroy_block_vars('_file'); - - $block_array = array(); - - // Some basics... - $attachment['extension'] = strtolower(trim($attachment['extension'])); - $filename = PHPBB_ROOT_PATH . phpbb::$config['upload_path'] . '/' . basename($attachment['physical_filename']); - $thumbnail_filename = PHPBB_ROOT_PATH . phpbb::$config['upload_path'] . '/thumb_' . basename($attachment['physical_filename']); - - $upload_icon = ''; - - if (isset($extensions[$attachment['extension']])) - { - if (phpbb::$user->img('icon_topic_attach', '') && !$extensions[$attachment['extension']]['upload_icon']) - { - $upload_icon = phpbb::$user->img('icon_topic_attach', ''); - } - else if ($extensions[$attachment['extension']]['upload_icon']) - { - $upload_icon = '<img src="' . PHPBB_ROOT_PATH . phpbb::$config['upload_icons_path'] . '/' . trim($extensions[$attachment['extension']]['upload_icon']) . '" alt="" />'; - } - } - - $filesize = $attachment['filesize']; - $size_lang = ($filesize >= 1048576) ? phpbb::$user->lang['MIB'] : (($filesize >= 1024) ? phpbb::$user->lang['KIB'] : phpbb::$user->lang['BYTES']); - $filesize = get_formatted_filesize($filesize, false); - - $comment = bbcode_nl2br(censor_text($attachment['attach_comment'])); - - $block_array += array( - 'UPLOAD_ICON' => $upload_icon, - 'FILESIZE' => $filesize, - 'SIZE_LANG' => $size_lang, - 'DOWNLOAD_NAME' => basename($attachment['real_filename']), - 'COMMENT' => $comment, - ); - - $denied = false; - - if (!extension_allowed($forum_id, $attachment['extension'], $extensions)) - { - $denied = true; - - $block_array += array( - 'S_DENIED' => true, - 'DENIED_MESSAGE' => phpbb::$user->lang('EXTENSION_DISABLED_AFTER_POSTING', $attachment['extension']), - ); - } - - if (!$denied) - { - $l_downloaded_viewed = $download_link = ''; - $display_cat = $extensions[$attachment['extension']]['display_cat']; - - if ($display_cat == ATTACHMENT_CATEGORY_IMAGE) - { - if ($attachment['thumbnail']) - { - $display_cat = ATTACHMENT_CATEGORY_THUMB; - } - else - { - if (phpbb::$config['img_display_inlined']) - { - if (phpbb::$config['img_link_width'] || phpbb::$config['img_link_height']) - { - $dimension = @getimagesize($filename); - - // If the dimensions could not be determined or the image being 0x0 we display it as a link for safety purposes - if ($dimension === false || empty($dimension[0]) || empty($dimension[1])) - { - $display_cat = ATTACHMENT_CATEGORY_NONE; - } - else - { - $display_cat = ($dimension[0] <= phpbb::$config['img_link_width'] && $dimension[1] <= phpbb::$config['img_link_height']) ? ATTACHMENT_CATEGORY_IMAGE : ATTACHMENT_CATEGORY_NONE; - } - } - } - else - { - $display_cat = ATTACHMENT_CATEGORY_NONE; - } - } - } - - // Make some descisions based on user options being set. - if (($display_cat == ATTACHMENT_CATEGORY_IMAGE || $display_cat == ATTACHMENT_CATEGORY_THUMB) && !phpbb::$user->optionget('viewimg')) - { - $display_cat = ATTACHMENT_CATEGORY_NONE; - } - - if ($display_cat == ATTACHMENT_CATEGORY_FLASH && !phpbb::$user->optionget('viewflash')) - { - $display_cat = ATTACHMENT_CATEGORY_NONE; - } - - $download_link = append_sid('download/file', 'id=' . $attachment['attach_id']); - - switch ($display_cat) - { - // Images - case ATTACHMENT_CATEGORY_IMAGE: - $l_downloaded_viewed = 'VIEWED_COUNT'; - $inline_link = append_sid('download/file', 'id=' . $attachment['attach_id']); - $download_link .= '&mode=view'; - - $block_array += array( - 'S_IMAGE' => true, - 'U_INLINE_LINK' => $inline_link, - ); - - $update_count[] = $attachment['attach_id']; - break; - - // Images, but display Thumbnail - case ATTACHMENT_CATEGORY_THUMB: - $l_downloaded_viewed = 'VIEWED_COUNT'; - $thumbnail_link = append_sid('download/file', 'id=' . $attachment['attach_id'] . '&t=1'); - $download_link .= '&mode=view'; - - $block_array += array( - 'S_THUMBNAIL' => true, - 'THUMB_IMAGE' => $thumbnail_link, - ); - - $update_count[] = $attachment['attach_id']; - break; - - // Windows Media Streams - case ATTACHMENT_CATEGORY_WM: - $l_downloaded_viewed = 'VIEWED_COUNT'; - - // Giving the filename directly because within the wm object all variables are in local context making it impossible - // to validate against a valid session (all params can differ) - // $download_link = $filename; - - $block_array += array( - 'U_FORUM' => generate_board_url(), - 'ATTACH_ID' => $attachment['attach_id'], - 'S_WM_FILE' => true, - ); - - // Viewed/Heared File ... update the download count - $update_count[] = $attachment['attach_id']; - break; - - // Real Media Streams - case ATTACHMENT_CATEGORY_RM: - case ATTACHMENT_CATEGORY_QUICKTIME: - $l_downloaded_viewed = 'VIEWED_COUNT'; - - $block_array += array( - 'S_RM_FILE' => ($display_cat == ATTACHMENT_CATEGORY_RM) ? true : false, - 'S_QUICKTIME_FILE' => ($display_cat == ATTACHMENT_CATEGORY_QUICKTIME) ? true : false, - 'U_FORUM' => generate_board_url(), - 'ATTACH_ID' => $attachment['attach_id'], - ); - - // Viewed/Heared File ... update the download count - $update_count[] = $attachment['attach_id']; - break; - - // Macromedia Flash Files - case ATTACHMENT_CATEGORY_FLASH: - list($width, $height) = @getimagesize($filename); - - $l_downloaded_viewed = 'VIEWED_COUNT'; - - $block_array += array( - 'S_FLASH_FILE' => true, - 'WIDTH' => $width, - 'HEIGHT' => $height, - 'U_VIEW_LINK' => $download_link . '&view=1', - ); - - // Viewed/Heared File ... update the download count - $update_count[] = $attachment['attach_id']; - break; - - default: - $l_downloaded_viewed = 'DOWNLOAD_COUNT'; - - $block_array += array( - 'S_FILE' => true, - ); - break; - } - - $block_array += array( - 'U_DOWNLOAD_LINK' => $download_link, - 'L_DOWNLOAD_COUNT' => phpbb::$user->lang($l_downloaded_viewed, $attachment['download_count']), - ); - } - - phpbb::$template->assign_block_vars('_file', $block_array); - - $compiled_attachments[] = phpbb::$template->assign_display('attachment_tpl'); - } - - $attachments = $compiled_attachments; - unset($compiled_attachments); - - $tpl_size = sizeof($attachments); - - $unset_tpl = array(); - - preg_match_all('#<!\-\- ia([0-9]+) \-\->(.*?)<!\-\- ia\1 \-\->#', $message, $matches, PREG_PATTERN_ORDER); - - $replace = array(); - foreach ($matches[0] as $num => $capture) - { - // Flip index if we are displaying the reverse way - $index = (phpbb::$config['display_order']) ? ($tpl_size-($matches[1][$num] + 1)) : $matches[1][$num]; - - $replace['from'][] = $matches[0][$num]; - $replace['to'][] = (isset($attachments[$index])) ? $attachments[$index] : sprintf(phpbb::$user->lang['MISSING_INLINE_ATTACHMENT'], $matches[2][array_search($index, $matches[1])]); - - $unset_tpl[] = $index; - } - - if (isset($replace['from'])) - { - $message = str_replace($replace['from'], $replace['to'], $message); - } - - $unset_tpl = array_unique($unset_tpl); - - // Needed to let not display the inlined attachments at the end of the post again - foreach ($unset_tpl as $index) - { - unset($attachments[$index]); - } -} - -/** -* Check if extension is allowed to be posted. -* -* @param mixed $forum_id The forum id to check or false if private message -* @param string $extension The extension to check, for example zip. -* @param array &$extensions The extension array holding the information from the cache (will be obtained if empty) -* -* @return bool False if the extension is not allowed to be posted, else true. -*/ -function extension_allowed($forum_id, $extension, &$extensions) -{ - if (empty($extensions)) - { - $extensions = phpbb_cache::obtain_extensions_forum($forum_id); - } - - return (!isset($extensions['_allowed_'][$extension])) ? false : true; -} - -/** -* Truncates string while retaining special characters if going over the max length -* The default max length is 60 at the moment -* The maximum storage length is there to fit the string within the given length. The string may be further truncated due to html entities. -* For example: string given is 'a "quote"' (length: 9), would be a stored as 'a "quote"' (length: 19) -* -* @param string $string The text to truncate to the given length. String is specialchared. -* @param int $max_length Maximum length of string (multibyte character count as 1 char / Html entity count as 1 char) -* @param int $max_store_length Maximum character length of string (multibyte character count as 1 char / Html entity count as entity chars). -* @param bool $allow_reply Allow Re: in front of string -* @param string $append String to be appended -*/ -function truncate_string($string, $max_length = 60, $max_store_length = 255, $allow_reply = true, $append = '') -{ - $chars = array(); - - $strip_reply = false; - $stripped = false; - if ($allow_reply && strpos($string, 'Re: ') === 0) - { - $strip_reply = true; - $string = substr($string, 4); - } - - $_chars = utf8_str_split(htmlspecialchars_decode($string)); - $chars = array_map('utf8_htmlspecialchars', $_chars); - - // Now check the length ;) - if (sizeof($chars) > $max_length) - { - // Cut off the last elements from the array - $string = implode('', array_slice($chars, 0, $max_length - utf8_strlen($append))); - $stripped = true; - } - - // Due to specialchars, we may not be able to store the string... - if (utf8_strlen($string) > $max_store_length) - { - // let's split again, we do not want half-baked strings where entities are split - $_chars = utf8_str_split(htmlspecialchars_decode($string)); - $chars = array_map('utf8_htmlspecialchars', $_chars); - - do - { - array_pop($chars); - $string = implode('', $chars); - } - while (!empty($chars) && utf8_strlen($string) > $max_store_length); - } - - if ($strip_reply) - { - $string = 'Re: ' . $string; - } - - if ($append != '' && $stripped) - { - $string = $string . $append; - } - - return $string; -} - -/** -* Get username details for placing into templates. -* This function caches all modes on first call, except for no_profile - determined by $user_id/$guest_username combination. -* -* @param string $mode Can be profile (for getting an url to the profile), username (for obtaining the username), colour (for obtaining the user colour), full (for obtaining a html string representing a coloured link to the users profile) or no_profile (the same as full but forcing no profile link) -* @param int $user_id The users id -* @param string $username The users name -* @param string $username_colour The users colour -* @param string $guest_username optional parameter to specify the guest username. It will be used in favor of the GUEST language variable then. -* @param string $custom_profile_url optional parameter to specify a profile url. The user id get appended to this url as &u={user_id} -* -* @return string A string consisting of what is wanted based on $mode. -* @author BartVB, Acyd Burn -*/ -function get_username_string($mode, $user_id, $username, $username_colour = '', $guest_username = false, $custom_profile_url = false) -{ - static $_profile_cache; - - // We cache some common variables we need within this function - if (empty($_profile_cache)) - { - $_profile_cache['base_url'] = phpbb::$url->append_sid('memberlist', 'mode=viewprofile&u={USER_ID}'); - $_profile_cache['tpl_noprofile'] = '{USERNAME}'; - $_profile_cache['tpl_noprofile_colour'] = '<span style="color: {USERNAME_COLOUR};" class="username-coloured">{USERNAME}</span>'; - $_profile_cache['tpl_profile'] = '<a href="{PROFILE_URL}">{USERNAME}</a>'; - $_profile_cache['tpl_profile_colour'] = '<a href="{PROFILE_URL}" style="color: {USERNAME_COLOUR};" class="username-coloured">{USERNAME}</a>'; - } - - // This switch makes sure we only run code required for the mode - switch ($mode) - { - case 'full': - case 'no_profile': - case 'colour': - - // Build correct username colour - $username_colour = ($username_colour) ? '#' . $username_colour : ''; - - // Return colour - if ($mode == 'colour') - { - return $username_colour; - } - - // no break; - - case 'username': - - // Build correct username - if ($guest_username === false) - { - $username = ($username) ? $username : phpbb::$user->lang['GUEST']; - } - else - { - $username = ($user_id && $user_id != ANONYMOUS) ? $username : ((!empty($guest_username)) ? $guest_username : phpbb::$user->lang['GUEST']); - } - - // Return username - if ($mode == 'username') - { - return $username; - } - - // no break; - - case 'profile': - - // Build correct profile url - only show if not anonymous and permission to view profile if registered user - // For anonymous the link leads to a login page. - if ($user_id && $user_id != ANONYMOUS && (phpbb::$user->is_guest || phpbb::$acl->acl_get('u_viewprofile'))) - { - $profile_url = ($custom_profile_url !== false) ? $custom_profile_url . '&u=' . (int) $user_id : str_replace(array('={USER_ID}', '=%7BUSER_ID%7D'), '=' . (int) $user_id, $_profile_cache['base_url']); - } - else - { - $profile_url = ''; - } - - // Return profile - if ($mode == 'profile') - { - return $profile_url; - } - - // no break; - } - - if (($mode == 'full' && !$profile_url) || $mode == 'no_profile') - { - return str_replace(array('{USERNAME_COLOUR}', '{USERNAME}'), array($username_colour, $username), (!$username_colour) ? $_profile_cache['tpl_noprofile'] : $_profile_cache['tpl_noprofile_colour']); - } - - return str_replace(array('{PROFILE_URL}', '{USERNAME_COLOUR}', '{USERNAME}'), array($profile_url, $username_colour, $username), (!$username_colour) ? $_profile_cache['tpl_profile'] : $_profile_cache['tpl_profile_colour']); -} - -/** -* @package phpBB3 -*/ -class bitfield -{ - var $data; - - function __construct($bitfield = '') - { - $this->data = base64_decode($bitfield); - } - - /** - */ - function get($n) - { - // Get the ($n / 8)th char - $byte = $n >> 3; - - if (strlen($this->data) >= $byte + 1) - { - $c = $this->data[$byte]; - - // Lookup the ($n % 8)th bit of the byte - $bit = 7 - ($n & 7); - return (bool) (ord($c) & (1 << $bit)); - } - else - { - return false; - } - } - - function set($n) - { - $byte = $n >> 3; - $bit = 7 - ($n & 7); - - if (strlen($this->data) >= $byte + 1) - { - $this->data[$byte] = $this->data[$byte] | chr(1 << $bit); - } - else - { - $this->data .= str_repeat("\0", $byte - strlen($this->data)); - $this->data .= chr(1 << $bit); - } - } - - function clear($n) - { - $byte = $n >> 3; - - if (strlen($this->data) >= $byte + 1) - { - $bit = 7 - ($n & 7); - $this->data[$byte] = $this->data[$byte] &~ chr(1 << $bit); - } - } - - function get_blob() - { - return $this->data; - } - - function get_base64() - { - return base64_encode($this->data); - } - - function get_bin() - { - $bin = ''; - $len = strlen($this->data); - - for ($i = 0; $i < $len; ++$i) - { - $bin .= str_pad(decbin(ord($this->data[$i])), 8, '0', STR_PAD_LEFT); - } - - return $bin; - } - - function get_all_set() - { - return array_keys(array_filter(str_split($this->get_bin()))); - } - - function merge($bitfield) - { - $this->data = $this->data | $bitfield->get_blob(); - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/functions_convert.php b/phpBB/includes/functions_convert.php deleted file mode 100644 index 6e06545b25..0000000000 --- a/phpBB/includes/functions_convert.php +++ /dev/null @@ -1,2446 +0,0 @@ -<?php -/** -* -* @package install -* @version $Id$ -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Default avatar width/height -* @ignore -*/ -define('DEFAULT_AVATAR_X', 80); -define('DEFAULT_AVATAR_Y', 80); - -// Global functions - all functions can be used by convertors - -// SIMPLE FUNCTIONS - -/** -* Return the preceding value -*/ -function dec($var) -{ - return --$var; -} - -/** -* Return the next value -*/ -function inc($var) -{ - return ++$var; -} - -/** -* Return whether the value is positive -*/ -function is_positive($n) -{ - return ($n > 0) ? 1 : 0; -} - -/** -* Boolean inverse of the value -*/ -function not($var) -{ - return ($var) ? 0 : 1; -} - -/** -* Convert a textual value to it's equivalent boolean value -* -* @param string $str String to convert (converts yes, on, y, 1 and true to boolean true) -* @return boolean The equivalent value -*/ -function str_to_bool($str) -{ - $str = strtolower($str); - return ($str == 'yes' || $str == 'on' || $str == 'y' || $str == 'true' || $str == '1') ? true : false; -} - -/** -* Function to mimic php's empty() function (it is the same) -*/ -function is_empty($mixed) -{ - return empty($mixed); -} - -/** -* Convert the name of a user's primary group to the appropriate equivalent phpBB group id -* -* @param string $status The name of the group -* @return int The group_id corresponding to the equivalent group -*/ -function str_to_primary_group($status) -{ - switch (ucfirst(strtolower($status))) - { - case 'Administrator': - return get_group_id('administrators'); - break; - - case 'Super moderator': - case 'Global moderator': - case 'Moderator': - return get_group_id('global_moderators'); - break; - - case 'Guest': - case 'Anonymous': - return get_group_id('guests'); - break; - - default: - return get_group_id('registered'); - break; - } -} - -/** -* Convert a boolean into the appropriate phpBB constant indicating whether the item is locked -*/ -function is_item_locked($bool) -{ - return ($bool) ? ITEM_LOCKED : ITEM_UNLOCKED; -} - -/** -* Convert a value from days to seconds -*/ -function days_to_seconds($days) -{ - return ($days * 86400); -} - -/** -* Determine whether a user is anonymous and return the appropriate new user_id -*/ -function is_user_anonymous($user_id) -{ - return ($user_id > ANONYMOUS) ? $user_id : ANONYMOUS; -} - -/** -* Generate a key value based on existing values -* -* @param int $pad Amount to add to the maximum value -* @return int Key value -*/ -function auto_id($pad = 0) -{ - global $auto_id, $convert_row; - - if (!empty($convert_row['max_id'])) - { - return $convert_row['max_id'] + $pad; - } - - return $auto_id + $pad; -} - -/** -* Convert a boolean into the appropriate phpBB constant indicating whether the user is active -*/ -function set_user_type($user_active) -{ - return ($user_active) ? phpbb::USER_NORMAL : phpbb::USER_INACTIVE; -} - -/** -* Convert a value from minutes to hours -*/ -function minutes_to_hours($minutes) -{ - return ($minutes / 3600); -} - -/** -* Return the group_id for a given group name -*/ -function get_group_id($group_name) -{ - global $db, $group_mapping; - - if (empty($group_mapping)) - { - $sql = 'SELECT group_name, group_id - FROM ' . GROUPS_TABLE; - $result = $db->sql_query($sql); - - $group_mapping = array(); - while ($row = $db->sql_fetchrow($result)) - { - $group_mapping[strtoupper($row['group_name'])] = (int) $row['group_id']; - } - $db->sql_freeresult($result); - } - - if (!sizeof($group_mapping)) - { - add_default_groups(); - return get_group_id($group_name); - } - - if (isset($group_mapping[strtoupper($group_name)])) - { - return $group_mapping[strtoupper($group_name)]; - } - - return $group_mapping['REGISTERED']; -} - -/** -* Generate the email hash stored in the users table -*/ -function gen_email_hash($email) -{ - return (crc32(strtolower($email)) . strlen($email)); -} - -/** -* Convert a boolean into the appropriate phpBB constant indicating whether the topic is locked -*/ -function is_topic_locked($bool) -{ - return (!empty($bool)) ? ITEM_LOCKED : ITEM_UNLOCKED; -} - -/** -* Generate a bbcode_uid value -*/ -function make_uid($timestamp) -{ - static $last_timestamp, $last_uid; - - if (empty($last_timestamp) || $timestamp != $last_timestamp) - { - $last_uid = substr(base_convert(unique_id(), 16, 36), 0, BBCODE_UID_LEN); - } - $last_timestamp = $timestamp; - return $last_uid; -} - - -/** -* Validate a website address -*/ -function validate_website($url) -{ - if ($url === 'http://') - { - return ''; - } - else if (!preg_match('#^[a-z0-9]+://#i', $url) && strlen($url) > 0) - { - return 'http://' . $url; - } - return $url; -} - -/** -* Convert nulls to zeros for fields which allowed a NULL value in the source but not the destination -*/ -function null_to_zero($value) -{ - return ($value === NULL) ? 0 : $value; -} - -/** -* Convert nulls to empty strings for fields which allowed a NULL value in the source but not the destination -*/ -function null_to_str($value) -{ - return ($value === NULL) ? '' : $value; -} - -// EXTENDED FUNCTIONS - -/** -* Get old config value -*/ -function get_config_value($config_name) -{ - static $convert_config; - - if (!isset($convert_config)) - { - $convert_config = get_config(); - } - - if (!isset($convert_config[$config_name])) - { - return false; - } - - return (empty($convert_config[$config_name])) ? '' : $convert_config[$config_name]; -} - -/** -* Convert an IP address from the hexadecimal notation to normal dotted-quad notation -*/ -function decode_ip($int_ip) -{ - if (!$int_ip) - { - return $int_ip; - } - - $hexipbang = explode('.', chunk_split($int_ip, 2, '.')); - - // Any mod changing the way ips are stored? Then we are not able to convert and enter the ip "as is" to not "destroy" anything... - if (sizeof($hexipbang) < 4) - { - return $int_ip; - } - - return hexdec($hexipbang[0]) . '.' . hexdec($hexipbang[1]) . '.' . hexdec($hexipbang[2]) . '.' . hexdec($hexipbang[3]); -} - -/** -* Reverse the encoding of wild-carded bans -*/ -function decode_ban_ip($int_ip) -{ - return str_replace('255', '*', decode_ip($int_ip)); -} - -/** -* Determine the MIME-type of a specified filename -* This does not actually inspect the file, but simply uses the file extension -*/ -function mimetype($filename) -{ - if (!preg_match('/\.([a-z0-9]+)$/i', $filename, $m)) - { - return 'application/octet-stream'; - } - - switch (strtolower($m[1])) - { - case 'zip': return 'application/zip'; - case 'jpeg': return 'image/jpeg'; - case 'jpg': return 'image/jpeg'; - case 'jpe': return 'image/jpeg'; - case 'png': return 'image/png'; - case 'gif': return 'image/gif'; - case 'htm': - case 'html': return 'text/html'; - case 'tif': return 'image/tiff'; - case 'tiff': return 'image/tiff'; - case 'ras': return 'image/x-cmu-raster'; - case 'pnm': return 'image/x-portable-anymap'; - case 'pbm': return 'image/x-portable-bitmap'; - case 'pgm': return 'image/x-portable-graymap'; - case 'ppm': return 'image/x-portable-pixmap'; - case 'rgb': return 'image/x-rgb'; - case 'xbm': return 'image/x-xbitmap'; - case 'xpm': return 'image/x-xpixmap'; - case 'xwd': return 'image/x-xwindowdump'; - case 'z': return 'application/x-compress'; - case 'gtar': return 'application/x-gtar'; - case 'tgz': return 'application/x-gtar'; - case 'gz': return 'application/x-gzip'; - case 'tar': return 'application/x-tar'; - case 'xls': return 'application/excel'; - case 'pdf': return 'application/pdf'; - case 'ppt': return 'application/powerpoint'; - case 'rm': return 'application/vnd.rn-realmedia'; - case 'wma': return 'audio/x-ms-wma'; - case 'swf': return 'application/x-shockwave-flash'; - case 'ief': return 'image/ief'; - case 'doc': - case 'dot': - case 'wrd': return 'application/msword'; - case 'ai': - case 'eps': - case 'ps': return 'application/postscript'; - case 'asc': - case 'txt': - case 'c': - case 'cc': - case 'h': - case 'hh': - case 'cpp': - case 'hpp': - case 'php': - case 'php3': return 'text/plain'; - default: return 'application/octet-stream'; - } -} - -/** -* Obtain the dimensions of all remotely hosted avatars -* This should only be called from execute_last -* There can be significant network overhead if there are a large number of remote avatars -* @todo Look at the option of allowing the user to decide whether this is called or to force the dimensions -*/ -function remote_avatar_dims() -{ - global $db; - - $sql = 'SELECT user_id, user_avatar - FROM ' . USERS_TABLE . ' - WHERE user_avatar_type = ' . AVATAR_REMOTE; - $result = $db->sql_query($sql); - - $remote_avatars = array(); - while ($row = $db->sql_fetchrow($result)) - { - $remote_avatars[(int) $row['user_id']] = $row['user_avatar']; - } - $db->sql_freeresult($result); - - foreach ($remote_avatars as $user_id => $avatar) - { - $width = (int) get_remote_avatar_dim($avatar, 0); - $height = (int) get_remote_avatar_dim($avatar, 1); - - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_avatar_width = ' . (int) $width . ', user_avatar_height = ' . (int) $height . ' - WHERE user_id = ' . $user_id; - $db->sql_query($sql); - } -} - -function import_avatar_gallery($gallery_name = '', $subdirs_as_galleries = false) -{ - global $convert, $user; - - $relative_path = empty($convert->convertor['source_path_absolute']); - - if (empty($convert->convertor['avatar_gallery_path'])) - { - $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_GALLERY_PATH'], 'import_avatar_gallery()'), __LINE__, __FILE__); - } - - $src_path = relative_base(path($convert->convertor['avatar_gallery_path'], $relative_path), $relative_path); - - if (is_dir($src_path)) - { - // Do not die on failure... safe mode restrictions may be in effect. - copy_dir($convert->convertor['avatar_gallery_path'], path(phpbb::$config['avatar_gallery_path']) . $gallery_name, !$subdirs_as_galleries, false, false, $relative_path); - - // only doing 1 level deep. (ibf 1.x) - // notes: ibf has 2 tiers: directly in the avatar directory for base gallery (handled in the above statement), plus subdirs(handled below). - // recursive subdirs ignored. -- i don't know if other forums support recursive galleries. if they do, this following code could be upgraded to be recursive. - if ($subdirs_as_galleries) - { - $dirlist = array(); - if ($handle = @opendir($src_path)) - { - while ($entry = readdir($handle)) - { - if ($entry[0] == '.' || $entry == 'CVS' || $entry == 'index.htm') - { - continue; - } - - if (is_dir($src_path . $entry)) - { - $dirlist[] = $entry; - } - } - closedir($handle); - } - else if ($dir = @dir($src_path)) - { - while ($entry = $dir->read()) - { - if ($entry[0] == '.' || $entry == 'CVS' || $entry == 'index.htm') - { - continue; - } - - if (is_dir($src_path . $entry)) - { - $dirlist[] = $entry; - } - } - $dir->close(); - } - - for ($i = 0; $i < sizeof($dirlist); ++$i) - { - $dir = $dirlist[$i]; - - // Do not die on failure... safe mode restrictions may be in effect. - copy_dir(path($convert->convertor['avatar_gallery_path'], $relative_path) . $dir, path(phpbb::$config['avatar_gallery_path']) . $dir, true, false, false, $relative_path); - } - } - } -} - -function import_attachment_files($category_name = '') -{ - global $convert, $db, $user; - - $sql = 'SELECT config_value AS upload_path - FROM ' . CONFIG_TABLE . " - WHERE config_name = 'upload_path'"; - $result = $db->sql_query($sql); - phpbb::$config['upload_path'] = $db->sql_fetchfield('upload_path'); - $db->sql_freeresult($result); - - $relative_path = empty($convert->convertor['source_path_absolute']); - - if (empty($convert->convertor['upload_path'])) - { - $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_UPLOAD_DIR'], 'import_attachment_files()'), __LINE__, __FILE__); - } - - if (is_dir(relative_base(path($convert->convertor['upload_path'], $relative_path), $relative_path))) - { - copy_dir($convert->convertor['upload_path'], path(phpbb::$config['upload_path']) . $category_name, true, false, true, $relative_path); - } -} - -function attachment_forum_perms($forum_id) -{ - if (!is_array($forum_id)) - { - $forum_id = array($forum_id); - } - - return serialize($forum_id); -} - -// base64todec function -// -> from php manual? -function base64_unpack($string) -{ - $chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ+-'; - $base = strlen($chars); - - $length = strlen($string); - $number = 0; - - for ($i = 1; $i <= $length; $i++) - { - $pos = $length - $i; - $operand = strpos($chars, substr($string, $pos, 1)); - $exponent = pow($base, $i-1); - $dec_value = $operand * $exponent; - $number += $dec_value; - } - - return $number; -} - -function _import_check($config_var, $source, $use_target) -{ - global $convert; - - $result = array( - 'orig_source' => $source, - 'copied' => false, - 'relative_path' => (empty($convert->convertor['source_path_absolute'])) ? true : false, - ); - - // copy file will prepend PHPBB_ROOT_PATH - $target = phpbb::$config[$config_var] . '/' . basename(($use_target === false) ? $source : $use_target); - - if (!empty($convert->convertor[$config_var]) && strpos($source, $convert->convertor[$config_var]) !== 0) - { - $source = $convert->convertor[$config_var] . $source; - } - - $result['source'] = $source; - - if (file_exists(relative_base($source, $result['relative_path'], __LINE__, __FILE__))) - { - $result['copied'] = copy_file($source, $target, false, false, $result['relative_path']); - } - - if ($result['copied']) - { - $result['target'] = basename($target); - } - else - { - $result['target'] = ($use_target !== false) ? $result['orig_source'] : basename($target); - } - - return $result; -} - -function import_attachment($source, $use_target = false) -{ - if (empty($source)) - { - return ''; - } - - global $convert, $user; - - if (empty($convert->convertor['upload_path'])) - { - $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_UPLOAD_DIR'], 'import_attachment()'), __LINE__, __FILE__); - } - - $result = _import_check('upload_path', $source, $use_target); - - if ($result['copied']) - { - // Thumbnails? - if (is_array($convert->convertor['thumbnails'])) - { - $thumb_dir = $convert->convertor['thumbnails'][0]; - $thumb_prefix = $convert->convertor['thumbnails'][1]; - $thumb_source = $thumb_dir . $thumb_prefix . basename($result['source']); - - if (strpos($thumb_source, $convert->convertor['upload_path']) !== 0) - { - $thumb_source = $convert->convertor['upload_path'] . $thumb_source; - } - $thumb_target = phpbb::$config['upload_path'] . '/thumb_' . $result['target']; - - if (file_exists(relative_base($thumb_source, $result['relative_path'], __LINE__, __FILE__))) - { - copy_file($thumb_source, $thumb_target, false, false, $result['relative_path']); - } - } - } - - return $result['target']; -} - -function import_rank($source, $use_target = false) -{ - if (empty($source)) - { - return ''; - } - - global $convert, $user; - - if (!isset($convert->convertor['ranks_path'])) - { - $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_RANKS_PATH'], 'import_rank()'), __LINE__, __FILE__); - } - - $result = _import_check('ranks_path', $source, $use_target); - return $result['target']; -} - -function import_smiley($source, $use_target = false) -{ - if (empty($source)) - { - return ''; - } - - global $convert, $user; - - if (!isset($convert->convertor['smilies_path'])) - { - $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_SMILIES_PATH'], 'import_smiley()'), __LINE__, __FILE__); - } - - $result = _import_check('smilies_path', $source, $use_target); - return $result['target']; -} - -/* -*/ -function import_avatar($source, $use_target = false, $user_id = false) -{ - if (empty($source) || preg_match('#^https?:#i', $source) || preg_match('#blank\.(gif|png)$#i', $source)) - { - return; - } - - global $convert, $user; - - if (!isset($convert->convertor['avatar_path'])) - { - $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_AVATAR_PATH'], 'import_avatar()'), __LINE__, __FILE__); - } - - if ($use_target === false && $user_id !== false) - { - $use_target = phpbb::$config['avatar_salt'] . '_' . $user_id . '.' . substr(strrchr($source, '.'), 1); - } - - $result = _import_check('avatar_path', $source, $use_target); - - return ((!empty($user_id)) ? $user_id : $use_target) . '.' . substr(strrchr($source, '.'), 1); -} - -/** -* @todo all image dimension functions below (there are a *lot*) should get revisited and converted to one or two functions (no more needed, really). -*/ - -/** -* Calculate the size of the specified image -* Called from the following functions for calculating the size of specific image types -*/ -function get_image_dim($source) -{ - if (empty($source)) - { - return array(0, 0); - } - - global $convert; - - $relative_path = empty($convert->convertor['source_path_absolute']); - - if (file_exists(relative_base($source, $relative_path))) - { - $image = relative_base($source, $relative_path); - return @getimagesize($image); - } - - return false; -} - -/** -* Obtain the width of the specified smilie -*/ -function get_smiley_width($src) -{ - return get_smiley_dim($src, 0); -} - -/** -* Obtain the height of the specified smilie -*/ -function get_smiley_height($src) -{ - return get_smiley_dim($src, 1); -} - -/** -* Obtain the size of the specified smilie (using the cache if possible) and cache the value -*/ -function get_smiley_dim($source, $axis) -{ - if (empty($source)) - { - return 15; - } - - static $smiley_cache = array(); - - if (isset($smiley_cache[$source])) - { - return $smiley_cache[$source][$axis]; - } - - global $convert, $user; - - $orig_source = $source; - - if (!isset($convert->convertor['smilies_path'])) - { - $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_SMILIES_PATH'], 'get_smiley_dim()'), __LINE__, __FILE__); - } - - if (!empty($convert->convertor['smilies_path']) && strpos($source, $convert->convertor['smilies_path']) !== 0) - { - $source = $convert->convertor['smilies_path'] . $source; - } - - $smiley_cache[$orig_source] = get_image_dim($source); - - if (empty($smiley_cache[$orig_source]) || empty($smiley_cache[$orig_source][0]) || empty($smiley_cache[$orig_source][1])) - { - $smiley_cache[$orig_source] = array(15, 15); - return 15; - } - - return $smiley_cache[$orig_source][$axis]; -} - -/** -* Obtain the width of the specified avatar -*/ -function get_avatar_width($src, $func = false, $arg1 = false, $arg2 = false) -{ - return get_avatar_dim($src, 0, $func, $arg1, $arg2); -} - -/** -* Obtain the height of the specified avatar -*/ -function get_avatar_height($src, $func = false, $arg1 = false, $arg2 = false) -{ - return get_avatar_dim($src, 1, $func, $arg1, $arg2); -} - -/** -*/ -function get_avatar_dim($src, $axis, $func = false, $arg1 = false, $arg2 = false) -{ - $avatar_type = AVATAR_UPLOAD; - - if ($func) - { - if ($arg1 || $arg2) - { - $ary = array($arg1); - - if ($arg2) - { - $ary[] = $arg2; - } - - $avatar_type = call_user_func_array($func, $ary); - } - else - { - $avatar_type = call_user_func($func); - } - } - - switch ($avatar_type) - { - case AVATAR_UPLOAD: - return get_upload_avatar_dim($src, $axis); - break; - - case AVATAR_GALLERY: - return get_gallery_avatar_dim($src, $axis); - break; - - case AVATAR_REMOTE: - // see notes on this functions usage and (hopefully) model $func to avoid this accordingly - return get_remote_avatar_dim($src, $axis); - break; - - default: - $default_x = (defined('DEFAULT_AVATAR_X_CUSTOM')) ? DEFAULT_AVATAR_X_CUSTOM : DEFAULT_AVATAR_X; - $default_y = (defined('DEFAULT_AVATAR_Y_CUSTOM')) ? DEFAULT_AVATAR_Y_CUSTOM : DEFAULT_AVATAR_Y; - - return $axis ? $default_y : $default_x; - break; - } -} - -/** -* Obtain the size of the specified uploaded avatar (using the cache if possible) and cache the value -*/ -function get_upload_avatar_dim($source, $axis) -{ - static $cachedims = false; - static $cachekey = false; - - if (empty($source)) - { - return 0; - } - - if ($cachekey == $source) - { - return $cachedims[$axis]; - } - - $orig_source = $source; - - if (substr($source, 0, 7) == 'upload:') - { - $source = substr($source, 7); - } - - global $convert, $user; - - if (!isset($convert->convertor['avatar_path'])) - { - $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_AVATAR_PATH'], 'get_upload_avatar_dim()'), __LINE__, __FILE__); - } - - if (!empty($convert->convertor['avatar_path']) && strpos($source, $convert->convertor['avatar_path']) !== 0) - { - $source = path($convert->convertor['avatar_path'], empty($convert->convertor['source_path_absolute'])) . $source; - } - - $cachedims = get_image_dim($source); - - if (empty($cachedims) || empty($cachedims[0]) || empty($cachedims[1])) - { - $default_x = (defined('DEFAULT_AVATAR_X_CUSTOM')) ? DEFAULT_AVATAR_X_CUSTOM : DEFAULT_AVATAR_X; - $default_y = (defined('DEFAULT_AVATAR_Y_CUSTOM')) ? DEFAULT_AVATAR_Y_CUSTOM : DEFAULT_AVATAR_Y; - - $cachedims = array($default_x, $default_y); - } - - return $cachedims[$axis]; -} - -/** -* Obtain the size of the specified gallery avatar (using the cache if possible) and cache the value -*/ -function get_gallery_avatar_dim($source, $axis) -{ - if (empty($source)) - { - return 0; - } - - static $avatar_cache = array(); - - if (isset($avatar_cache[$source])) - { - return $avatar_cache[$source][$axis]; - } - - global $convert, $user; - - $orig_source = $source; - - if (!isset($convert->convertor['avatar_gallery_path'])) - { - $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_GALLERY_PATH'], 'get_gallery_avatar_dim()'), __LINE__, __FILE__); - } - - if (!empty($convert->convertor['avatar_gallery_path']) && strpos($source, $convert->convertor['avatar_gallery_path']) !== 0) - { - $source = path($convert->convertor['avatar_gallery_path'], empty($convert->convertor['source_path_absolute'])) . $source; - } - - $avatar_cache[$orig_source] = get_image_dim($source); - - if (empty($avatar_cache[$orig_source]) || empty($avatar_cache[$orig_source][0]) || empty($avatar_cache[$orig_source][1])) - { - $default_x = (defined('DEFAULT_AVATAR_X_CUSTOM')) ? DEFAULT_AVATAR_X_CUSTOM : DEFAULT_AVATAR_X; - $default_y = (defined('DEFAULT_AVATAR_Y_CUSTOM')) ? DEFAULT_AVATAR_Y_CUSTOM : DEFAULT_AVATAR_Y; - - $avatar_cache[$orig_source] = array($default_x, $default_y); - } - - return $avatar_cache[$orig_source][$axis]; -} - -/** -* Obtain the size of the specified remote avatar (using the cache if possible) and cache the value -* Whilst it's unlikely that remote avatars will be duplicated, it is possible so caching seems the best option -* This should only be called from a post processing step due to the possibility of network timeouts -*/ -function get_remote_avatar_dim($src, $axis) -{ - if (empty($src)) - { - return 0; - } - - static $remote_avatar_cache = array(); - - // an ugly hack: we assume that the dimensions of each remote avatar are accessed exactly twice (x and y) - if (isset($remote_avatar_cache[$src])) - { - $retval = $remote_avatar_cache[$src][$axis]; - unset($remote_avatar_cache); - return $retval; - } - - $url_info = @parse_url($src); - if (empty($url_info['host'])) - { - return 0; - } - $host = $url_info['host']; - $port = (isset($url_info['port'])) ? $url_info['port'] : 0; - $protocol = (isset($url_info['scheme'])) ? $url_info['scheme'] : 'http'; - if (empty($port)) - { - switch(strtolower($protocol)) - { - case 'ftp': - $port = 21; - break; - - case 'https': - $port = 443; - break; - - default: - $port = 80; - } - } - - $timeout = @ini_get('default_socket_timeout'); - @ini_set('default_socket_timeout', 2); - - // We're just trying to reach the server to avoid timeouts - $fp = @fsockopen($host, $port, $errno, $errstr, 1); - if ($fp) - { - $remote_avatar_cache[$src] = @getimagesize($src); - fclose($fp); - } - - $default_x = (defined('DEFAULT_AVATAR_X_CUSTOM')) ? DEFAULT_AVATAR_X_CUSTOM : DEFAULT_AVATAR_X; - $default_y = (defined('DEFAULT_AVATAR_Y_CUSTOM')) ? DEFAULT_AVATAR_Y_CUSTOM : DEFAULT_AVATAR_Y; - $default = array($default_x, $default_y); - - if (empty($remote_avatar_cache[$src]) || empty($remote_avatar_cache[$src][0]) || empty($remote_avatar_cache[$src][1])) - { - $remote_avatar_cache[$src] = $default; - } - else - { - // We trust gallery and uploaded avatars to conform to the size settings; we might have to adjust here - if ($remote_avatar_cache[$src][0] > $default_x || $remote_avatar_cache[$src][1] > $default_y) - { - $bigger = ($remote_avatar_cache[$src][0] > $remote_avatar_cache[$src][1]) ? 0 : 1; - $ratio = $default[$bigger] / $remote_avatar_cache[$src][$bigger]; - $remote_avatar_cache[$src][0] = (int)($remote_avatar_cache[$src][0] * $ratio); - $remote_avatar_cache[$src][1] = (int)($remote_avatar_cache[$src][1] * $ratio); - } - } - - @ini_set('default_socket_timeout', $timeout); - return $remote_avatar_cache[$src][$axis]; -} - -function set_user_options() -{ - global $convert_row; - - // Key need to be set in row, else default value is chosen - $keyoptions = array( - 'viewimg' => array('bit' => 0, 'default' => 1), - 'viewflash' => array('bit' => 1, 'default' => 1), - 'viewsmilies' => array('bit' => 2, 'default' => 1), - 'viewsigs' => array('bit' => 3, 'default' => 1), - 'viewavatars' => array('bit' => 4, 'default' => 1), - 'viewcensors' => array('bit' => 5, 'default' => 1), - 'attachsig' => array('bit' => 6, 'default' => 0), - 'bbcode' => array('bit' => 8, 'default' => 1), - 'smilies' => array('bit' => 9, 'default' => 1), - 'popuppm' => array('bit' => 10, 'default' => 0), - ); - - $option_field = 0; - - foreach ($keyoptions as $key => $key_ary) - { - $value = (isset($convert_row[$key])) ? (int) $convert_row[$key] : $key_ary['default']; - - if ($value && !($option_field & 1 << $key_ary['bit'])) - { - $option_field += 1 << $key_ary['bit']; - } - } - - return $option_field; -} - -/** -* Index messages on the fly as we convert them -* @todo naderman, can you check that this works with the new search plugins as it's use is currently disabled (and thus untested) -function search_indexing($message = '') -{ - global $fulltext_search, $convert_row; - - if (!isset($convert_row['post_id'])) - { - return; - } - - if (!$message) - { - if (!isset($convert_row['message'])) - { - return; - } - - $message = $convert_row['message']; - } - - $title = (isset($convert_row['title'])) ? $convert_row['title'] : ''; - - $fulltext_search->index('post', $convert_row['post_id'], $message, $title, $convert_row['poster_id'], $convert_row['forum_id']); -} -*/ - -function make_unique_filename($filename) -{ - if (!strlen($filename)) - { - $filename = md5(unique_id()) . '.dat'; - } - else if ($filename[0] == '.') - { - $filename = md5(unique_id()) . $filename; - } - else if (preg_match('/\.([a-z]+)$/i', $filename, $m)) - { - $filename = preg_replace('/\.([a-z]+)$/i', '_' . md5(unique_id()) . '.\1', $filename); - } - else - { - $filename .= '_' . md5(unique_id()) . '.dat'; - } - - return $filename; -} - -function words_unique(&$words) -{ - reset($words); - $return_array = array(); - - $word = current($words); - do - { - $return_array[$word] = $word; - } - while ($word = next($words)); - - return $return_array; -} - -/** -* Adds a user to the specified group and optionally makes them a group leader -* This function does not create the group if it does not exist and so should only be called after the groups have been created -*/ -function add_user_group($group_id, $user_id, $group_leader=false) -{ - global $convert, $user, $db; - - $sql = 'INSERT INTO ' . USER_GROUP_TABLE . ' ' . $db->sql_build_array('INSERT', array( - 'group_id' => $group_id, - 'user_id' => $user_id, - 'group_leader' => ($group_leader) ? 1 : 0, - 'user_pending' => 0)); - $db->sql_query($sql); -} - -// STANDALONE FUNCTIONS - -/** -* Add users to the pre-defined "special" groups -* -* @param string $group The name of the special group to add to -* @param string $select_query An SQL query to retrieve the user(s) to add to the group -*/ -function user_group_auth($group, $select_query, $use_src_db) -{ - global $convert, $user, $db, $src_db, $same_db; - - if (!in_array($group, array('guests', 'registered', 'registered_coppa', 'global_moderators', 'administrators', 'bots'))) - { - $convert->p_master->error(sprintf($user->lang['CONV_ERROR_WRONG_GROUP'], $group, 'user_group_auth()'), __LINE__, __FILE__, true); - return; - } - - $sql = 'SELECT group_id - FROM ' . GROUPS_TABLE . " - WHERE group_name_clean = '" . $db->sql_escape(utf8_clean_string($group)) . "'"; - $result = $db->sql_query($sql); - $group_id = (int) $db->sql_fetchfield('group_id'); - $db->sql_freeresult($result); - - if (!$group_id) - { - $convert->p_master->error(sprintf($user->lang['CONV_ERROR_NO_GROUP'], $group, 'user_group_auth()'), __LINE__, __FILE__, true); - return; - } - - if ($same_db || !$use_src_db) - { - $sql = 'INSERT INTO ' . USER_GROUP_TABLE . ' (user_id, group_id, user_pending) - ' . str_replace('{' . strtoupper($group) . '}', $group_id . ', 0', $select_query); - $db->sql_query($sql); - } - else - { - $result = $src_db->sql_query(str_replace('{' . strtoupper($group) . '}', $group_id . ' ', $select_query)); - while ($row = $src_db->sql_fetchrow($result)) - { - // this might become quite a lot of INSERTS unfortunately - $sql = 'INSERT INTO ' . USER_GROUP_TABLE . " (user_id, group_id, user_pending) - VALUES ({$row['user_id']}, $group_id, 0)"; - $db->sql_query($sql); - } - $src_db->sql_freeresult($result); - } -} - -/** -* Retrieves configuration information from the source forum and caches it as an array -* Both database and file driven configuration formats can be handled -* (the type used is specified in $config_schema, see convert_phpbb20.php for more details) -*/ -function get_config() -{ - static $convert_config; - global $user; - - if (isset($convert_config)) - { - return $convert_config; - } - - global $src_db, $same_db; - global $convert; - - if ($convert->config_schema['table_format'] != 'file') - { - if ($convert->mysql_convert && $same_db) - { - $src_db->sql_query("SET NAMES 'binary'"); - } - - $sql = 'SELECT * FROM ' . $convert->src_table_prefix . $convert->config_schema['table_name']; - $result = $src_db->sql_query($sql); - $row = $src_db->sql_fetchrow($result); - - if (!$row) - { - $convert->p_master->error($user->lang['CONV_ERROR_GET_CONFIG'], __LINE__, __FILE__); - } - } - - if (is_array($convert->config_schema['table_format'])) - { - $convert_config = array(); - list($key, $val) = each($convert->config_schema['table_format']); - - do - { - $convert_config[$row[$key]] = $row[$val]; - } - while ($row = $src_db->sql_fetchrow($result)); - $src_db->sql_freeresult($result); - - if ($convert->mysql_convert && $same_db) - { - $src_db->sql_query("SET NAMES 'utf8'"); - } - } - else if ($convert->config_schema['table_format'] == 'file') - { - $filename = $convert->options['forum_path'] . '/' . $convert->config_schema['filename']; - if (!file_exists($filename)) - { - $convert->p_master->error($user->lang['FILE_NOT_FOUND'] . ': ' . $filename, __LINE__, __FILE__); - } - - $convert_config = extract_variables_from_file($filename); - if (!empty($convert->config_schema['array_name'])) - { - $convert_config = $convert_config[$convert->config_schema['array_name']]; - } - } - else - { - $convert_config = $row; - if ($convert->mysql_convert && $same_db) - { - $src_db->sql_query("SET NAMES 'utf8'"); - } - } - - if (!sizeof($convert_config)) - { - $convert->p_master->error($user->lang['CONV_ERROR_CONFIG_EMPTY'], __LINE__, __FILE__); - } - - return $convert_config; -} - -/** -* Transfers the relevant configuration information from the source forum -* The mapping of fields is specified in $config_schema, see convert_phpbb20.php for more details -*/ -function restore_config($schema) -{ - global $db; - - $convert_config = get_config(); - foreach ($schema['settings'] as $config_name => $src) - { - if (preg_match('/(.*)\((.*)\)/', $src, $m)) - { - $var = (empty($m[2]) || empty($convert_config[$m[2]])) ? "''" : "'" . addslashes($convert_config[$m[2]]) . "'"; - $exec = '$config_value = ' . $m[1] . '(' . $var . ');'; - eval($exec); - } - else - { - $config_value = (isset($convert_config[$src])) ? $convert_config[$src] : ''; - } - - if ($config_value !== '') - { - // Most are... - if (is_string($config_value)) - { - $config_value = truncate_string(utf8_htmlspecialchars($config_value), 255, 255, false); - } - - set_config($config_name, $config_value); - } - } -} - -/** -* Update the count of PM's in custom folders for all users -*/ -function update_folder_pm_count() -{ - global $db, $convert, $user; - - $sql = 'SELECT user_id, folder_id, COUNT(msg_id) as num_messages - FROM ' . PRIVMSGS_TO_TABLE . ' - WHERE folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ', ' . PRIVMSGS_INBOX . ', ' . PRIVMSGS_OUTBOX . ', ' . PRIVMSGS_SENTBOX . ') - GROUP BY folder_id, user_id'; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $db->sql_query('UPDATE ' . PRIVMSGS_FOLDER_TABLE . ' SET pm_count = ' . $row['num_messages'] . ' - WHERE user_id = ' . $row['user_id'] . ' AND folder_id = ' . $row['folder_id']); - } - $db->sql_freeresult($result); -} - -// Functions mainly used by the main convertor script - -function path($path, $path_relative = true) -{ - if ($path === false) - { - return ''; - } - - if (substr($path, -1) != '/') - { - $path .= '/'; - } - - if (!$path_relative) - { - return $path; - } - - if (substr($path, 0, 1) == '/') - { - $path = substr($path, 1); - } - - return $path; -} - -/** -* Extract the variables defined in a configuration file -* @todo As noted by Xore we need to look at this from a security perspective -*/ -function extract_variables_from_file($_filename) -{ - include($_filename); - - $vars = get_defined_vars(); - unset($vars['_filename']); - - return $vars; -} - -function get_path($src_path, $src_url, $test_file) -{ - $board_config = get_config(); - - $test_file = preg_replace('/\.php$/i', '.' . PHP_EXT, $test_file); - $src_path = path($src_path); - - if (@file_exists(PHPBB_ROOT_PATH . $src_path . $test_file)) - { - return $src_path; - } - - if (!empty($src_url) && !empty($board_config['server_name'])) - { - if (!preg_match('#https?://([^/]+)(.*)#i', $src_url, $m)) - { - return false; - } - - if ($m[1] != $board_config['server_name']) - { - return false; - } - - $url_parts = explode('/', $m[2]); - if (substr($src_url, -1) != '/') - { - if (preg_match('/.*\.([a-z0-9]{3,4})$/i', $url_parts[sizeof($url_parts) - 1])) - { - $url_parts[sizeof($url_parts) - 1] = ''; - } - else - { - $url_parts[] = ''; - } - } - - $script_path = $board_config['script_path']; - if (substr($script_path, -1) == '/') - { - $script_path = substr($script_path, 0, -1); - } - - $path_array = array(); - - $phpbb_parts = explode('/', $script_path); - for ($i = 0; $i < sizeof($url_parts); ++$i) - { - if ($i < sizeof($phpbb_parts[$i]) && $url_parts[$i] == $phpbb_parts[$i]) - { - $path_array[] = $url_parts[$i]; - unset($url_parts[$i]); - } - else - { - $path = ''; - for ($j = $i; $j < sizeof($phpbb_parts); ++$j) - { - $path .= '../'; - } - $path .= implode('/', $url_parts); - break; - } - } - - if (!empty($path)) - { - if (@file_exists(PHPBB_ROOT_PATH . $path . $test_file)) - { - return $path; - } - } - } - - return false; -} - -function compare_table($tables, $tablename, &$prefixes) -{ - for ($i = 0, $table_size = sizeof($tables); $i < $table_size; ++$i) - { - if (preg_match('/(.*)' . $tables[$i] . '$/', $tablename, $m)) - { - if (empty($m[1])) - { - $m[1] = '*'; - } - - if (isset($prefixes[$m[1]])) - { - $prefixes[$m[1]]++; - } - else - { - $prefixes[$m[1]] = 1; - } - } - } -} - -/** -* Grant permissions to a specified user or group -* -* @param string $ug_type user|group|user_role|group_role -* @param mixed $forum_id forum ids (array|int|0) -> 0 == all forums -* @param mixed $ug_id [int] user_id|group_id : [string] usergroup name -* @param mixed $acl_list [string] acl entry : [array] acl entries : [string] role entry -* @param int $setting phpbb::ACL_YES|ACL_NO|ACL_NEVER -*/ -function mass_auth($ug_type, $forum_id, $ug_id, $acl_list, $setting = ACL_NO) -{ - global $db, $convert, $user; - static $acl_option_ids, $group_ids; - - if (($ug_type == 'group' || $ug_type == 'group_role') && is_string($ug_id)) - { - if (!isset($group_ids[$ug_id])) - { - $sql = 'SELECT group_id - FROM ' . GROUPS_TABLE . " - WHERE group_name_clean = '" . $db->sql_escape(utf8_clean_string($ug_id)) . "'"; - $result = $db->sql_query_limit($sql, 1); - $id = (int) $db->sql_fetchfield('group_id'); - $db->sql_freeresult($result); - - if (!$id) - { - return; - } - - $group_ids[$ug_id] = $id; - } - - $ug_id = (int) $group_ids[$ug_id]; - } - - $table = ($ug_type == 'user' || $ug_type == 'user_role') ? ACL_USERS_TABLE : ACL_GROUPS_TABLE; - $id_field = ($ug_type == 'user' || $ug_type == 'user_role') ? 'user_id' : 'group_id'; - - // Role based permissions are the simplest to handle so check for them first - if ($ug_type == 'user_role' || $ug_type == 'group_role') - { - if (is_numeric($forum_id)) - { - $sql = 'SELECT role_id - FROM ' . ACL_ROLES_TABLE . " - WHERE role_name = 'ROLE_" . $db->sql_escape($acl_list) . "'"; - $result = $db->sql_query_limit($sql, 1); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - // If we have no role id there is something wrong here - if ($row) - { - $sql = "INSERT INTO $table ($id_field, forum_id, auth_role_id) VALUES ($ug_id, $forum_id, " . $row['role_id'] . ')'; - $db->sql_query($sql); - } - } - - return; - } - - // Build correct parameters - $auth = array(); - - if (!is_array($acl_list)) - { - $auth = array($acl_list => $setting); - } - else - { - foreach ($acl_list as $auth_option) - { - $auth[$auth_option] = $setting; - } - } - unset($acl_list); - - if (!is_array($forum_id)) - { - $forum_id = array($forum_id); - } - - // Set any flags as required - foreach ($auth as $auth_option => $acl_setting) - { - $flag = substr($auth_option, 0, strpos($auth_option, '_') + 1); - if (empty($auth[$flag])) - { - $auth[$flag] = $acl_setting; - } - } - - if (!is_array($acl_option_ids) || empty($acl_option_ids)) - { - $sql = 'SELECT auth_option_id, auth_option - FROM ' . ACL_OPTIONS_TABLE; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $acl_option_ids[$row['auth_option']] = $row['auth_option_id']; - } - $db->sql_freeresult($result); - } - - $sql_forum = 'AND ' . $db->sql_in_set('a.forum_id', array_map('intval', $forum_id), false, true); - - $sql = ($ug_type == 'user') ? 'SELECT o.auth_option_id, o.auth_option, a.forum_id, a.auth_setting FROM ' . ACL_USERS_TABLE . ' a, ' . ACL_OPTIONS_TABLE . " o WHERE a.auth_option_id = o.auth_option_id $sql_forum AND a.user_id = $ug_id" : 'SELECT o.auth_option_id, o.auth_option, a.forum_id, a.auth_setting FROM ' . ACL_GROUPS_TABLE . ' a, ' . ACL_OPTIONS_TABLE . " o WHERE a.auth_option_id = o.auth_option_id $sql_forum AND a.group_id = $ug_id"; - $result = $db->sql_query($sql); - - $cur_auth = array(); - while ($row = $db->sql_fetchrow($result)) - { - $cur_auth[$row['forum_id']][$row['auth_option_id']] = $row['auth_setting']; - } - $db->sql_freeresult($result); - - $sql_ary = array(); - foreach ($forum_id as $forum) - { - foreach ($auth as $auth_option => $setting) - { - $auth_option_id = $acl_option_ids[$auth_option]; - - if (!$auth_option_id) - { - continue; - } - - switch ($setting) - { - case ACL_NO: - if (isset($cur_auth[$forum][$auth_option_id])) - { - $sql_ary['delete'][] = "DELETE FROM $table - WHERE forum_id = $forum - AND auth_option_id = $auth_option_id - AND $id_field = $ug_id"; - } - break; - - default: - if (!isset($cur_auth[$forum][$auth_option_id])) - { - $sql_ary['insert'][] = "$ug_id, $forum, $auth_option_id, $setting"; - } - else if ($cur_auth[$forum][$auth_option_id] != $setting) - { - $sql_ary['update'][] = "UPDATE " . $table . " - SET auth_setting = $setting - WHERE $id_field = $ug_id - AND forum_id = $forum - AND auth_option_id = $auth_option_id"; - } - } - } - } - unset($cur_auth); - - $sql = ''; - foreach ($sql_ary as $sql_type => $sql_subary) - { - switch ($sql_type) - { - case 'insert': - switch ($db->dbms_type) - { - case 'mysql': - $sql = 'VALUES ' . implode(', ', preg_replace('#^(.*?)$#', '(\1)', $sql_subary)); - break; - - case 'mssql': - case 'sqlite': - $sql = implode(' UNION ALL ', preg_replace('#^(.*?)$#', 'SELECT \1', $sql_subary)); - break; - - default: - foreach ($sql_subary as $sql) - { - $sql = "INSERT INTO $table ($id_field, forum_id, auth_option_id, auth_setting) VALUES ($sql)"; - $db->sql_query($sql); - $sql = ''; - } - } - - if ($sql != '') - { - $sql = "INSERT INTO $table ($id_field, forum_id, auth_option_id, auth_setting) $sql"; - $db->sql_query($sql); - } - break; - - case 'update': - case 'delete': - foreach ($sql_subary as $sql) - { - $db->sql_query($sql); - $sql = ''; - } - break; - } - unset($sql_ary[$sql_type]); - } - unset($sql_ary); - -} - -/** -* Update the count of unread private messages for all users -*/ -function update_unread_count() -{ - global $db; - - $sql = 'SELECT user_id, COUNT(msg_id) as num_messages - FROM ' . PRIVMSGS_TO_TABLE . ' - WHERE pm_unread = 1 - AND folder_id <> ' . PRIVMSGS_OUTBOX . ' - GROUP BY user_id'; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $db->sql_query('UPDATE ' . USERS_TABLE . ' SET user_unread_privmsg = ' . $row['num_messages'] . ' - WHERE user_id = ' . $row['user_id']); - } - $db->sql_freeresult($result); -} - -/** -* Add any of the pre-defined "special" groups which are missing from the database -*/ -function add_default_groups() -{ - global $db; - - $default_groups = array( - 'GUESTS' => array('', 0, 0), - 'REGISTERED' => array('', 0, 0), - 'REGISTERED_COPPA' => array('', 0, 0), - 'GLOBAL_MODERATORS' => array('00AA00', 1, 0), - 'ADMINISTRATORS' => array('AA0000', 1, 1), - 'BOTS' => array('9E8DA7', 0, 0) - ); - - $sql = 'SELECT * - FROM ' . GROUPS_TABLE . ' - WHERE ' . $db->sql_in_set('group_name_clean', array_map('utf8_clean_string', array_keys($default_groups))); - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - unset($default_groups[strtoupper($row['group_name'])]); - } - $db->sql_freeresult($result); - - $sql_ary = array(); - - foreach ($default_groups as $name => $data) - { - $sql_ary[] = array( - 'group_name' => (string) $name, - 'group_name_clean' => (string) utf8_clean_string($name), - 'group_desc' => '', - 'group_desc_uid' => '', - 'group_desc_bitfield' => '', - 'group_type' => GROUP_SPECIAL, - 'group_colour' => (string) $data[0], - 'group_legend' => (int) $data[1], - 'group_founder_manage' => (int) $data[2] - ); - } - - if (sizeof($sql_ary)) - { - $db->sql_multi_insert(GROUPS_TABLE, $sql_ary); - } -} - - -/** -* Sync post count. We might need to do this in batches. -*/ -function sync_post_count($offset, $limit) -{ - global $db; - $sql = 'SELECT COUNT(post_id) AS num_posts, poster_id - FROM ' . POSTS_TABLE . ' - WHERE post_postcount = 1 - AND post_approved = 1 - GROUP BY poster_id - ORDER BY poster_id'; - $result = $db->sql_query_limit($sql, $limit, $offset); - - while ($row = $db->sql_fetchrow($result)) - { - $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_posts = {$row['num_posts']} WHERE user_id = {$row['poster_id']}"); - } - $db->sql_freeresult($result); -} - -/** -* Add the search bots into the database -* This code should be used in execute_last if the source database did not have bots -* If you are converting bots this function should not be called -* @todo We might want to look at sharing the bot list between the install code and this code for consistancy -*/ -function add_bots() -{ - global $db, $convert, $user; - - $db->sql_query($convert->truncate_statement . BOTS_TABLE); - - $sql = 'SELECT group_id FROM ' . GROUPS_TABLE . " WHERE group_name_clean = 'bots'"; - $result = $db->sql_query($sql); - $group_id = (int) $db->sql_fetchfield('group_id', $result); - $db->sql_freeresult($result); - - if (!$group_id) - { - add_default_groups(); - - $sql = 'SELECT group_id FROM ' . GROUPS_TABLE . " WHERE group_name_clean = 'bots'"; - $result = $db->sql_query($sql); - $group_id = (int) $db->sql_fetchfield('group_id', $result); - $db->sql_freeresult($result); - - if (!$group_id) - { - global $install; - $install->error($user->lang['CONV_ERROR_INCONSISTENT_GROUPS'], __LINE__, __FILE__); - } - } - - $bots = array( - 'AdsBot [Google]' => array('AdsBot-Google', ''), - 'Alexa [Bot]' => array('ia_archiver', ''), - 'Alta Vista [Bot]' => array('Scooter/', ''), - 'Ask Jeeves [Bot]' => array('Ask Jeeves', ''), - 'Baidu [Spider]' => array('Baiduspider+(', ''), - 'Exabot [Bot]' => array('Exabot/', ''), - 'FAST Enterprise [Crawler]' => array('FAST Enterprise Crawler', ''), - 'FAST WebCrawler [Crawler]' => array('FAST-WebCrawler/', ''), - 'Francis [Bot]' => array('http://www.neomo.de/', ''), - 'Gigabot [Bot]' => array('Gigabot/', ''), - 'Google Adsense [Bot]' => array('Mediapartners-Google', ''), - 'Google Desktop' => array('Google Desktop', ''), - 'Google Feedfetcher' => array('Feedfetcher-Google', ''), - 'Google [Bot]' => array('Googlebot', ''), - 'Heise IT-Markt [Crawler]' => array('heise-IT-Markt-Crawler', ''), - 'Heritrix [Crawler]' => array('heritrix/1.', ''), - 'IBM Research [Bot]' => array('ibm.com/cs/crawler', ''), - 'ICCrawler - ICjobs' => array('ICCrawler - ICjobs', ''), - 'ichiro [Crawler]' => array('ichiro/2', ''), - 'Majestic-12 [Bot]' => array('MJ12bot/', ''), - 'Metager [Bot]' => array('MetagerBot/', ''), - 'MSN NewsBlogs' => array('msnbot-NewsBlogs/', ''), - 'MSN [Bot]' => array('msnbot/', ''), - 'MSNbot Media' => array('msnbot-media/', ''), - 'NG-Search [Bot]' => array('NG-Search/', ''), - 'Nutch [Bot]' => array('http://lucene.apache.org/nutch/', ''), - 'Nutch/CVS [Bot]' => array('NutchCVS/', ''), - 'OmniExplorer [Bot]' => array('OmniExplorer_Bot/', ''), - 'Online link [Validator]' => array('online link validator', ''), - 'psbot [Picsearch]' => array('psbot/0', ''), - 'Seekport [Bot]' => array('Seekbot/', ''), - 'Sensis [Crawler]' => array('Sensis Web Crawler', ''), - 'SEO Crawler' => array('SEO search Crawler/', ''), - 'Seoma [Crawler]' => array('Seoma [SEO Crawler]', ''), - 'SEOSearch [Crawler]' => array('SEOsearch/', ''), - 'Snappy [Bot]' => array('Snappy/1.1 ( http://www.urltrends.com/ )', ''), - 'Steeler [Crawler]' => array('http://www.tkl.iis.u-tokyo.ac.jp/~crawler/', ''), - 'Synoo [Bot]' => array('SynooBot/', ''), - 'Telekom [Bot]' => array('crawleradmin.t-info@telekom.de', ''), - 'TurnitinBot [Bot]' => array('TurnitinBot/', ''), - 'Voyager [Bot]' => array('voyager/1.0', ''), - 'W3 [Sitesearch]' => array('W3 SiteSearch Crawler', ''), - 'W3C [Linkcheck]' => array('W3C-checklink/', ''), - 'W3C [Validator]' => array('W3C_*Validator', ''), - 'WiseNut [Bot]' => array('http://www.WISEnutbot.com', ''), - 'YaCy [Bot]' => array('yacybot', ''), - 'Yahoo MMCrawler [Bot]' => array('Yahoo-MMCrawler/', ''), - 'Yahoo Slurp [Bot]' => array('Yahoo! DE Slurp', ''), - 'Yahoo [Bot]' => array('Yahoo! Slurp', ''), - 'YahooSeeker [Bot]' => array('YahooSeeker/', ''), - ); - - if (!function_exists('user_add')) - { - include(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); - } - - foreach ($bots as $bot_name => $bot_ary) - { - $user_row = array( - 'user_type' => phpbb::USER_IGNORE, - 'group_id' => $group_id, - 'username' => $bot_name, - 'user_regdate' => time(), - 'user_password' => '', - 'user_colour' => '9E8DA7', - 'user_email' => '', - 'user_lang' => phpbb::$config['default_lang'], - 'user_style' => 1, - 'user_timezone' => 0, - 'user_allow_massemail' => 0, - ); - - $user_id = user_add($user_row); - - if ($user_id) - { - $sql = 'INSERT INTO ' . BOTS_TABLE . ' ' . $db->sql_build_array('INSERT', array( - 'bot_active' => 1, - 'bot_name' => $bot_name, - 'user_id' => $user_id, - 'bot_agent' => $bot_ary[0], - 'bot_ip' => $bot_ary[1]) - ); - $db->sql_query($sql); - } - } -} - -/** -* Update any dynamic configuration variables after the conversion is finished -* @todo Confirm that this updates all relevant values since it has not necessarily been kept in sync with all changes -*/ -function update_dynamic_config() -{ - global $db; - - // Get latest username - $sql = 'SELECT user_id, username, user_colour - FROM ' . USERS_TABLE . ' - WHERE user_type IN (' . phpbb::USER_NORMAL . ', ' . phpbb::USER_FOUNDER . ')'; - - if (!empty(phpbb::$config['increment_user_id'])) - { - $sql .= ' AND user_id <> ' . phpbb::$config['increment_user_id']; - } - - $sql .= ' ORDER BY user_id DESC'; - - $result = $db->sql_query_limit($sql, 1); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if ($row) - { - set_config('newest_user_id', $row['user_id'], true); - set_config('newest_username', $row['username'], true); - set_config('newest_user_colour', $row['user_colour'], true); - } - -// Also do not reset record online user/date. There will be old data or the fresh data from the schema. -// set_config('record_online_users', 1, true); -// set_config('record_online_date', time(), true); - - $sql = 'SELECT COUNT(post_id) AS stat - FROM ' . POSTS_TABLE . ' - WHERE post_approved = 1'; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - set_config('num_posts', (int) $row['stat'], true); - - $sql = 'SELECT COUNT(topic_id) AS stat - FROM ' . TOPICS_TABLE . ' - WHERE topic_approved = 1'; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - set_config('num_topics', (int) $row['stat'], true); - - $sql = 'SELECT COUNT(user_id) AS stat - FROM ' . USERS_TABLE . ' - WHERE user_type IN (' . phpbb::USER_NORMAL . ',' . phpbb::USER_FOUNDER . ')'; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - set_config('num_users', (int) $row['stat'], true); - - $sql = 'SELECT COUNT(attach_id) as stat - FROM ' . ATTACHMENTS_TABLE . ' - WHERE is_orphan = 0'; - $result = $db->sql_query($sql); - set_config('num_files', (int) $db->sql_fetchfield('stat'), true); - $db->sql_freeresult($result); - - $sql = 'SELECT SUM(filesize) as stat - FROM ' . ATTACHMENTS_TABLE . ' - WHERE is_orphan = 0'; - $result = $db->sql_query($sql); - set_config('upload_dir_size', (float) $db->sql_fetchfield('stat'), true); - $db->sql_freeresult($result); - - /** - * We do not resync users post counts - this can be done by the admin after conversion if wanted. - $sql = 'SELECT COUNT(post_id) AS num_posts, poster_id - FROM ' . POSTS_TABLE . ' - WHERE post_postcount = 1 - GROUP BY poster_id'; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_posts = {$row['num_posts']} WHERE user_id = {$row['poster_id']}"); - } - $db->sql_freeresult($result); - */ -} - -/** -* Updates topics_posted entries -*/ -function update_topics_posted() -{ - global $db; - - if ($db->truncate) - { - $db->sql_query('DELETE FROM ' . TOPICS_POSTED_TABLE); - } - else - { - $db->sql_query('TRUNCATE TABLE ' . TOPICS_POSTED_TABLE); - } - - // This can get really nasty... therefore we only do the last six months - $get_from_time = time() - (6 * 4 * 7 * 24 * 60 * 60); - - // Select forum ids, do not include categories - $sql = 'SELECT forum_id - FROM ' . FORUMS_TABLE . ' - WHERE forum_type <> ' . FORUM_CAT; - $result = $db->sql_query($sql); - - $forum_ids = array(); - while ($row = $db->sql_fetchrow($result)) - { - $forum_ids[] = $row['forum_id']; - } - $db->sql_freeresult($result); - - // Any global announcements? ;) - $forum_ids[] = 0; - - // Now go through the forums and get us some topics... - foreach ($forum_ids as $forum_id) - { - $sql = 'SELECT p.poster_id, p.topic_id - FROM ' . POSTS_TABLE . ' p, ' . TOPICS_TABLE . ' t - WHERE t.forum_id = ' . $forum_id . ' - AND t.topic_moved_id = 0 - AND t.topic_last_post_time > ' . $get_from_time . ' - AND t.topic_id = p.topic_id - AND p.poster_id <> ' . ANONYMOUS . ' - GROUP BY p.poster_id, p.topic_id'; - $result = $db->sql_query($sql); - - $posted = array(); - while ($row = $db->sql_fetchrow($result)) - { - $posted[$row['poster_id']][] = $row['topic_id']; - } - $db->sql_freeresult($result); - - $sql_ary = array(); - foreach ($posted as $user_id => $topic_row) - { - foreach ($topic_row as $topic_id) - { - $sql_ary[] = array( - 'user_id' => (int) $user_id, - 'topic_id' => (int) $topic_id, - 'topic_posted' => 1, - ); - } - } - unset($posted); - - if (sizeof($sql_ary)) - { - $db->sql_multi_insert(TOPICS_POSTED_TABLE, $sql_ary); - } - } -} - -/** -* Ensure that all users have a default group specified and update related information such as their colour -*/ -function fix_empty_primary_groups() -{ - global $db; - - // Set group ids for users not already having it - $sql = 'UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('registered') . ' - WHERE group_id = 0 AND user_type = ' . phpbb::USER_INACTIVE; - $db->sql_query($sql); - - $sql = 'UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('registered') . ' - WHERE group_id = 0 AND user_type = ' . phpbb::USER_NORMAL; - $db->sql_query($sql); - - $db->sql_query('UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('guests') . ' WHERE user_id = ' . ANONYMOUS); - - $sql = 'SELECT user_id FROM ' . USER_GROUP_TABLE . ' WHERE group_id = ' . get_group_id('administrators'); - $result = $db->sql_query($sql); - - $user_ids = array(); - while ($row = $db->sql_fetchrow($result)) - { - $user_ids[] = $row['user_id']; - } - $db->sql_freeresult($result); - - if (sizeof($user_ids)) - { - $db->sql_query('UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('administrators') . ' - WHERE group_id = 0 AND ' . $db->sql_in_set('user_id', $user_ids)); - } - - $sql = 'SELECT user_id FROM ' . USER_GROUP_TABLE . ' WHERE group_id = ' . get_group_id('global_moderators'); - - $user_ids = array(); - while ($row = $db->sql_fetchrow($result)) - { - $user_ids[] = $row['user_id']; - } - $db->sql_freeresult($result); - - if (sizeof($user_ids)) - { - $db->sql_query('UPDATE ' . USERS_TABLE . ' SET group_id = ' . get_group_id('global_moderators') . ' - WHERE group_id = 0 AND ' . $db->sql_in_set('user_id', $user_ids)); - } - - // Set user colour - $sql = 'SELECT group_id, group_colour FROM ' . GROUPS_TABLE . " - WHERE group_colour <> ''"; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $db->sql_query('UPDATE ' . USERS_TABLE . " SET user_colour = '{$row['group_colour']}' WHERE group_id = {$row['group_id']}"); - } - $db->sql_freeresult($result); -} - -/** -* Cleanly remove invalid user entries after converting the users table... -*/ -function remove_invalid_users() -{ - global $convert, $db; - - // username_clean is UNIQUE - $sql = 'SELECT user_id - FROM ' . USERS_TABLE . " - WHERE username_clean = ''"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if ($row) - { - if (!function_exists('user_delete')) - { - include(PHPBB_ROOT_PATH . 'includes/functions_user.' . PHP_EXT); - } - - user_delete('remove', $row['user_id']); - } -} - -function convert_bbcode($message, $convert_size = true, $extended_bbcodes = false) -{ - static $orig, $repl, $origx, $replx, $str_from, $str_to; - - if (empty($orig)) - { - $orig = $repl = array(); - - $orig[] = '#\[(php|sql)\](.*?)\[/(php|sql)\]#is'; - $repl[] = '[code]\2[/code]'; - - $orig[] = '#\[font=[^\]]+\](.*?)\[/font\]#is'; - $repl[] = '\1'; - - $orig[] = '#\[align=[a-z]+\](.*?)\[/align\]#is'; - $repl[] = '\1'; - - $orig[] = '#\[/list=.*?\]#is'; - $repl[] = '[/list]'; - - $origx = array( - '#\[glow[^\]]+\](.*?)\[/glow\]#is', - '#\[shadow[^\]]+\](.*?)\[/shadow\]#is', - '#\[flash[^\]]+\](.*?)\[/flash\]#is' - ); - - $replx = array( - '\1', - '\1', - '[url=\1]Flash[/url]' - ); - - $str_from = array( - '[ftp]', '[/ftp]', - '[ftp=', '[/ftp]', - '[pre]', '[/pre]', - '[table]', '[/table]', - '[td]', '[/td]', - '[tr]', '[/tr]', - '[s]', '[/s]', - '[left]', '[/left]', - '[right]', '[/right]', - '[center]', '[/center]', - '[sub]', '[/sub]', - '[sup]', '[/sup]', - '[tt]', '[/tt]', - '[move]', '[/move]', - '[hr]' - ); - - $str_to = array( - '[url]', '[/url]', - '[url=', '[/url]', - '[code]', '[/code]', - "\n", '', - '', '', - "\n", '', - '', '', - '', '', - '', '', - '', '', - '', '', - '', '', - '', '', - '', '', - "\n\n" - ); - - for ($i = 0; $i < sizeof($str_from); ++$i) - { - $origx[] = '#\\' . str_replace(']', '\\]', $str_from[$i]) . '#is'; - $replx[] = $str_to[$i]; - } - } - - if (preg_match_all('#\[email=([^\]]+)\](.*?)\[/email\]#i', $message, $m)) - { - for ($i = 0; $i < sizeof($m[1]); ++$i) - { - if ($m[1][$i] == $m[2][$i]) - { - $message = str_replace($m[0][$i], '[email]' . $m[1][$i] . '[/email]', $message); - } - else - { - $message = str_replace($m[0][$i], $m[2][$i] . ' ([email]' . $m[1][$i] . '[/email])', $message); - } - } - } - - if ($convert_size && preg_match('#\[size=[0-9]+\].*?\[/size\]#i', $message)) - { - $size = array(9, 9, 12, 15, 18, 24, 29, 29, 29, 29); - $message = preg_replace('#\[size=([0-9]+)\](.*?)\[/size\]#i', '[size=\1]\2[/size]', $message); - $message = preg_replace('#\[size=[0-9]{2,}\](.*?)\[/size\]#i', '[size=29]\1[/size]', $message); - - for ($i = sizeof($size); $i; ) - { - $i--; - $message = str_replace('[size=' . $i . ']', '[size=' . $size[$i] . ']', $message); - } - } - - if ($extended_bbcodes) - { - $message = preg_replace($origx, $replx, $message); - } - - $message = preg_replace($orig, $repl, $message); - return $message; -} - - -function copy_file($src, $trg, $overwrite = false, $die_on_failure = true, $source_relative_path = true) -{ - global $convert, $user, $db; - - if (substr($trg, -1) == '/') - { - $trg .= basename($src); - } - $src_path = relative_base($src, $source_relative_path, __LINE__, __FILE__); - $trg_path = $trg; - - if (!$overwrite && @file_exists($trg_path)) - { - return true; - } - - if (!@file_exists($src_path)) - { - return; - } - - $path = PHPBB_ROOT_PATH; - $parts = explode('/', $trg); - unset($parts[sizeof($parts) - 1]); - - for ($i = 0; $i < sizeof($parts); ++$i) - { - $path .= $parts[$i] . '/'; - - if (!is_dir($path)) - { - @mkdir($path, 0777); - } - } - - if (!is_writable($path)) - { - @chmod($path, 0777); - } - - if (!@copy($src_path, PHPBB_ROOT_PATH . $trg_path)) - { - $convert->p_master->error(sprintf($user->lang['COULD_NOT_COPY'], $src_path, PHPBB_ROOT_PATH . $trg_path), __LINE__, __FILE__, !$die_on_failure); - return; - } - - if ($perm = @fileperms($src_path)) - { - @chmod(PHPBB_ROOT_PATH . $trg_path, $perm); - } - - return true; -} - -function copy_dir($src, $trg, $copy_subdirs = true, $overwrite = false, $die_on_failure = true, $source_relative_path = true) -{ - global $convert, $user, $db; - - $dirlist = $filelist = $bad_dirs = array(); - $src = path($src, $source_relative_path); - $trg = path($trg); - $src_path = relative_base($src, $source_relative_path, __LINE__, __FILE__); - $trg_path = PHPBB_ROOT_PATH . $trg; - - if (!is_dir($trg_path)) - { - @mkdir($trg_path, 0777); - @chmod($trg_path, 0777); - } - - if (!@is_writable($trg_path)) - { - $bad_dirs[] = path(phpbb::$config['script_path']) . $trg; - } - - if ($handle = @opendir($src_path)) - { - while ($entry = readdir($handle)) - { - if ($entry[0] == '.' || $entry == 'CVS' || $entry == 'index.htm') - { - continue; - } - - if (is_dir($src_path . $entry)) - { - $dirlist[] = $entry; - } - else - { - $filelist[] = $entry; - } - } - closedir($handle); - } - else if ($dir = @dir($src_path)) - { - while ($entry = $dir->read()) - { - if ($entry[0] == '.' || $entry == 'CVS' || $entry == 'index.htm') - { - continue; - } - - if (is_dir($src_path . $entry)) - { - $dirlist[] = $entry; - } - else - { - $filelist[] = $entry; - } - } - $dir->close(); - } - else - { - $convert->p_master->error(sprintf($user->lang['CONV_ERROR_COULD_NOT_READ'], relative_base($src, $source_relative_path)), __LINE__, __FILE__); - } - - if ($copy_subdirs) - { - for ($i = 0; $i < sizeof($dirlist); ++$i) - { - $dir = $dirlist[$i]; - - if ($dir == 'CVS') - { - continue; - } - - if (!is_dir($trg_path . $dir)) - { - @mkdir($trg_path . $dir, 0777); - @chmod($trg_path . $dir, 0777); - } - - if (!@is_writable($trg_path . $dir)) - { - $bad_dirs[] = $trg . $dir; - $bad_dirs[] = $trg_path . $dir; - } - - if (!sizeof($bad_dirs)) - { - copy_dir($src . $dir, $trg . $dir, true, $overwrite, $die_on_failure, $source_relative_path); - } - } - } - - if (sizeof($bad_dirs)) - { - $str = (sizeof($bad_dirs) == 1) ? $user->lang['MAKE_FOLDER_WRITABLE'] : $user->lang['MAKE_FOLDERS_WRITABLE']; - sort($bad_dirs); - $convert->p_master->error(sprintf($str, implode('<br />', $bad_dirs)), __LINE__, __FILE__); - } - - for ($i = 0; $i < sizeof($filelist); ++$i) - { - copy_file($src . $filelist[$i], $trg . $filelist[$i], $overwrite, $die_on_failure, $source_relative_path); - } -} - -function relative_base($path, $is_relative = true, $line = false, $file = false) -{ - global $convert, $user, $db; - - if (!$is_relative) - { - return $path; - } - - if (empty($convert->options['forum_path']) && $is_relative) - { - $line = $line ? $line : __LINE__; - $file = $file ? $file : __FILE__; - - $convert->p_master->error($user->lang['CONV_ERROR_NO_FORUM_PATH'], $line, $file); - } - - return $convert->options['forum_path'] . '/' . $path; -} - -function get_smiley_display() -{ - static $smiley_count = 0; - $smiley_count++; - return ($smiley_count < 50) ? 1 : 0; -} - - -function fill_dateformat($user_dateformat) -{ - return ((empty($user_dateformat)) ? phpbb::$config['default_dateformat'] : $user_dateformat); -} - - - -?>
\ No newline at end of file diff --git a/phpBB/includes/functions_display.php b/phpBB/includes/functions_display.php deleted file mode 100644 index cf12a60aec..0000000000 --- a/phpBB/includes/functions_display.php +++ /dev/null @@ -1,1202 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Display Forums -*/ -function display_forums($root_data = '', $display_moderators = true, $return_moderators = false) -{ - $forum_rows = $subforums = $forum_ids = $forum_ids_moderator = $forum_moderators = $active_forum_ary = array(); - $parent_id = $visible_forums = 0; - $sql_from = ''; - - // Mark forums read? - $mark_read = request_var('mark', ''); - - if ($mark_read == 'all') - { - $mark_read = ''; - } - - if (!$root_data) - { - if ($mark_read == 'forums') - { - $mark_read = 'all'; - } - - $root_data = array('forum_id' => 0); - $sql_where = ''; - } - else - { - $sql_where = 'left_id > ' . $root_data['left_id'] . ' AND left_id < ' . $root_data['right_id']; - } - - // Display list of active topics for this category? - $show_active = (isset($root_data['forum_flags']) && ($root_data['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS)) ? true : false; - - $sql_array = array( - 'SELECT' => 'f.*', - 'FROM' => array( - FORUMS_TABLE => 'f' - ), - 'LEFT_JOIN' => array(), - ); - - if (phpbb::$config['load_db_lastread'] && phpbb::$user->is_registered) - { - $sql_array['LEFT_JOIN'][] = array('FROM' => array(FORUMS_TRACK_TABLE => 'ft'), 'ON' => 'ft.user_id = ' . phpbb::$user->data['user_id'] . ' AND ft.forum_id = f.forum_id'); - $sql_array['SELECT'] .= ', ft.mark_time'; - } - else if (phpbb::$config['load_anon_lastread'] || phpbb::$user->is_registered) - { - $tracking_topics = request::variable(phpbb::$config['cookie_name'] . '_track', '', false, request::COOKIE); - $tracking_topics = ($tracking_topics) ? tracking_unserialize($tracking_topics) : array(); - - if (!phpbb::$user->is_registered) - { - phpbb::$user->data['user_lastmark'] = (isset($tracking_topics['l'])) ? (int) (base_convert($tracking_topics['l'], 36, 10) + phpbb::$config['board_startdate']) : 0; - } - } - - if ($show_active) - { - $sql_array['LEFT_JOIN'][] = array( - 'FROM' => array(FORUMS_ACCESS_TABLE => 'fa'), - 'ON' => "fa.forum_id = f.forum_id AND fa.session_id = '" . phpbb::$db->sql_escape(phpbb::$user->session_id) . "'" - ); - - $sql_array['SELECT'] .= ', fa.user_id'; - } - - $sql = phpbb::$db->sql_build_query('SELECT', array( - 'SELECT' => $sql_array['SELECT'], - 'FROM' => $sql_array['FROM'], - 'LEFT_JOIN' => $sql_array['LEFT_JOIN'], - - 'WHERE' => $sql_where, - - 'ORDER_BY' => 'f.left_id', - )); - - $result = phpbb::$db->sql_query($sql); - - $forum_tracking_info = array(); - $branch_root_id = $root_data['forum_id']; - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $forum_id = $row['forum_id']; - - // Mark forums read? - if ($mark_read == 'forums' || $mark_read == 'all') - { - if (phpbb::$acl->acl_get('f_list', $forum_id)) - { - $forum_ids[] = $forum_id; - continue; - } - } - - // Category with no members - if ($row['forum_type'] == FORUM_CAT && ($row['left_id'] + 1 == $row['right_id'])) - { - continue; - } - - // Skip branch - if (isset($right_id)) - { - if ($row['left_id'] < $right_id) - { - continue; - } - unset($right_id); - } - - if (!phpbb::$acl->acl_get('f_list', $forum_id)) - { - // if the user does not have permissions to list this forum, skip everything until next branch - $right_id = $row['right_id']; - continue; - } - - $forum_ids[] = $forum_id; - - if (phpbb::$config['load_db_lastread'] && phpbb::$user->is_registered) - { - $forum_tracking_info[$forum_id] = (!empty($row['mark_time'])) ? $row['mark_time'] : phpbb::$user->data['user_lastmark']; - } - else if (phpbb::$config['load_anon_lastread'] || phpbb::$user->is_registered) - { - if (!phpbb::$user->is_registered) - { - phpbb::$user->data['user_lastmark'] = (isset($tracking_topics['l'])) ? (int) (base_convert($tracking_topics['l'], 36, 10) + phpbb::$config['board_startdate']) : 0; - } - $forum_tracking_info[$forum_id] = (isset($tracking_topics['f'][$forum_id])) ? (int) (base_convert($tracking_topics['f'][$forum_id], 36, 10) + phpbb::$config['board_startdate']) : phpbb::$user->data['user_lastmark']; - } - - $row['forum_topics'] = (phpbb::$acl->acl_get('m_approve', $forum_id)) ? $row['forum_topics_real'] : $row['forum_topics']; - - // Display active topics from this forum? - if ($show_active && $row['forum_type'] == FORUM_POST && phpbb::$acl->acl_get('f_read', $forum_id) && ($row['forum_flags'] & FORUM_FLAG_ACTIVE_TOPICS)) - { - if (!isset($active_forum_ary['forum_topics'])) - { - $active_forum_ary['forum_topics'] = 0; - } - - if (!isset($active_forum_ary['forum_posts'])) - { - $active_forum_ary['forum_posts'] = 0; - } - - $active_forum_ary['forum_id'][] = $forum_id; - $active_forum_ary['enable_icons'][] = $row['enable_icons']; - $active_forum_ary['forum_topics'] += $row['forum_topics']; - $active_forum_ary['forum_posts'] += $row['forum_posts']; - - // If this is a passworded forum we do not show active topics from it if the user is not authorised to view it... - if ($row['forum_password'] && $row['user_id'] != phpbb::$user->data['user_id']) - { - $active_forum_ary['exclude_forum_id'][] = $forum_id; - } - } - - // - if ($row['parent_id'] == $root_data['forum_id'] || $row['parent_id'] == $branch_root_id) - { - if ($row['forum_type'] != FORUM_CAT) - { - $forum_ids_moderator[] = (int) $forum_id; - } - - // Direct child of current branch - $parent_id = $forum_id; - $forum_rows[$forum_id] = $row; - - if ($row['forum_type'] == FORUM_CAT && $row['parent_id'] == $root_data['forum_id']) - { - $branch_root_id = $forum_id; - } - $forum_rows[$parent_id]['forum_id_last_post'] = $row['forum_id']; - $forum_rows[$parent_id]['orig_forum_last_post_time'] = $row['forum_last_post_time']; - } - else if ($row['forum_type'] != FORUM_CAT) - { - $subforums[$parent_id][$forum_id]['display'] = ($row['display_on_index']) ? true : false; - $subforums[$parent_id][$forum_id]['name'] = $row['forum_name']; - $subforums[$parent_id][$forum_id]['orig_forum_last_post_time'] = $row['forum_last_post_time']; - $subforums[$parent_id][$forum_id]['children'] = array(); - - if (isset($subforums[$parent_id][$row['parent_id']]) && !$row['display_on_index']) - { - $subforums[$parent_id][$row['parent_id']]['children'][] = $forum_id; - } - - $forum_rows[$parent_id]['forum_topics'] += $row['forum_topics']; - - // Do not list redirects in LINK Forums as Posts. - if ($row['forum_type'] != FORUM_LINK) - { - $forum_rows[$parent_id]['forum_posts'] += $row['forum_posts']; - } - - if ($row['forum_last_post_time'] > $forum_rows[$parent_id]['forum_last_post_time']) - { - $forum_rows[$parent_id]['forum_last_post_id'] = $row['forum_last_post_id']; - $forum_rows[$parent_id]['forum_last_post_subject'] = $row['forum_last_post_subject']; - $forum_rows[$parent_id]['forum_last_post_time'] = $row['forum_last_post_time']; - $forum_rows[$parent_id]['forum_last_poster_id'] = $row['forum_last_poster_id']; - $forum_rows[$parent_id]['forum_last_poster_name'] = $row['forum_last_poster_name']; - $forum_rows[$parent_id]['forum_last_poster_colour'] = $row['forum_last_poster_colour']; - $forum_rows[$parent_id]['forum_id_last_post'] = $forum_id; - } - } - } - phpbb::$db->sql_freeresult($result); - - // Handle marking posts - if ($mark_read == 'forums' || $mark_read == 'all') - { - $redirect = phpbb::$url->build_url(array('mark', 'hash')); - $token = request_var('hash', ''); - - if (phpbb::$security->check_link($token, 'global')) - { - if ($mark_read == 'all') - { - markread('all'); - $message = phpbb::$user->lang('RETURN_INDEX', '<a href="' . $redirect . '">', '</a>'); - } - else - { - markread('topics', $forum_ids); - $message = phpbb::$user->lang('RETURN_FORUM', '<a href="' . $redirect . '">', '</a>'); - } - meta_refresh(3, $redirect); - trigger_error(phpbb::$user->lang['FORUMS_MARKED'] . '<br /><br />' . $message); - } - else - { - $message = phpbb::$user->lang('RETURN_PAGE', '<a href="' . $redirect . '">', '</a>'); - phpbb::$url->meta_refresh(3, $redirect); - trigger_error($message); - } - } - - // Grab moderators ... if necessary - if ($display_moderators) - { - if ($return_moderators) - { - $forum_ids_moderator[] = $root_data['forum_id']; - } - get_moderators($forum_moderators, $forum_ids_moderator); - } - - // Used to tell whatever we have to create a dummy category or not. - $last_catless = true; - foreach ($forum_rows as $row) - { - // Empty category - if ($row['parent_id'] == $root_data['forum_id'] && $row['forum_type'] == FORUM_CAT) - { - phpbb::$template->assign_block_vars('forumrow', array( - 'S_IS_CAT' => true, - 'FORUM_ID' => $row['forum_id'], - 'FORUM_NAME' => $row['forum_name'], - 'FORUM_DESC' => generate_text_for_display($row['forum_desc'], $row['forum_desc_uid'], $row['forum_desc_bitfield'], $row['forum_desc_options']), - 'FORUM_FOLDER_IMG' => '', - 'FORUM_FOLDER_IMG_SRC' => '', - 'FORUM_IMAGE' => ($row['forum_image']) ? '<img src="' . PHPBB_ROOT_PATH . $row['forum_image'] . '" alt="' . phpbb::$user->lang['FORUM_CAT'] . '" />' : '', - 'FORUM_IMAGE_SRC' => ($row['forum_image']) ? PHPBB_ROOT_PATH . $row['forum_image'] : '', - 'U_VIEWFORUM' => phpbb::$url->append_sid('viewforum', 'f=' . $row['forum_id']), - )); - - continue; - } - - $visible_forums++; - $forum_id = $row['forum_id']; - - $forum_unread = (isset($forum_tracking_info[$forum_id]) && $row['orig_forum_last_post_time'] > $forum_tracking_info[$forum_id]) ? true : false; - - $folder_image = $folder_alt = $l_subforums = ''; - $subforums_list = array(); - - // Generate list of subforums if we need to - if (isset($subforums[$forum_id])) - { - foreach ($subforums[$forum_id] as $subforum_id => $subforum_row) - { - $subforum_unread = (isset($forum_tracking_info[$subforum_id]) && $subforum_row['orig_forum_last_post_time'] > $forum_tracking_info[$subforum_id]) ? true : false; - - if (!$subforum_unread && !empty($subforum_row['children'])) - { - foreach ($subforum_row['children'] as $child_id) - { - if (isset($forum_tracking_info[$child_id]) && $subforums[$forum_id][$child_id]['orig_forum_last_post_time'] > $forum_tracking_info[$child_id]) - { - // Once we found an unread child forum, we can drop out of this loop - $subforum_unread = true; - break; - } - } - } - - if ($subforum_row['display'] && $subforum_row['name']) - { - $subforums_list[] = array( - 'link' => phpbb::$url->append_sid('viewforum', 'f=' . $subforum_id), - 'name' => $subforum_row['name'], - 'unread' => $subforum_unread, - ); - } - else - { - unset($subforums[$forum_id][$subforum_id]); - } - - // If one subforum is unread the forum gets unread too... - if ($subforum_unread) - { - $forum_unread = true; - } - } - - $folder_image = ($forum_unread) ? 'forum_unread_subforum' : 'forum_read_subforum'; - } - else - { - switch ($row['forum_type']) - { - case FORUM_POST: - $folder_image = ($forum_unread) ? 'forum_unread' : 'forum_read'; - break; - - case FORUM_LINK: - $folder_image = 'forum_link'; - break; - } - } - - // Which folder should we display? - if ($row['forum_status'] == ITEM_LOCKED) - { - $folder_image = ($forum_unread) ? 'forum_unread_locked' : 'forum_read_locked'; - $folder_alt = 'FORUM_LOCKED'; - } - else - { - $folder_alt = ($forum_unread) ? 'NEW_POSTS' : 'NO_NEW_POSTS'; - } - - // Create last post link information, if appropriate - if ($row['forum_last_post_id']) - { - $last_post_subject = $row['forum_last_post_subject']; - $last_post_time = phpbb::$user->format_date($row['forum_last_post_time']); - $last_post_url = phpbb::$url->append_sid('viewtopic', 'f=' . $row['forum_id_last_post'] . '&p=' . $row['forum_last_post_id']) . '#p' . $row['forum_last_post_id']; - } - else - { - $last_post_subject = $last_post_time = $last_post_url = ''; - } - - // Output moderator listing ... if applicable - $moderators_list = array(); - if ($display_moderators && !empty($forum_moderators[$forum_id])) - { - $moderators_list = $forum_moderators[$forum_id]; - } - - $l_post_click_count = ($row['forum_type'] == FORUM_LINK) ? 'CLICKS' : 'POSTS'; - $post_click_count = ($row['forum_type'] != FORUM_LINK || $row['forum_flags'] & FORUM_FLAG_LINK_TRACK) ? $row['forum_posts'] : ''; - - $s_subforums_list = array(); - foreach ($subforums_list as $subforum) - { - $s_subforums_list[] = '<a href="' . $subforum['link'] . '" class="subforum ' . (($subforum['unread']) ? 'unread' : 'read') . '" title="' . (($subforum['unread']) ? phpbb::$user->lang['NEW_POSTS'] : phpbb::$user->lang['NO_NEW_POSTS']) . '">' . $subforum['name'] . '</a>'; - } - $s_subforums_list = (string) implode(', ', $s_subforums_list); - $catless = ($row['parent_id'] == $root_data['forum_id']) ? true : false; - - if ($row['forum_type'] != FORUM_LINK) - { - $u_viewforum = phpbb::$url->append_sid('viewforum', 'f=' . $row['forum_id']); - } - else - { - // If the forum is a link and we count redirects we need to visit it - // If the forum is having a password or no read access we do not expose the link, but instead handle it in viewforum - if (($row['forum_flags'] & FORUM_FLAG_LINK_TRACK) || $row['forum_password'] || !phpbb::$acl->acl_get('f_read', $forum_id)) - { - $u_viewforum = phpbb::$url->append_sid('viewforum', 'f=' . $row['forum_id']); - } - else - { - $u_viewforum = $row['forum_link']; - } - } - - phpbb::$template->assign_block_vars('forumrow', array( - 'S_IS_CAT' => false, - 'S_NO_CAT' => $catless && !$last_catless, - 'S_IS_LINK' => ($row['forum_type'] == FORUM_LINK) ? true : false, - 'S_UNREAD_FORUM' => $forum_unread, - 'S_LOCKED_FORUM' => ($row['forum_status'] == ITEM_LOCKED) ? true : false, - 'S_LIST_SUBFORUMS' => ($row['display_subforum_list']) ? true : false, - 'S_SUBFORUMS' => (sizeof($subforums_list)) ? true : false, - - 'FORUM_ID' => $row['forum_id'], - 'FORUM_NAME' => $row['forum_name'], - 'FORUM_DESC' => generate_text_for_display($row['forum_desc'], $row['forum_desc_uid'], $row['forum_desc_bitfield'], $row['forum_desc_options']), - 'TOPICS' => $row['forum_topics'], - $l_post_click_count => $post_click_count, - 'FORUM_FOLDER_IMG' => phpbb::$user->img($folder_image, $folder_alt), - 'FORUM_FOLDER_IMG_SRC' => phpbb::$user->img($folder_image, $folder_alt, 'src'), - 'FORUM_FOLDER_IMG_ALT' => isset(phpbb::$user->lang[$folder_alt]) ? phpbb::$user->lang[$folder_alt] : '', - 'FORUM_IMAGE' => ($row['forum_image']) ? '<img src="' . PHPBB_ROOT_PATH . $row['forum_image'] . '" alt="' . phpbb::$user->lang[$folder_alt] . '" />' : '', - 'FORUM_IMAGE_SRC' => ($row['forum_image']) ? PHPBB_ROOT_PATH . $row['forum_image'] : '', - 'LAST_POST_SUBJECT' => censor_text($last_post_subject), - 'LAST_POST_TIME' => $last_post_time, - 'LAST_POSTER' => get_username_string('username', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']), - 'LAST_POSTER_COLOUR' => get_username_string('colour', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']), - 'LAST_POSTER_FULL' => get_username_string('full', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']), - 'MODERATORS' => implode(', ', $moderators_list), - 'SUBFORUMS' => $s_subforums_list, - - 'L_SUBFORUM_STR' => phpbb::$user->lang('SUBFORUMS', sizeof($subforums_list)), - 'L_FORUM_FOLDER_ALT' => $folder_alt, - 'L_MODERATOR_STR' => phpbb::$user->lang('MODERATORS', sizeof($moderators_list)), - - 'U_VIEWFORUM' => $u_viewforum, - 'U_LAST_POSTER' => get_username_string('profile', $row['forum_last_poster_id'], $row['forum_last_poster_name'], $row['forum_last_poster_colour']), - 'U_LAST_POST' => $last_post_url, - )); - - // Assign subforums loop for style authors - foreach ($subforums_list as $subforum) - { - phpbb::$template->assign_block_vars('forumrow.subforum', array( - 'U_SUBFORUM' => $subforum['link'], - 'SUBFORUM_NAME' => $subforum['name'], - 'S_UNREAD' => $subforum['unread'], - )); - } - - $last_catless = $catless; - } - - phpbb::$template->assign_vars(array( - 'U_MARK_FORUMS' => (phpbb::$user->is_registered || phpbb::$config['load_anon_lastread']) ? phpbb::$url->append_sid('viewforum', 'hash=' . generate_link_hash('global') . '&f=' . $root_data['forum_id'] . '&mark=forums') : '', - 'S_HAS_SUBFORUM' => ($visible_forums) ? true : false, - 'L_SUBFORUM' => phpbb::$user->lang('SUBFORUMS', $visible_forums), - 'LAST_POST_IMG' => phpbb::$user->img('icon_topic_latest', 'VIEW_LATEST_POST'), - )); - - if ($return_moderators) - { - return array($active_forum_ary, $forum_moderators); - } - - return array($active_forum_ary, array()); -} - -/** -* Create forum rules for given forum -*/ -function generate_forum_rules(&$forum_data) -{ - if (!$forum_data['forum_rules'] && !$forum_data['forum_rules_link']) - { - return; - } - - if ($forum_data['forum_rules']) - { - $forum_data['forum_rules'] = generate_text_for_display($forum_data['forum_rules'], $forum_data['forum_rules_uid'], $forum_data['forum_rules_bitfield'], $forum_data['forum_rules_options']); - } - - phpbb::$template->assign_vars(array( - 'S_FORUM_RULES' => true, - 'U_FORUM_RULES' => $forum_data['forum_rules_link'], - 'FORUM_RULES' => $forum_data['forum_rules'], - )); -} - -/** -* Create forum navigation links for given forum, create parent -* list if currently null, assign basic forum info to template -*/ -function generate_forum_nav(&$forum_data) -{ - if (!phpbb::$acl->acl_get('f_list', $forum_data['forum_id'])) - { - return; - } - - // Get forum parents - $forum_parents = get_forum_parents($forum_data); - - // Build navigation links - if (!empty($forum_parents)) - { - foreach ($forum_parents as $parent_forum_id => $parent_data) - { - list($parent_name, $parent_type) = array_values($parent_data); - - // Skip this parent if the user does not have the permission to view it - if (!phpbb::$acl->acl_get('f_list', $parent_forum_id)) - { - continue; - } - - phpbb::$template->assign_block_vars('navlinks', array( - 'S_IS_CAT' => ($parent_type == FORUM_CAT) ? true : false, - 'S_IS_LINK' => ($parent_type == FORUM_LINK) ? true : false, - 'S_IS_POST' => ($parent_type == FORUM_POST) ? true : false, - 'FORUM_NAME' => $parent_name, - 'FORUM_ID' => $parent_forum_id, - 'U_VIEW_FORUM' => phpbb::$url->append_sid('viewforum', 'f=' . $parent_forum_id), - )); - } - } - - phpbb::$template->assign_block_vars('navlinks', array( - 'S_IS_CAT' => ($forum_data['forum_type'] == FORUM_CAT) ? true : false, - 'S_IS_LINK' => ($forum_data['forum_type'] == FORUM_LINK) ? true : false, - 'S_IS_POST' => ($forum_data['forum_type'] == FORUM_POST) ? true : false, - 'FORUM_NAME' => $forum_data['forum_name'], - 'FORUM_ID' => $forum_data['forum_id'], - 'U_VIEW_FORUM' => phpbb::$url->append_sid('viewforum', 'f=' . $forum_data['forum_id']), - )); - - phpbb::$template->assign_vars(array( - 'FORUM_ID' => $forum_data['forum_id'], - 'FORUM_NAME' => $forum_data['forum_name'], - 'FORUM_DESC' => generate_text_for_display($forum_data['forum_desc'], $forum_data['forum_desc_uid'], $forum_data['forum_desc_bitfield'], $forum_data['forum_desc_options']), - )); - - return; -} - -/** -* Returns forum parents as an array. Get them from forum_data if available, or update the database otherwise -*/ -function get_forum_parents(&$forum_data) -{ - $forum_parents = array(); - - if ($forum_data['parent_id'] > 0) - { - if ($forum_data['forum_parents'] == '') - { - $sql = 'SELECT forum_id, forum_name, forum_type - FROM ' . FORUMS_TABLE . ' - WHERE left_id < ' . $forum_data['left_id'] . ' - AND right_id > ' . $forum_data['right_id'] . ' - ORDER BY left_id ASC'; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $forum_parents[$row['forum_id']] = array($row['forum_name'], (int) $row['forum_type']); - } - phpbb::$db->sql_freeresult($result); - - $forum_data['forum_parents'] = serialize($forum_parents); - - $sql = 'UPDATE ' . FORUMS_TABLE . " - SET forum_parents = '" . phpbb::$db->sql_escape($forum_data['forum_parents']) . "' - WHERE parent_id = " . $forum_data['parent_id']; - phpbb::$db->sql_query($sql); - } - else - { - $forum_parents = unserialize($forum_data['forum_parents']); - } - } - - return $forum_parents; -} - -/** -* Generate topic pagination -*/ -function topic_generate_pagination($replies, $url) -{ - // Make sure $per_page is a valid value - $per_page = (phpbb::$config['posts_per_page'] <= 0) ? 1 : phpbb::$config['posts_per_page']; - - if (($replies + 1) > $per_page) - { - $total_pages = ceil(($replies + 1) / $per_page); - $pagination = ''; - - $times = 1; - for ($j = 0; $j < $replies + 1; $j += $per_page) - { - $pagination .= '<a href="' . $url . '&start=' . $j . '">' . $times . '</a>'; - if ($times == 1 && $total_pages > 5) - { - $pagination .= ' ... '; - - // Display the last three pages - $times = $total_pages - 3; - $j += ($total_pages - 4) * $per_page; - } - else if ($times < $total_pages) - { - $pagination .= '<span class="page-sep">' . phpbb::$user->lang['COMMA_SEPARATOR'] . '</span>'; - } - $times++; - } - } - else - { - $pagination = ''; - } - - return $pagination; -} - -/** -* Obtain list of moderators of each forum -*/ -function get_moderators(&$forum_moderators, $forum_id = false) -{ - // Have we disabled the display of moderators? If so, then return - // from whence we came ... - if (!phpbb::$config['load_moderators']) - { - return; - } - - $forum_sql = ''; - - if ($forum_id !== false) - { - if (!is_array($forum_id)) - { - $forum_id = array($forum_id); - } - - // If we don't have a forum then we can't have a moderator - if (!sizeof($forum_id)) - { - return; - } - - $forum_sql = 'AND m.' . phpbb::$db->sql_in_set('forum_id', $forum_id); - } - - $sql_array = array( - 'SELECT' => 'm.*, u.user_colour, g.group_colour, g.group_type', - - 'FROM' => array( - MODERATOR_CACHE_TABLE => 'm', - ), - - 'LEFT_JOIN' => array( - array( - 'FROM' => array(USERS_TABLE => 'u'), - 'ON' => 'm.user_id = u.user_id', - ), - array( - 'FROM' => array(GROUPS_TABLE => 'g'), - 'ON' => 'm.group_id = g.group_id', - ), - ), - - 'WHERE' => "m.display_on_index = 1 $forum_sql", - ); - - $sql = phpbb::$db->sql_build_query('SELECT', $sql_array); - $result = phpbb::$db->sql_query($sql, 3600); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if (!empty($row['user_id'])) - { - $forum_moderators[$row['forum_id']][] = get_username_string('full', $row['user_id'], $row['username'], $row['user_colour']); - } - else - { - $group_name = (($row['group_type'] == GROUP_SPECIAL) ? phpbb::$user->lang['G_' . $row['group_name']] : $row['group_name']); - - if (!phpbb::$user->is_guest && !phpbb::$acl->acl_get('u_viewprofile')) - { - $forum_moderators[$row['forum_id']][] = '<span' . (($row['group_colour']) ? ' style="color:#' . $row['group_colour'] . ';"' : '') . '>' . $group_name . '</span>'; - } - else - { - $forum_moderators[$row['forum_id']][] = '<a' . (($row['group_colour']) ? ' style="color:#' . $row['group_colour'] . ';"' : '') . ' href="' . phpbb::$url->append_sid('memberlist', 'mode=group&g=' . $row['group_id']) . '">' . $group_name . '</a>'; - } - } - } - phpbb::$db->sql_freeresult($result); - - return; -} - -/** -* User authorisation levels output -* -* @param string $mode Can be forum or topic. Not in use at the moment. -* @param int $forum_id The current forum the user is in. -* @param int $forum_status The forums status bit. -*/ -function gen_forum_auth_level($mode, $forum_id, $forum_status) -{ - $locked = ($forum_status == ITEM_LOCKED && !phpbb::$acl->acl_get('m_edit', $forum_id)) ? true : false; - - $rules = array( - (phpbb::$acl->acl_get('f_post', $forum_id) && !$locked) ? phpbb::$user->lang['RULES_POST_CAN'] : phpbb::$user->lang['RULES_POST_CANNOT'], - (phpbb::$acl->acl_get('f_reply', $forum_id) && !$locked) ? phpbb::$user->lang['RULES_REPLY_CAN'] : phpbb::$user->lang['RULES_REPLY_CANNOT'], - (phpbb::$user->is_registered && phpbb::$acl->acl_gets('f_edit', 'm_edit', $forum_id) && !$locked) ? phpbb::$user->lang['RULES_EDIT_CAN'] : phpbb::$user->lang['RULES_EDIT_CANNOT'], - (phpbb::$user->is_registered && phpbb::$acl->acl_gets('f_delete', 'm_delete', $forum_id) && !$locked) ? phpbb::$user->lang['RULES_DELETE_CAN'] : phpbb::$user->lang['RULES_DELETE_CANNOT'], - ); - - if (phpbb::$config['allow_attachments']) - { - $rules[] = (phpbb::$acl->acl_get('f_attach', $forum_id) && phpbb::$acl->acl_get('u_attach') && !$locked) ? phpbb::$user->lang['RULES_ATTACH_CAN'] : phpbb::$user->lang['RULES_ATTACH_CANNOT']; - } - - foreach ($rules as $rule) - { - phpbb::$template->assign_block_vars('rules', array('RULE' => $rule)); - } - - return; -} - -/** -* Generate topic status -*/ -function topic_status(&$topic_row, $replies, $unread_topic, &$folder_img, &$folder_alt, &$topic_type) -{ - $folder = $folder_new = ''; - - if ($topic_row['topic_status'] == ITEM_MOVED) - { - $topic_type = phpbb::$user->lang['VIEW_TOPIC_MOVED']; - $folder_img = 'topic_moved'; - $folder_alt = 'TOPIC_MOVED'; - } - else - { - switch ($topic_row['topic_type']) - { - case POST_GLOBAL: - $topic_type = phpbb::$user->lang['VIEW_TOPIC_GLOBAL']; - $folder = 'global_read'; - $folder_new = 'global_unread'; - break; - - case POST_ANNOUNCE: - $topic_type = phpbb::$user->lang['VIEW_TOPIC_ANNOUNCEMENT']; - $folder = 'announce_read'; - $folder_new = 'announce_unread'; - break; - - case POST_STICKY: - $topic_type = phpbb::$user->lang['VIEW_TOPIC_STICKY']; - $folder = 'sticky_read'; - $folder_new = 'sticky_unread'; - break; - - default: - $topic_type = ''; - $folder = 'topic_read'; - $folder_new = 'topic_unread'; - - // Hot topic threshold is for posts in a topic, which is replies + the first post. ;) - if (phpbb::$config['hot_threshold'] && ($replies + 1) >= phpbb::$config['hot_threshold'] && $topic_row['topic_status'] != ITEM_LOCKED) - { - $folder .= '_hot'; - $folder_new .= '_hot'; - } - break; - } - - if ($topic_row['topic_status'] == ITEM_LOCKED) - { - $topic_type = phpbb::$user->lang['VIEW_TOPIC_LOCKED']; - $folder .= '_locked'; - $folder_new .= '_locked'; - } - - - $folder_img = ($unread_topic) ? $folder_new : $folder; - $folder_alt = ($unread_topic) ? 'NEW_POSTS' : (($topic_row['topic_status'] == ITEM_LOCKED) ? 'TOPIC_LOCKED' : 'NO_NEW_POSTS'); - - // Posted image? - if (!empty($topic_row['topic_posted']) && $topic_row['topic_posted']) - { - $folder_img .= '_mine'; - } - } - - if ($topic_row['poll_start'] && $topic_row['topic_status'] != ITEM_MOVED) - { - $topic_type = phpbb::$user->lang['VIEW_TOPIC_POLL']; - } -} - -/** -* Assign/Build custom bbcodes for display in screens supporting using of bbcodes -* The custom bbcodes buttons will be placed within the template block 'custom_codes' -*/ -function display_custom_bbcodes() -{ - // Start counting from 22 for the bbcode ids (every bbcode takes two ids - opening/closing) - $num_predefined_bbcodes = 22; - - $sql = 'SELECT bbcode_id, bbcode_tag, bbcode_helpline - FROM ' . BBCODES_TABLE . ' - WHERE display_on_posting = 1 - ORDER BY bbcode_tag'; - $result = phpbb::$db->sql_query($sql); - - $i = 0; - while ($row = phpbb::$db->sql_fetchrow($result)) - { - // If the helpline is defined within the language file, we will use the localised version, else just use the database entry... - if (isset(phpbb::$user->lang[strtoupper($row['bbcode_helpline'])])) - { - $row['bbcode_helpline'] = phpbb::$user->lang[strtoupper($row['bbcode_helpline'])]; - } - - phpbb::$template->assign_block_vars('custom_tags', array( - 'BBCODE_NAME' => "'[{$row['bbcode_tag']}]', '[/" . str_replace('=', '', $row['bbcode_tag']) . "]'", - 'BBCODE_ID' => $num_predefined_bbcodes + ($i * 2), - 'BBCODE_TAG' => $row['bbcode_tag'], - 'BBCODE_HELPLINE' => $row['bbcode_helpline'], - 'A_BBCODE_HELPLINE' => str_replace(array('&', '"', "'", '<', '>'), array('&', '"', "\'", '<', '>'), $row['bbcode_helpline']), - )); - - $i++; - } - phpbb::$db->sql_freeresult($result); -} - -/** -* Display reasons -*/ -function display_reasons($reason_id = 0) -{ - $sql = 'SELECT * - FROM ' . REPORTS_REASONS_TABLE . ' - ORDER BY reason_order ASC'; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - // If the reason is defined within the language file, we will use the localized version, else just use the database entry... - if (isset(phpbb::$user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]) && isset(phpbb::$user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])])) - { - $row['reason_description'] = phpbb::$user->lang['report_reasons']['DESCRIPTION'][strtoupper($row['reason_title'])]; - $row['reason_title'] = phpbb::$user->lang['report_reasons']['TITLE'][strtoupper($row['reason_title'])]; - } - - phpbb::$template->assign_block_vars('reason', array( - 'ID' => $row['reason_id'], - 'TITLE' => $row['reason_title'], - 'DESCRIPTION' => $row['reason_description'], - 'S_SELECTED' => ($row['reason_id'] == $reason_id) ? true : false, - )); - } - phpbb::$db->sql_freeresult($result); -} - -/** -* Display user activity (action forum/topic) -*/ -function display_user_activity(&$userdata) -{ - // Do not display user activity for users having more than 5000 posts... - if ($userdata['user_posts'] > 5000) - { - return; - } - - $forum_ary = array(); - - // Do not include those forums the user is not having read access to... - $forum_read_ary = phpbb::$acl->acl_getf('!f_read'); - - foreach ($forum_read_ary as $forum_id => $not_allowed) - { - if ($not_allowed['f_read']) - { - $forum_ary[] = (int) $forum_id; - } - } - - $forum_ary = array_unique($forum_ary); - $forum_sql = (sizeof($forum_ary)) ? 'AND ' . phpbb::$db->sql_in_set('forum_id', $forum_ary, true) : ''; - - // Obtain active forum - $sql = 'SELECT forum_id, COUNT(post_id) AS num_posts - FROM ' . POSTS_TABLE . ' - WHERE poster_id = ' . $userdata['user_id'] . " - AND post_postcount = 1 - $forum_sql - GROUP BY forum_id - ORDER BY num_posts DESC"; - $result = phpbb::$db->sql_query_limit($sql, 1); - $active_f_row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if (!empty($active_f_row)) - { - $sql = 'SELECT forum_name - FROM ' . FORUMS_TABLE . ' - WHERE forum_id = ' . $active_f_row['forum_id']; - $result = phpbb::$db->sql_query($sql, 3600); - $active_f_row['forum_name'] = (string) phpbb::$db->sql_fetchfield('forum_name'); - phpbb::$db->sql_freeresult($result); - } - - // Obtain active topic - $sql = 'SELECT topic_id, COUNT(post_id) AS num_posts - FROM ' . POSTS_TABLE . ' - WHERE poster_id = ' . $userdata['user_id'] . " - AND post_postcount = 1 - $forum_sql - GROUP BY topic_id - ORDER BY num_posts DESC"; - $result = phpbb::$db->sql_query_limit($sql, 1); - $active_t_row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if (!empty($active_t_row)) - { - $sql = 'SELECT topic_title - FROM ' . TOPICS_TABLE . ' - WHERE topic_id = ' . $active_t_row['topic_id']; - $result = phpbb::$db->sql_query($sql); - $active_t_row['topic_title'] = (string) phpbb::$db->sql_fetchfield('topic_title'); - phpbb::$db->sql_freeresult($result); - } - - $userdata['active_t_row'] = $active_t_row; - $userdata['active_f_row'] = $active_f_row; - - $active_f_name = $active_f_id = $active_f_count = $active_f_pct = ''; - if (!empty($active_f_row['num_posts'])) - { - $active_f_name = $active_f_row['forum_name']; - $active_f_id = $active_f_row['forum_id']; - $active_f_count = $active_f_row['num_posts']; - $active_f_pct = ($userdata['user_posts']) ? ($active_f_count / $userdata['user_posts']) * 100 : 0; - } - - $active_t_name = $active_t_id = $active_t_count = $active_t_pct = ''; - if (!empty($active_t_row['num_posts'])) - { - $active_t_name = $active_t_row['topic_title']; - $active_t_id = $active_t_row['topic_id']; - $active_t_count = $active_t_row['num_posts']; - $active_t_pct = ($userdata['user_posts']) ? ($active_t_count / $userdata['user_posts']) * 100 : 0; - } - - $l_active_pct = ($userdata['user_id'] != ANONYMOUS && $userdata['user_id'] == phpbb::$user->data['user_id']) ? phpbb::$user->lang['POST_PCT_ACTIVE_OWN'] : phpbb::$user->lang['POST_PCT_ACTIVE']; - - phpbb::$template->assign_vars(array( - 'ACTIVE_FORUM' => $active_f_name, - 'ACTIVE_FORUM_POSTS' => ($active_f_count == 1) ? sprintf(phpbb::$user->lang['USER_POST'], 1) : sprintf(phpbb::$user->lang['USER_POSTS'], $active_f_count), - 'ACTIVE_FORUM_PCT' => sprintf($l_active_pct, $active_f_pct), - 'ACTIVE_TOPIC' => censor_text($active_t_name), - 'ACTIVE_TOPIC_POSTS' => ($active_t_count == 1) ? sprintf(phpbb::$user->lang['USER_POST'], 1) : sprintf(phpbb::$user->lang['USER_POSTS'], $active_t_count), - 'ACTIVE_TOPIC_PCT' => sprintf($l_active_pct, $active_t_pct), - 'U_ACTIVE_FORUM' => phpbb::$url->append_sid('viewforum', 'f=' . $active_f_id), - 'U_ACTIVE_TOPIC' => phpbb::$url->append_sid('viewtopic', 't=' . $active_t_id), - 'S_SHOW_ACTIVITY' => true, - )); -} - -/** -* Topic and forum watching common code -*/ -function watch_topic_forum($mode, &$s_watching, $user_id, $forum_id, $topic_id, $notify_status = 'unset', $start = 0) -{ - global $start; - - $table_sql = ($mode == 'forum') ? FORUMS_WATCH_TABLE : TOPICS_WATCH_TABLE; - $where_sql = ($mode == 'forum') ? 'forum_id' : 'topic_id'; - $match_id = ($mode == 'forum') ? $forum_id : $topic_id; - $u_url = 'uid=' . phpbb::$user->data['user_id']; - $u_url .= ($mode == 'forum') ? '&f' : '&f=' . $forum_id . '&t'; - - // Is user watching this thread? - if ($user_id != ANONYMOUS) - { - $can_watch = true; - - if ($notify_status == 'unset') - { - $sql = "SELECT notify_status - FROM $table_sql - WHERE $where_sql = $match_id - AND user_id = $user_id"; - $result = phpbb::$db->sql_query($sql); - - $notify_status = ($row = phpbb::$db->sql_fetchrow($result)) ? $row['notify_status'] : NULL; - phpbb::$db->sql_freeresult($result); - } - - if (!is_null($notify_status) && $notify_status !== '') - { - - if (phpbb_request::is_set('unwatch', phpbb_request::GET)) - { - $uid = request_var('uid', 0); - if ($uid != $user_id) - { - $redirect_url = phpbb::$url->append_sid("view$mode", "$u_url=$match_id&start=$start"); - $message = phpbb::$user->lang['ERR_UNWATCHING'] . '<br /><br />' . sprintf(phpbb::$user->lang['RETURN_' . strtoupper($mode)], '<a href="' . $redirect_url . '">', '</a>'); - trigger_error($message); - } - if (phpbb_request::variable('unwatch', '', false, phpbb_request::GET) == $mode) - { - $is_watching = 0; - - $sql = 'DELETE FROM ' . $table_sql . " - WHERE $where_sql = $match_id - AND user_id = $user_id"; - phpbb::$db->sql_query($sql); - } - - $redirect_url = phpbb::$url->append_sid("view$mode", "$u_url=$match_id&start=$start"); - - meta_refresh(3, $redirect_url); - - $message = phpbb::$user->lang['NOT_WATCHING_' . strtoupper($mode)] . '<br /><br />' . sprintf(phpbb::$user->lang['RETURN_' . strtoupper($mode)], '<a href="' . $redirect_url . '">', '</a>'); - trigger_error($message); - } - else - { - $is_watching = true; - - if ($notify_status) - { - $sql = 'UPDATE ' . $table_sql . " - SET notify_status = 0 - WHERE $where_sql = $match_id - AND user_id = $user_id"; - phpbb::$db->sql_query($sql); - } - } - } - else - { - if (phpbb_request::is_set('watch', phpbb_request::GET)) - { - $token = request_var('hash', ''); - $redirect_url = phpbb::$url->append_sid("view$mode", "$u_url=$match_id&start=$start"); - - if (phpbb_request::variable('watch', '', false, phpbb_request::GET) == $mode && check_link_hash($token, "{$mode}_$match_id")) - { - $is_watching = true; - - $sql = 'INSERT INTO ' . $table_sql . " (user_id, $where_sql, notify_status) - VALUES ($user_id, $match_id, 0)"; - phpbb::$db->sql_query($sql); - $message = phpbb::$user->lang['ARE_WATCHING_' . strtoupper($mode)] . '<br /><br />' . sprintf(phpbb::$user->lang['RETURN_' . strtoupper($mode)], '<a href="' . $redirect_url . '">', '</a>'); - } - else - { - $message = phpbb::$user->lang['ERR_WATCHING'] . '<br /><br />' . sprintf(phpbb::$user->lang['RETURN_' . strtoupper($mode)], '<a href="' . $redirect_url . '">', '</a>'); - } - - meta_refresh(3, $redirect_url); - - trigger_error($message); - } - else - { - $is_watching = 0; - } - } - } - else - { - if (phpbb_request::variable('unwatch', '', false, phpbb_request::GET) == $mode) - { - login_box(); - } - else - { - $can_watch = 0; - $is_watching = 0; - } - } - - if ($can_watch) - { - $s_watching['link'] = phpbb::$url->append_sid("view$mode", "$u_url=$match_id&" . (($is_watching) ? 'unwatch' : 'watch') . "=$mode&start=$start&hash=" . generate_link_hash("{$mode}_$match_id")); - $s_watching['title'] = phpbb::$user->lang[(($is_watching) ? 'STOP' : 'START') . '_WATCHING_' . strtoupper($mode)]; - $s_watching['is_watching'] = $is_watching; - } - - return; -} - -/** -* Get user rank title and image -* -* @param int $user_id the users user id -* @param int $user_rank the current stored users rank id -* @param int $user_posts the users number of posts -* @param string &$rank_title the rank title will be stored here after execution -* @param string &$rank_img the rank image as full img tag is stored here after execution -* @param string &$rank_img_src the rank image source is stored here after execution -* -*/ -function get_user_rank($user_id, $user_rank, $user_posts, &$rank_title, &$rank_img, &$rank_img_src) -{ - global $ranks; - - if (empty($ranks)) - { - $ranks = phpbb_cache::obtain_ranks(); - } - - if (!empty($user_rank)) - { - $rank_title = (isset($ranks['special'][$user_rank]['rank_title'])) ? $ranks['special'][$user_rank]['rank_title'] : ''; - $rank_img = (!empty($ranks['special'][$user_rank]['rank_image'])) ? '<img src="' . PHPBB_ROOT_PATH . phpbb::$config['ranks_path'] . '/' . $ranks['special'][$user_rank]['rank_image'] . '" alt="' . $ranks['special'][$user_rank]['rank_title'] . '" title="' . $ranks['special'][$user_rank]['rank_title'] . '" />' : ''; - $rank_img_src = (!empty($ranks['special'][$user_rank]['rank_image'])) ? PHPBB_ROOT_PATH . phpbb::$config['ranks_path'] . '/' . $ranks['special'][$user_rank]['rank_image'] : ''; - } - else if ($user_id != ANONYMOUS) - { - if (!empty($ranks['normal'])) - { - foreach ($ranks['normal'] as $rank) - { - if ($user_posts >= $rank['rank_min']) - { - $rank_title = $rank['rank_title']; - $rank_img = (!empty($rank['rank_image'])) ? '<img src="' . PHPBB_ROOT_PATH . phpbb::$config['ranks_path'] . '/' . $rank['rank_image'] . '" alt="' . $rank['rank_title'] . '" title="' . $rank['rank_title'] . '" />' : ''; - $rank_img_src = (!empty($rank['rank_image'])) ? PHPBB_ROOT_PATH . phpbb::$config['ranks_path'] . '/' . $rank['rank_image'] : ''; - break; - } - } - } - } -} - -/** -* Get user avatar -* -* @param string $avatar Users assigned avatar name -* @param int $avatar_type Type of avatar -* @param string $avatar_width Width of users avatar -* @param string $avatar_height Height of users avatar -* @param string $alt Optional language string for alt tag within image, can be a language key or text -* -* @return string Avatar image -*/ -function get_user_avatar($avatar, $avatar_type, $avatar_width, $avatar_height, $alt = 'USER_AVATAR') -{ - if (empty($avatar) || !$avatar_type) - { - return ''; - } - - $avatar_img = ''; - - switch ($avatar_type) - { - case AVATAR_UPLOAD: - $avatar_img = PHPBB_ROOT_PATH . 'download/file.' . PHP_EXT . '?avatar='; - break; - - case AVATAR_GALLERY: - $avatar_img = PHPBB_ROOT_PATH . phpbb::$config['avatar_gallery_path'] . '/'; - break; - } - - $avatar_img .= $avatar; - return '<img src="' . (str_replace(' ', '%20', $avatar_img)) . '" width="' . $avatar_width . '" height="' . $avatar_height . '" alt="' . ((!empty(phpbb::$user->lang[$alt])) ? phpbb::$user->lang[$alt] : $alt) . '" />'; -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/functions_install.php b/phpBB/includes/functions_install.php deleted file mode 100644 index 630bb78a71..0000000000 --- a/phpBB/includes/functions_install.php +++ /dev/null @@ -1,531 +0,0 @@ -<?php -/** -* -* @package install -* @version $Id$ -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Determine if we are able to load a specified PHP module and do so if possible -* -* @param string $dll Name of the DLL without extension. For example 'sqlite'. -* @return bool Returns true of successfully loaded, else false. -*/ -function can_load_dll($dll) -{ - return ((@ini_get('enable_dl') || strtolower(@ini_get('enable_dl')) == 'on') && (!@ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == 'off') && @dl($dll . '.' . PHP_SHLIB_SUFFIX)) ? true : false; -} - -/** -* Returns an array of available DBMS with some data, if a DBMS is specified it will only return data for that DBMS and will load its extension if necessary. -* -*/ -function get_available_dbms($dbms = false, $return_unavailable = false, $only_30x_options = false) -{ - $available_dbms = array( - 'firebird' => array( - 'LABEL' => 'FireBird', - 'MODULE' => 'interbase', - 'DRIVER' => 'firebird', - 'AVAILABLE' => true, - '3.0.x' => true, - ), - 'mysqli' => array( - 'LABEL' => 'MySQL with MySQLi Extension', - 'MODULE' => 'mysqli', - 'DRIVER' => 'mysqli', - 'AVAILABLE' => true, - '3.0.x' => true, - ), - 'mysql' => array( - 'LABEL' => 'MySQL', - 'MODULE' => 'mysql', - 'DRIVER' => 'mysql', - 'AVAILABLE' => true, - '3.0.x' => true, - ), - 'mssql' => array( - 'LABEL' => 'MS SQL Server 2000+', - 'MODULE' => 'mssql', - 'DRIVER' => 'mssql', - 'AVAILABLE' => true, - '3.0.x' => true, - ), - 'mssql_odbc'=> array( - 'LABEL' => 'MS SQL Server [ ODBC ]', - 'MODULE' => 'odbc', - 'DRIVER' => 'mssql_odbc', - 'AVAILABLE' => true, - '3.0.x' => true, - ), - 'mssql_2005'=> array( - 'LABEL' => 'MS SQL Server [ 2005/2008 ]', - 'MODULE' => array('sqlsrv', 'sqlsrv_ts'), - 'DRIVER' => 'mssql_2005', - 'AVAILABLE' => true, - '3.0.x' => true, - ), - 'db2' => array( - 'LABEL' => 'IBM DB2', - 'MODULE' => 'ibm_db2', - 'DRIVER' => 'db2', - 'AVAILABLE' => true, - '3.0.x' => false, - ), - 'oracle' => array( - 'LABEL' => 'Oracle', - 'MODULE' => 'oci8', - 'DRIVER' => 'oracle', - 'AVAILABLE' => true, - '3.0.x' => true, - ), - 'postgres' => array( - 'LABEL' => 'PostgreSQL 7.x/8.x', - 'MODULE' => 'pgsql', - 'DRIVER' => 'postgres', - 'AVAILABLE' => true, - '3.0.x' => true, - ), - 'sqlite' => array( - 'LABEL' => 'SQLite', - 'MODULE' => 'sqlite', - 'DRIVER' => 'sqlite', - 'AVAILABLE' => true, - '3.0.x' => true, - ), - ); - - if ($dbms) - { - if (isset($available_dbms[$dbms])) - { - $available_dbms = array($dbms => $available_dbms[$dbms]); - } - else - { - return array(); - } - } - - $any_db_support = false; - - // now perform some checks whether they are really available - foreach ($available_dbms as $db_name => $db_ary) - { - if ($only_30x_options && !$db_ary['3.0.x']) - { - if ($return_unavailable) - { - $available_dbms[$db_name]['AVAILABLE'] = false; - } - else - { - unset($available_dbms[$db_name]); - } - continue; - } - - $dll = $db_ary['MODULE']; - - if (!is_array($dll)) - { - $dll = array($dll); - } - - $is_available = false; - foreach ($dll as $test_dll) - { - if (@extension_loaded($test_dll) || can_load_dll($test_dll)) - { - $is_available = true; - break; - } - } - - if (!$is_available) - { - if ($return_unavailable) - { - $available_dbms[$db_name]['AVAILABLE'] = false; - } - else - { - unset($available_dbms[$db_name]); - } - continue; - } - - $any_db_support = true; - } - - if ($return_unavailable) - { - $available_dbms['ANY_DB_SUPPORT'] = $any_db_support; - } - - return $available_dbms; -} - -/** -* Generate the drop down of available database options -*/ -function dbms_select($default = '', $only_30x_options = false) -{ - $available_dbms = get_available_dbms(false, false, $only_30x_options); - - $dbms_options = ''; - foreach ($available_dbms as $dbms_name => $details) - { - $selected = ($dbms_name == $default) ? ' selected="selected"' : ''; - $dbms_options .= '<option value="' . $dbms_name . '"' . $selected .'>' . phpbb::$user->lang['DLL_' . strtoupper($dbms_name)] . '</option>'; - } - - return $dbms_options; -} - -/** -* Get tables of a database -*/ -function get_tables($db) -{ - switch ($db->dbms_type) - { - case 'mysql': - $sql = 'SHOW TABLES'; - break; - - case 'sqlite': - $sql = 'SELECT name - FROM sqlite_master - WHERE type = "table"'; - break; - - case 'mssql': - $sql = "SELECT name - FROM sysobjects - WHERE type='U'"; - break; - - case 'postgres': - $sql = 'SELECT relname - FROM pg_stat_user_tables'; - break; - - case 'firebird': - $sql = 'SELECT rdb$relation_name - FROM rdb$relations - WHERE rdb$view_source is null - AND rdb$system_flag = 0'; - break; - - case 'db2': - $sql = "SELECT tabname - FROM SYSCAT.TABLES - WHERE type = 'T' - AND tabschema = 'DB2ADMIN'"; - $field = 'tabname'; - break; - - case 'oracle': - $sql = 'SELECT table_name - FROM USER_TABLES'; - break; - } - - $result = $db->sql_query($sql); - - $tables = array(); - while ($row = $db->sql_fetchrow($result)) - { - $tables[] = current($row); - } - $db->sql_freeresult($result); - - return $tables; -} - -/** -* Used to test whether we are able to connect to the database the user has specified -* and identify any problems (eg there are already tables with the names we want to use -* @param array $dbms should be of the format of an element of the array returned by {@link get_available_dbms get_available_dbms()} -* necessary extensions should be loaded already -*/ -function connect_check_db($dbms_details, $table_prefix, $dbhost, $dbuser, $dbpasswd, $dbname, $dbport, &$error, $prefix_may_exist = false) -{ - $dbms = $dbms_details['DRIVER']; - - phpbb::assign('checkdb', phpbb_db_dbal::new_instance($dbms)); - $db = phpbb::get_instance('checkdb'); - - $db->sql_return_on_error(true); - - // Check that we actually have a database name before going any further..... - if ($dbms_details['DRIVER'] != 'sqlite' && $dbms_details['DRIVER'] != 'oracle' && $dbname === '') - { - $error[] = phpbb::$user->lang['INST_ERR_DB_NO_NAME']; - return false; - } - - // Make sure we don't have a daft user who thinks having the SQLite database in the forum directory is a good idea - if ($dbms_details['DRIVER'] == 'sqlite' && stripos(phpbb::$url->realpath($dbhost), phpbb::$url->realpath('../')) === 0) - { - $error[] = phpbb::$user->lang['INST_ERR_DB_FORUM_PATH']; - return false; - } - - // Check the prefix length to ensure that index names are not too long and does not contain invalid characters - switch ($dbms_details['DRIVER']) - { - case 'mysql': - case 'mysqli': - if (strspn($table_prefix, '-./\\') !== 0) - { - $error[] = phpbb::$user->lang['INST_ERR_PREFIX_INVALID']; - return false; - } - - // no break; - - case 'postgres': - $prefix_length = 36; - break; - - case 'mssql': - case 'mssql_odbc': - case 'mssql_2005': - $prefix_length = 90; - break; - - case 'db2': - $prefix_length = 108; - break; - - case 'sqlite': - $prefix_length = 200; - break; - - case 'firebird': - case 'oracle': - $prefix_length = 6; - break; - } - - if (strlen($table_prefix) > $prefix_length) - { - $error[] = phpbb::$user->lang('INST_ERR_PREFIX_TOO_LONG', $prefix_length); - return false; - } - - // Try and connect ... - if (is_array($db->sql_connect($dbhost, $dbuser, $dbpasswd, $dbname, $dbport, false, true))) - { - $db_error = $db->sql_error(); - $error[] = phpbb::$user->lang['INST_ERR_DB_CONNECT'] . '<br />' . (($db_error['message']) ? $db_error['message'] : phpbb::$user->lang['INST_ERR_DB_NO_ERROR']); - return false; - } - - // Likely matches for an existing phpBB installation - if (!$prefix_may_exist) - { - $temp_prefix = strtolower($table_prefix); - $table_ary = array($temp_prefix . 'attachments', $temp_prefix . 'config', $temp_prefix . 'sessions', $temp_prefix . 'topics', $temp_prefix . 'users'); - - $tables = get_tables($db); - $tables = array_map('strtolower', $tables); - $table_intersect = array_intersect($tables, $table_ary); - - if (sizeof($table_intersect)) - { - $error[] = phpbb::$user->lang['INST_ERR_PREFIX']; - return false; - } - } - - // Make sure that the user has selected a sensible DBAL for the DBMS actually installed - switch ($dbms_details['DRIVER']) - { - case 'mysql': - if (version_compare($db->sql_server_info(true), '4.1.3', '<')) - { - $error[] = phpbb::$user->lang['INST_ERR_DB_MYSQL_VERSION']; - } - break; - - case 'mysqli': - if (version_compare($db->sql_server_info(true), '4.1.3', '<')) - { - $error[] = phpbb::$user->lang['INST_ERR_DB_MYSQLI_VERSION']; - } - break; - - case 'sqlite': - if (version_compare($db->sql_server_info(true), '2.8.2', '<')) - { - $error[] = phpbb::$user->lang['INST_ERR_DB_SQLITE_VERSION']; - } - break; - - case 'firebird': - // check the version of FB, use some hackery if we can't get access to the server info - if ($db->service_handle !== false && strtolower($dbuser) == 'sysdba') - { - $val = @ibase_server_info($db->service_handle, IBASE_SVC_SERVER_VERSION); - preg_match('#V([\d.]+)#', $val, $match); - if ($match[1] < 2) - { - $error[] = phpbb::$user->lang['INST_ERR_DB_FIREBIRD_VERSION']; - } - $db_info = @ibase_db_info($db->service_handle, $dbname, IBASE_STS_HDR_PAGES); - - preg_match('/^\\s*Page size\\s*(\\d+)/m', $db_info, $regs); - $page_size = intval($regs[1]); - if ($page_size < 8192) - { - $error[] = phpbb::$user->lang['INST_ERR_DB_NO_FIREBIRD_PS']; - } - } - else - { - $sql = "SELECT * - FROM RDB\$FUNCTIONS - WHERE RDB\$SYSTEM_FLAG IS NULL - AND RDB\$FUNCTION_NAME = 'CHAR_LENGTH'"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - // if its a UDF, its too old - if ($row) - { - $error[] = phpbb::$user->lang['INST_ERR_DB_FIREBIRD_VERSION']; - } - else - { - $sql = "SELECT FIRST 0 char_length('') - FROM RDB\$DATABASE"; - $result = $db->sql_query($sql); - if (!$result) // This can only fail if char_length is not defined - { - $error[] = phpbb::$user->lang['INST_ERR_DB_FIREBIRD_VERSION']; - } - $db->sql_freeresult($result); - } - - // Setup the stuff for our random table - $char_array = array_merge(range('A', 'Z'), range('0', '9')); - $char_len = mt_rand(7, 9); - $char_array_len = sizeof($char_array) - 1; - - $final = ''; - - for ($i = 0; $i < $char_len; $i++) - { - $final .= $char_array[mt_rand(0, $char_array_len)]; - } - - // Create some random table - $sql = 'CREATE TABLE ' . $final . " ( - FIELD1 VARCHAR(255) CHARACTER SET UTF8 DEFAULT '' NOT NULL COLLATE UNICODE, - FIELD2 INTEGER DEFAULT 0 NOT NULL);"; - $db->sql_query($sql); - - // Create an index that should fail if the page size is less than 8192 - $sql = 'CREATE INDEX ' . $final . ' ON ' . $final . '(FIELD1, FIELD2);'; - $db->sql_query($sql); - - if (ibase_errmsg() !== false) - { - $error[] = phpbb::$user->lang['INST_ERR_DB_NO_FIREBIRD_PS']; - } - - // Kill the old table - $db->sql_query('DROP TABLE ' . $final . ';'); - - unset($final); - } - break; - - case 'oracle': - $sql = "SELECT * - FROM NLS_DATABASE_PARAMETERS - WHERE PARAMETER = 'NLS_RDBMS_VERSION' - OR PARAMETER = 'NLS_CHARACTERSET'"; - $result = $db->sql_query($sql); - - while ($row = $db->sql_fetchrow($result)) - { - $stats[$row['parameter']] = $row['value']; - } - $db->sql_freeresult($result); - - if (version_compare($stats['NLS_RDBMS_VERSION'], '9.2', '<')) - { - $error[] = phpbb::$user->lang['INST_ERR_DB_ORACLE_VERSION']; - } - - if ($stats['NLS_CHARACTERSET'] !== 'AL32UTF8') - { - $error[] = phpbb::$user->lang['INST_ERR_DB_NO_ORACLE_NLS']; - } - break; - - case 'postgres': - - if (version_compare($db->sql_server_info(true), '8.2', '<')) - { - $error[] = phpbb::$user->lang['INST_ERR_DB_POSTGRES_VERSION']; - } - else - { - $sql = "SHOW server_encoding;"; - $result = $db->sql_query($sql); - $row = $db->sql_fetchrow($result); - $db->sql_freeresult($result); - - if ($row['server_encoding'] !== 'UNICODE' && $row['server_encoding'] !== 'UTF8') - { - $error[] = phpbb::$user->lang['INST_ERR_DB_NO_POSTGRES_UTF8']; - } - } - break; - - case 'mssql_odbc': - /** - * @todo check odbc.defaultlrl (min 128K) and odbc.defaultbinmode (1) - */ - break; - - case 'db2': - if (version_compare($db->sql_server_info(true), '8.2.2', '<')) - { - $error[] = phpbb::$user->lang['INST_ERR_DB_DB2_VERSION']; - } - - // Now check the extension version - if (!function_exists('db2_escape_string')) - { - $error[] = phpbb::$user->lang['INST_ERR_DB_DB2_EXT_VERSION']; - } - break; - } - - if (sizeof($error)) - { - return false; - } - - return true; -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/functions_jabber.php b/phpBB/includes/functions_jabber.php deleted file mode 100644 index 5fc7123db7..0000000000 --- a/phpBB/includes/functions_jabber.php +++ /dev/null @@ -1,872 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2007 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* -* Jabber class from Flyspray project -* -* @version class.jabber2.php 1595 2008-09-19 (0.9.9) -* @copyright 2006 Flyspray.org -* @author Florian Schmitz (floele) -* -* Only slightly modified by Acyd Burn -* -* @package phpBB3 -*/ -class jabber -{ - private $connection = null; - private $session = array(); - private $timeout = 10; - - private $server; - private $connect_server; - private $port; - private $username; - private $password; - private $use_ssl; - private $resource = 'functions_jabber.phpbb.php'; - - private $enable_logging; - private $log_array; - - private $features = array(); - - /** - */ - function __construct($server, $port, $username, $password, $use_ssl = false) - { - $this->connect_server = ($server) ? $server : 'localhost'; - $this->port = ($port) ? $port : 5222; - - // Get the server and the username - if (strpos($username, '@') === false) - { - $this->server = $this->connect_server; - $this->username = $username; - } - else - { - $jid = explode('@', $username, 2); - - $this->username = $jid[0]; - $this->server = $jid[1]; - } - - $this->password = $password; - $this->use_ssl = ($use_ssl && self::can_use_ssl()) ? true : false; - - // Change port if we use SSL - if ($this->port == 5222 && $this->use_ssl) - { - $this->port = 5223; - } - - $this->enable_logging = true; - $this->log_array = array(); - } - - /** - * Able to use the SSL functionality? - */ - public static function can_use_ssl() - { - // Will not work with PHP >= 5.2.1 or < 5.2.3RC2 until timeout problem with ssl hasn't been fixed (http://bugs.php.net/41236) - return ((version_compare(PHP_VERSION, '5.2.1', '<') || version_compare(PHP_VERSION, '5.2.3RC2', '>=')) && @extension_loaded('openssl')) ? true : false; - } - - /** - * Able to use TLS? - */ - public static function can_use_tls() - { - if (!@extension_loaded('openssl') || !function_exists('stream_socket_enable_crypto') || !function_exists('stream_get_meta_data') || !function_exists('socket_set_blocking') || !function_exists('stream_get_wrappers')) - { - return false; - } - - /** - * Make sure the encryption stream is supported - * Also seem to work without the crypto stream if correctly compiled - - $streams = stream_get_wrappers(); - - if (!in_array('streams.crypto', $streams)) - { - return false; - } - */ - - return true; - } - - /** - * Sets the resource which is used. No validation is done here, only escaping. - * @param string $name - * @access public - */ - public function set_resource($name) - { - $this->resource = $name; - } - - /** - * Connect - */ - public function connect() - { -/* if (!$this->check_jid($this->username . '@' . $this->server)) - { - $this->add_to_log('Error: Jabber ID is not valid: ' . $this->username . '@' . $this->server); - return false; - }*/ - - $this->session['ssl'] = $this->use_ssl; - - if ($this->open_socket($this->connect_server, $this->port, $this->use_ssl)) - { - $this->send("<?xml version='1.0' encoding='UTF-8' ?" . ">\n"); - $this->send("<stream:stream to='{$this->server}' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>\n"); - } - else - { - $this->add_to_log('Error: connect() #2'); - return false; - } - - // Now we listen what the server has to say...and give appropriate responses - $this->response($this->listen()); - return true; - } - - /** - * Disconnect - */ - public function disconnect() - { - if ($this->connected()) - { - // disconnect gracefully - if (isset($this->session['sent_presence'])) - { - $this->send_presence('offline', '', true); - } - - $this->send('</stream:stream>'); - $this->session = array(); - return fclose($this->connection); - } - - return false; - } - - /** - * Connected? - */ - public function connected() - { - return (is_resource($this->connection) && !feof($this->connection)) ? true : false; - } - - - /** - * Initiates login (using data from contructor, after calling connect()) - * @access public - * @return bool - */ - public function login() - { - if (!sizeof($this->features)) - { - $this->add_to_log('Error: No feature information from server available.'); - return false; - } - - return $this->response($this->features); - } - - /** - * Send data to the Jabber server - * @param string $xml - * @access private - * @return bool - */ - private function send($xml) - { - if ($this->connected()) - { - $xml = trim($xml); - $this->add_to_log('SEND: '. $xml); - return fwrite($this->connection, $xml); - } - else - { - $this->add_to_log('Error: Could not send, connection lost (flood?).'); - return false; - } - } - - /** - * OpenSocket - * @param string $server host to connect to - * @param int $port port number - * @param bool $use_ssl use ssl or not - * @access private - * @return bool - */ - private function open_socket($server, $port, $use_ssl = false) - { - if (@function_exists('dns_get_record')) - { - $record = @dns_get_record("_xmpp-client._tcp.$server", DNS_SRV); - if (!empty($record) && !empty($record[0]['target'])) - { - $server = $record[0]['target']; - } - } - - $server = $use_ssl ? 'ssl://' . $server : $server; - - if ($this->connection = @fsockopen($server, $port, $errorno, $errorstr, $this->timeout)) - { - socket_set_blocking($this->connection, 0); - socket_set_timeout($this->connection, 60); - - return true; - } - - // Apparently an error occured... - $this->add_to_log('Error: open_socket() - ' . $errorstr); - return false; - } - - /** - * Return log - */ - public function get_log() - { - if ($this->enable_logging && sizeof($this->log_array)) - { - return implode("<br /><br />", $this->log_array); - } - - return ''; - } - - /** - * Add information to log - */ - private function add_to_log($string) - { - if ($this->enable_logging) - { - $this->log_array[] = utf8_htmlspecialchars($string); - } - } - - /** - * Listens to the connection until it gets data or the timeout is reached. - * Thus, it should only be called if data is expected to be received. - * @access private - * @return mixed either false for timeout or an array with the received data - */ - private function listen($timeout = 10, $wait = false) - { - if (!$this->connected()) - { - return false; - } - - // Wait for a response until timeout is reached - $start = time(); - $data = ''; - - do - { - $read = trim(fread($this->connection, 4096)); - $data .= $read; - } - while (time() <= $start + $timeout && !feof($this->connection) && ($wait || $data == '' || $read != '' || (substr(rtrim($data), -1) != '>'))); - - if ($data != '') - { - $this->add_to_log('RECV: '. $data); - return self::xmlize($data); - } - else - { - $this->add_to_log('Timeout, no response from server.'); - return false; - } - } - - /** - * Initiates account registration (based on data used for contructor) - * @access private - * @return bool - */ - private function register() - { - if (!isset($this->session['id']) || isset($this->session['jid'])) - { - $this->add_to_log('Error: Cannot initiate registration.'); - return false; - } - - $this->send("<iq type='get' id='reg_1'><query xmlns='jabber:iq:register'/></iq>"); - return $this->response($this->listen()); - } - - /** - * Sets account presence. No additional info required (default is "online" status) - * @param $message online, offline... - * @param $type dnd, away, chat, xa or nothing - * @param $unavailable set this to true if you want to become unavailable - * @access private - * @return bool - */ - private function send_presence($message = '', $type = '', $unavailable = false) - { - if (!isset($this->session['jid'])) - { - $this->add_to_log('ERROR: send_presence() - Cannot set presence at this point, no jid given.'); - return false; - } - - $type = strtolower($type); - $type = (in_array($type, array('dnd', 'away', 'chat', 'xa'))) ? '<show>'. $type .'</show>' : ''; - - $unavailable = ($unavailable) ? " type='unavailable'" : ''; - $message = ($message) ? '<status>' . utf8_htmlspecialchars($message) .'</status>' : ''; - - $this->session['sent_presence'] = !$unavailable; - - return $this->send("<presence$unavailable>" . $type . $message . '</presence>'); - } - - /** - * This handles all the different XML elements - * @param array $xml - * @access private - * @return bool - */ - private function response($xml) - { - if (!is_array($xml) || !sizeof($xml)) - { - return false; - } - - // did we get multiple elements? do one after another - // array('message' => ..., 'presence' => ...) - if (sizeof($xml) > 1) - { - foreach ($xml as $key => $value) - { - $this->response(array($key => $value)); - } - return; - } - else - { - // or even multiple elements of the same type? - // array('message' => array(0 => ..., 1 => ...)) - if (sizeof(reset($xml)) > 1) - { - foreach (reset($xml) as $value) - { - $this->response(array(key($xml) => array(0 => $value))); - } - return; - } - } - - switch (key($xml)) - { - case 'stream:stream': - // Connection initialised (or after authentication). Not much to do here... - - if (isset($xml['stream:stream'][0]['#']['stream:features'])) - { - // we already got all info we need - $this->features = $xml['stream:stream'][0]['#']; - } - else - { - $this->features = $this->listen(); - } - - $second_time = isset($this->session['id']); - $this->session['id'] = $xml['stream:stream'][0]['@']['id']; - - if ($second_time) - { - // If we are here for the second time after TLS, we need to continue logging in - return $this->login(); - } - - // go on with authentication? - if (isset($this->features['stream:features'][0]['#']['bind']) || !empty($this->session['tls'])) - { - return $this->response($this->features); - } - break; - - case 'stream:features': - // Resource binding after successful authentication - if (isset($this->session['authenticated'])) - { - // session required? - $this->session['sess_required'] = isset($xml['stream:features'][0]['#']['session']); - - $this->send("<iq type='set' id='bind_1'> - <bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'> - <resource>" . utf8_htmlspecialchars($this->resource) . '</resource> - </bind> - </iq>'); - return $this->response($this->listen()); - } - - // Let's use TLS if SSL is not enabled and we can actually use it - if (!$this->session['ssl'] && self::can_use_tls() && self::can_use_ssl() && isset($xml['stream:features'][0]['#']['starttls'])) - { - $this->add_to_log('Switching to TLS.'); - $this->send("<starttls xmlns='urn:ietf:params:xml:ns:xmpp-tls'/>\n"); - return $this->response($this->listen()); - } - - // Does the server support SASL authentication? - - // I hope so, because we do (and no other method). - if (isset($xml['stream:features'][0]['#']['mechanisms'][0]['@']['xmlns']) && $xml['stream:features'][0]['#']['mechanisms'][0]['@']['xmlns'] == 'urn:ietf:params:xml:ns:xmpp-sasl') - { - // Now decide on method - $methods = array(); - - foreach ($xml['stream:features'][0]['#']['mechanisms'][0]['#']['mechanism'] as $value) - { - $methods[] = $value['#']; - } - - // we prefer DIGEST-MD5 - // we don't want to use plain authentication (neither does the server usually) if no encryption is in place - - // http://www.xmpp.org/extensions/attic/jep-0078-1.7.html - // The plaintext mechanism SHOULD NOT be used unless the underlying stream is encrypted (using SSL or TLS) - // and the client has verified that the server certificate is signed by a trusted certificate authority. - - if (in_array('DIGEST-MD5', $methods)) - { - $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='DIGEST-MD5'/>"); - } - else if (in_array('PLAIN', $methods) && ($this->session['ssl'] || !empty($this->session['tls']))) - { - $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='PLAIN'>" - . base64_encode(chr(0) . $this->username . '@' . $this->server . chr(0) . $this->password) . - '</auth>'); - } - else if (in_array('ANONYMOUS', $methods)) - { - $this->send("<auth xmlns='urn:ietf:params:xml:ns:xmpp-sasl' mechanism='ANONYMOUS'/>"); - } - else - { - // not good... - $this->add_to_log('Error: No authentication method supported.'); - $this->disconnect(); - return false; - } - - return $this->response($this->listen()); - } - else - { - // ok, this is it. bye. - $this->add_to_log('Error: Server does not offer SASL authentication.'); - $this->disconnect(); - return false; - } - break; - - case 'challenge': - // continue with authentication...a challenge literally -_- - $decoded = base64_decode($xml['challenge'][0]['#']); - $decoded = self::parse_data($decoded); - - if (!isset($decoded['digest-uri'])) - { - $decoded['digest-uri'] = 'xmpp/'. $this->server; - } - - // better generate a cnonce, maybe it's needed - $decoded['cnonce'] = base64_encode(md5(uniqid(mt_rand(), true))); - - // second challenge? - if (isset($decoded['rspauth'])) - { - $this->send("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'/>"); - } - else - { - // Make sure we only use 'auth' for qop (relevant for $this->encrypt_password()) - // If the <response> is choking up on the changed parameter we may need to adjust encrypt_password() directly - if (isset($decoded['qop']) && $decoded['qop'] != 'auth' && strpos($decoded['qop'], 'auth') !== false) - { - $decoded['qop'] = 'auth'; - } - - $response = array( - 'username' => $this->username, - 'response' => $this->encrypt_password(array_merge($decoded, array('nc' => '00000001'))), - 'charset' => 'utf-8', - 'nc' => '00000001', - 'qop' => 'auth', // only auth being supported - ); - - foreach (array('nonce', 'digest-uri', 'realm', 'cnonce') as $key) - { - if (isset($decoded[$key])) - { - $response[$key] = $decoded[$key]; - } - } - - $this->send("<response xmlns='urn:ietf:params:xml:ns:xmpp-sasl'>" . base64_encode($this->implode_data($response)) . '</response>'); - } - - return $this->response($this->listen()); - break; - - case 'failure': - $this->add_to_log('Error: Server sent "failure".'); - $this->disconnect(); - return false; - break; - - case 'proceed': - // continue switching to TLS - $meta = stream_get_meta_data($this->connection); - socket_set_blocking($this->connection, 1); - - if (!stream_socket_enable_crypto($this->connection, true, STREAM_CRYPTO_METHOD_TLS_CLIENT)) - { - $this->add_to_log('Error: TLS mode change failed.'); - return false; - } - - socket_set_blocking($this->connection, $meta['blocked']); - $this->session['tls'] = true; - - // new stream - $this->send("<?xml version='1.0' encoding='UTF-8' ?" . ">\n"); - $this->send("<stream:stream to='{$this->server}' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>\n"); - - return $this->response($this->listen()); - break; - - case 'success': - // Yay, authentication successful. - $this->send("<stream:stream to='{$this->server}' xmlns='jabber:client' xmlns:stream='http://etherx.jabber.org/streams' version='1.0'>\n"); - $this->session['authenticated'] = true; - - // we have to wait for another response - return $this->response($this->listen()); - break; - - case 'iq': - // we are not interested in IQs we did not expect - if (!isset($xml['iq'][0]['@']['id'])) - { - return false; - } - - // multiple possibilities here - switch ($xml['iq'][0]['@']['id']) - { - case 'bind_1': - $this->session['jid'] = $xml['iq'][0]['#']['bind'][0]['#']['jid'][0]['#']; - - // and (maybe) yet another request to be able to send messages *finally* - if ($this->session['sess_required']) - { - $this->send("<iq to='{$this->server}' type='set' id='sess_1'> - <session xmlns='urn:ietf:params:xml:ns:xmpp-session'/> - </iq>"); - return $this->response($this->listen()); - } - - return true; - break; - - case 'sess_1': - return true; - break; - - case 'reg_1': - $this->send("<iq type='set' id='reg_2'> - <query xmlns='jabber:iq:register'> - <username>" . utf8_htmlspecialchars($this->username) . "</username> - <password>" . utf8_htmlspecialchars($this->password) . "</password> - </query> - </iq>"); - return $this->response($this->listen()); - break; - - case 'reg_2': - // registration end - if (isset($xml['iq'][0]['#']['error'])) - { - $this->add_to_log('Warning: Registration failed.'); - return false; - } - return true; - break; - - case 'unreg_1': - return true; - break; - - default: - $this->add_to_log('Notice: Received unexpected IQ.'); - return false; - break; - } - break; - - case 'message': - // we are only interested in content... - if (!isset($xml['message'][0]['#']['body'])) - { - return false; - } - - $message['body'] = $xml['message'][0]['#']['body'][0]['#']; - $message['from'] = $xml['message'][0]['@']['from']; - - if (isset($xml['message'][0]['#']['subject'])) - { - $message['subject'] = $xml['message'][0]['#']['subject'][0]['#']; - } - $this->session['messages'][] = $message; - break; - - default: - // hm...don't know this response - $this->add_to_log('Notice: Unknown server response (' . key($xml) . ')'); - return false; - break; - } - } - - public function send_message($to, $text, $subject = '', $type = 'normal') - { - if (!isset($this->session['jid'])) - { - return false; - } - - if (!in_array($type, array('chat', 'normal', 'error', 'groupchat', 'headline'))) - { - $type = 'normal'; - } - - return $this->send("<message from='" . utf8_htmlspecialchars($this->session['jid']) . "' to='" . utf8_htmlspecialchars($to) . "' type='$type' id='" . uniqid('msg') . "'> - <subject>" . utf8_htmlspecialchars($subject) . "</subject> - <body>" . utf8_htmlspecialchars($text) . "</body> - </message>" - ); - } - - /** - * Encrypts a password as in RFC 2831 - * @param array $data Needs data from the client-server connection - * @access public - * @return string - */ - public function encrypt_password($data) - { - // let's me think about <challenge> again... - foreach (array('realm', 'cnonce', 'digest-uri') as $key) - { - if (!isset($data[$key])) - { - $data[$key] = ''; - } - } - - $pack = md5($this->username . ':' . $data['realm'] . ':' . $this->password); - - if (isset($data['authzid'])) - { - $a1 = pack('H32', $pack) . sprintf(':%s:%s:%s', $data['nonce'], $data['cnonce'], $data['authzid']); - } - else - { - $a1 = pack('H32', $pack) . sprintf(':%s:%s', $data['nonce'], $data['cnonce']); - } - - // should be: qop = auth - $a2 = 'AUTHENTICATE:'. $data['digest-uri']; - - return md5(sprintf('%s:%s:%s:%s:%s:%s', md5($a1), $data['nonce'], $data['nc'], $data['cnonce'], $data['qop'], md5($a2))); - } - - /** - * parse_data like a="b",c="d",... or like a="a, b", c, d="e", f=g,... - * @param string $data - * @access private - * @return array a => b ... - */ - private static function parse_data($data) - { - $data = explode(',', $data); - $pairs = array(); - $key = false; - - foreach ($data as $pair) - { - $dd = strpos($pair, '='); - - if ($dd) - { - $key = trim(substr($pair, 0, $dd)); - $pairs[$key] = trim(trim(substr($pair, $dd + 1)), '"'); - } - else if (strpos(strrev(trim($pair)), '"') === 0 && $key) - { - // We are actually having something left from "a, b" values, add it to the last one we handled. - $pairs[$key] .= ',' . trim(trim($pair), '"'); - continue; - } - } - - return $pairs; - } - - /** - * opposite of jabber::parse_data() - * @param array $data - * @access private - * @return string - */ - private function implode_data($data) - { - $return = array(); - foreach ($data as $key => $value) - { - $return[] = $key . '="' . $value . '"'; - } - return implode(',', $return); - } - - /** - * xmlize() - * @author Hans Anderson - * @copyright Hans Anderson / http://www.hansanderson.com/php/xml/ - */ - private static function xmlize($data, $skip_white = 1, $encoding = 'UTF-8') - { - $data = trim($data); - - if (substr($data, 0, 5) != '<?xml') - { - // mod - $data = '<root>'. $data . '</root>'; - } - - $vals = $index = $array = array(); - $parser = xml_parser_create($encoding); - xml_parser_set_option($parser, XML_OPTION_CASE_FOLDING, 0); - xml_parser_set_option($parser, XML_OPTION_SKIP_WHITE, $skip_white); - xml_parse_into_struct($parser, $data, $vals, $index); - xml_parser_free($parser); - - $i = 0; - $tagname = $vals[$i]['tag']; - - $array[$tagname][0]['@'] = (isset($vals[$i]['attributes'])) ? $vals[$i]['attributes'] : array(); - $array[$tagname][0]['#'] = self::_xml_depth($vals, $i); - - if (substr($data, 0, 5) != '<?xml') - { - $array = $array['root'][0]['#']; - } - - return $array; - } - - /** - * _xml_depth() - * @author Hans Anderson - * @copyright Hans Anderson / http://www.hansanderson.com/php/xml/ - */ - private static function _xml_depth($vals, &$i) - { - $children = array(); - - if (isset($vals[$i]['value'])) - { - array_push($children, $vals[$i]['value']); - } - - while (++$i < sizeof($vals)) - { - switch ($vals[$i]['type']) - { - case 'open': - - $tagname = (isset($vals[$i]['tag'])) ? $vals[$i]['tag'] : ''; - $size = (isset($children[$tagname])) ? sizeof($children[$tagname]) : 0; - - if (isset($vals[$i]['attributes'])) - { - $children[$tagname][$size]['@'] = $vals[$i]['attributes']; - } - - $children[$tagname][$size]['#'] = self::_xml_depth($vals, $i); - - break; - - case 'cdata': - array_push($children, $vals[$i]['value']); - break; - - case 'complete': - - $tagname = $vals[$i]['tag']; - $size = (isset($children[$tagname])) ? sizeof($children[$tagname]) : 0; - $children[$tagname][$size]['#'] = (isset($vals[$i]['value'])) ? $vals[$i]['value'] : array(); - - if (isset($vals[$i]['attributes'])) - { - $children[$tagname][$size]['@'] = $vals[$i]['attributes']; - } - - break; - - case 'close': - return $children; - break; - } - } - - return $children; - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/functions_messenger.php b/phpBB/includes/functions_messenger.php deleted file mode 100644 index 8d15e8a13f..0000000000 --- a/phpBB/includes/functions_messenger.php +++ /dev/null @@ -1,1442 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Messenger -* @package phpBB3 -*/ -class messenger -{ - private $vars, $msg, $extra_headers, $replyto, $from, $subject; - private $addresses = array(); - - private $mail_priority = MAIL_NORMAL_PRIORITY; - private $use_queue = true; - private $tpl_msg = array(); - - /** - * Constructor - */ - function __construct($use_queue = true) - { - $this->use_queue = (!phpbb::$config['email_package_size']) ? false : $use_queue; - $this->subject = ''; - } - - /** - * Resets all the data (address, template file, etc etc) to default - */ - private function reset() - { - $this->addresses = $this->extra_headers = array(); - $this->vars = $this->msg = $this->replyto = $this->from = ''; - $this->mail_priority = MAIL_NORMAL_PRIORITY; - } - - /** - * Sets an email address to send to - */ - function to($address, $realname = '') - { - if (!trim($address)) - { - return; - } - - $pos = isset($this->addresses['to']) ? sizeof($this->addresses['to']) : 0; - - $this->addresses['to'][$pos]['email'] = trim($address); - - // If empty sendmail_path on windows, PHP changes the to line - if (!phpbb::$config['smtp_delivery'] && DIRECTORY_SEPARATOR == '\\') - { - $this->addresses['to'][$pos]['name'] = ''; - } - else - { - $this->addresses['to'][$pos]['name'] = trim($realname); - } - } - - /** - * Sets an cc address to send to - */ - function cc($address, $realname = '') - { - if (!trim($address)) - { - return; - } - - $pos = isset($this->addresses['cc']) ? sizeof($this->addresses['cc']) : 0; - $this->addresses['cc'][$pos]['email'] = trim($address); - $this->addresses['cc'][$pos]['name'] = trim($realname); - } - - /** - * Sets an bcc address to send to - */ - function bcc($address, $realname = '') - { - if (!trim($address)) - { - return; - } - - $pos = isset($this->addresses['bcc']) ? sizeof($this->addresses['bcc']) : 0; - $this->addresses['bcc'][$pos]['email'] = trim($address); - $this->addresses['bcc'][$pos]['name'] = trim($realname); - } - - /** - * Sets a im contact to send to - */ - function im($address, $realname = '') - { - // IM-Addresses could be empty - if (!trim($address)) - { - return; - } - - $pos = isset($this->addresses['im']) ? sizeof($this->addresses['im']) : 0; - $this->addresses['im'][$pos]['uid'] = trim($address); - $this->addresses['im'][$pos]['name'] = trim($realname); - } - - /** - * Set the reply to address - */ - function replyto($address) - { - $this->replyto = trim($address); - } - - /** - * Set the from address - */ - function from($address) - { - $this->from = trim($address); - } - - /** - * set up subject for mail - */ - function subject($subject = '') - { - $this->subject = trim($subject); - } - - /** - * set up extra mail headers - */ - function headers($headers) - { - $this->extra_headers[] = trim($headers); - } - - /** - * Set the email priority - */ - function set_mail_priority($priority = MAIL_NORMAL_PRIORITY) - { - $this->mail_priority = $priority; - } - - /** - * Set email template to use - */ - function template($template_file, $template_lang = '') - { - if (!trim($template_file)) - { - trigger_error('No template file set', E_USER_ERROR); - } - - if (!trim($template_lang)) - { - $template_lang = basename(phpbb::$config['default_lang']); - } - - if (empty($this->tpl_msg[$template_lang . $template_file])) - { - $tpl_file = (!empty(phpbb::$user->lang_path)) ? phpbb::$user->lang_path : PHPBB_ROOT_PATH . 'language/'; - $tpl_file .= $template_lang . "/email/$template_file.txt"; - - if (!file_exists($tpl_file)) - { - trigger_error("Could not find email template file [ $tpl_file ]", E_USER_ERROR); - } - - if (($data = @file_get_contents($tpl_file)) === false) - { - trigger_error("Failed opening template file [ $tpl_file ]", E_USER_ERROR); - } - - $this->tpl_msg[$template_lang . $template_file] = $data; - } - - $this->msg = $this->tpl_msg[$template_lang . $template_file]; - - return true; - } - - /** - * assign variables to email template - */ - function assign_vars($vars) - { - $this->vars = (empty($this->vars)) ? $vars : $this->vars + $vars; - } - - /** - * Send the mail out to the recipients set previously in var $this->addresses - */ - function send($method = NOTIFY_EMAIL, $break = false) - { - // We add some standard variables we always use, no need to specify them always - $this->vars['U_BOARD'] = (!isset($this->vars['U_BOARD'])) ? generate_board_url() : $this->vars['U_BOARD']; - $this->vars['EMAIL_SIG'] = (!isset($this->vars['EMAIL_SIG'])) ? str_replace('<br />', "\n", "-- \n" . htmlspecialchars_decode(phpbb::$config['board_email_sig'])) : $this->vars['EMAIL_SIG']; - $this->vars['SITENAME'] = (!isset($this->vars['SITENAME'])) ? htmlspecialchars_decode(phpbb::$config['sitename']) : $this->vars['SITENAME']; - - // Escape all quotes, else the eval will fail. - $this->msg = str_replace ("'", "\'", $this->msg); - $this->msg = preg_replace('#\{([a-z0-9\-_]*?)\}#is', "' . ((isset(\$this->vars['\\1'])) ? \$this->vars['\\1'] : '') . '", $this->msg); - - eval("\$this->msg = '$this->msg';"); - - // We now try and pull a subject from the email body ... if it exists, - // do this here because the subject may contain a variable - $drop_header = ''; - $match = array(); - if (preg_match('#^(Subject:(.*?))$#m', $this->msg, $match)) - { - $this->subject = (trim($match[2]) != '') ? trim($match[2]) : (($this->subject != '') ? $this->subject : phpbb::$user->lang['NO_EMAIL_SUBJECT']); - $drop_header .= '[\r\n]*?' . preg_quote($match[1], '#'); - } - else - { - $this->subject = (($this->subject != '') ? $this->subject : phpbb::$user->lang['NO_EMAIL_SUBJECT']); - } - - if ($drop_header) - { - $this->msg = trim(preg_replace('#' . $drop_header . '#s', '', $this->msg)); - } - - if ($break) - { - return true; - } - - switch ($method) - { - case NOTIFY_EMAIL: - $result = $this->msg_email(); - break; - - case NOTIFY_IM: - $result = $this->msg_jabber(); - break; - - case NOTIFY_BOTH: - $result = $this->msg_email(); - $this->msg_jabber(); - break; - } - - $this->reset(); - return $result; - } - - /** - * Add error message to log - */ - public static function error($type, $msg) - { - // Session doesn't exist, create it - if (!isset(phpbb::$user->session_id) || phpbb::$user->session_id === '') - { - phpbb::$user->session_begin(); - } - - $calling_page = (!empty($_SERVER['PHP_SELF'])) ? $_SERVER['PHP_SELF'] : $_ENV['PHP_SELF']; - - $message = ''; - switch ($type) - { - case 'EMAIL': - $message = '<strong>EMAIL/' . ((phpbb::$config['smtp_delivery']) ? 'SMTP' : 'PHP/' . phpbb::$config['email_function_name'] . '()') . '</strong>'; - break; - - default: - $message = "<strong>$type</strong>"; - break; - } - - $message .= '<br /><em>' . htmlspecialchars($calling_page) . '</em><br /><br />' . $msg . '<br />'; - add_log('critical', 'LOG_ERROR_' . $type, $message); - } - - /** - * Save to queue - */ - function save_queue() - { - if (phpbb::$config['email_package_size'] && $this->use_queue && !empty($this->queue)) - { - $this->queue->save(); - return; - } - } - - /** - * Return email header - */ - private function build_header($to, $cc, $bcc) - { - $headers = array(); - - $headers[] = 'From: ' . $this->from; - - if ($cc) - { - $headers[] = 'Cc: ' . $cc; - } - - if ($bcc) - { - $headers[] = 'Bcc: ' . $bcc; - } - - $headers[] = 'Reply-To: ' . $this->replyto; - $headers[] = 'Return-Path: <' . phpbb::$config['board_email'] . '>'; - $headers[] = 'Sender: <' . phpbb::$config['board_email'] . '>'; - $headers[] = 'MIME-Version: 1.0'; - $headers[] = 'Message-ID: <' . md5(unique_id(time())) . '@' . phpbb::$config['server_name'] . '>'; - $headers[] = 'Date: ' . date('r', time()); - $headers[] = 'Content-Type: text/plain; charset=UTF-8'; // format=flowed - $headers[] = 'Content-Transfer-Encoding: 8bit'; // 7bit - - $headers[] = 'X-Priority: ' . $this->mail_priority; - $headers[] = 'X-MSMail-Priority: ' . (($this->mail_priority == MAIL_LOW_PRIORITY) ? 'Low' : (($this->mail_priority == MAIL_NORMAL_PRIORITY) ? 'Normal' : 'High')); - $headers[] = 'X-Mailer: PhpBB3'; - $headers[] = 'X-MimeOLE: phpBB3'; - $headers[] = 'X-phpBB-Origin: phpbb://' . str_replace(array('http://', 'https://'), array('', ''), generate_board_url()); - - if (sizeof($this->extra_headers)) - { - $headers = array_merge($headers, $this->extra_headers); - } - - return $headers; - } - - /** - * Send out emails - */ - private function msg_email() - { - if (empty(phpbb::$config['email_enable'])) - { - return false; - } - - // Addresses to send to? - if (empty($this->addresses) || (empty($this->addresses['to']) && empty($this->addresses['cc']) && empty($this->addresses['bcc']))) - { - // Send was successful. ;) - return true; - } - - $use_queue = false; - if (phpbb::$config['email_package_size'] && $this->use_queue) - { - if (empty($this->queue)) - { - $this->queue = new queue(); - $this->queue->init('email', phpbb::$config['email_package_size']); - } - $use_queue = true; - } - - if (empty($this->replyto)) - { - $this->replyto = '<' . phpbb::$config['board_contact'] . '>'; - } - - if (empty($this->from)) - { - $this->from = '<' . phpbb::$config['board_contact'] . '>'; - } - - // Build to, cc and bcc strings - $to = $cc = $bcc = ''; - foreach ($this->addresses as $type => $address_ary) - { - if ($type == 'im') - { - continue; - } - - foreach ($address_ary as $which_ary) - { - $$type .= (($$type != '') ? ', ' : '') . (($which_ary['name'] != '') ? '"' . mail_encode($which_ary['name']) . '" <' . $which_ary['email'] . '>' : $which_ary['email']); - } - } - - // Build header - $headers = $this->build_header($to, $cc, $bcc); - - // Send message ... - if (!$use_queue) - { - $mail_to = ($to == '') ? 'undisclosed-recipients:;' : $to; - $err_msg = ''; - - if (phpbb::$config['smtp_delivery']) - { - $result = smtpmail($this->addresses, mail_encode($this->subject), wordwrap(utf8_wordwrap($this->msg), 997, "\n", true), $err_msg, $headers); - } - else - { - // We use the EOL character for the OS here because the PHP mail function does not correctly transform line endings. On Windows SMTP is used (SMTP is \r\n), on UNIX a command is used... - // Reference: http://bugs.php.net/bug.php?id=15841 - $headers = implode(PHP_EOL, $headers); - - ob_start(); - $result = phpbb::$config['email_function_name']($mail_to, mail_encode($this->subject), wordwrap(utf8_wordwrap($this->msg), 997, "\n", true), $headers); - $err_msg = ob_get_clean(); - } - - if (!$result) - { - self::error('EMAIL', $err_msg); - return false; - } - } - else - { - $this->queue->put('email', array( - 'to' => $to, - 'addresses' => $this->addresses, - 'subject' => $this->subject, - 'msg' => $this->msg, - 'headers' => $headers) - ); - } - - return true; - } - - /** - * Send jabber message out - */ - private function msg_jabber() - { - if (empty(phpbb::$config['jab_enable']) || empty(phpbb::$config['jab_host']) || empty(phpbb::$config['jab_username']) || empty(phpbb::$config['jab_password'])) - { - return false; - } - - if (empty($this->addresses['im'])) - { - // Send was successful. ;) - return true; - } - - $use_queue = false; - if (phpbb::$config['jab_package_size'] && $this->use_queue) - { - if (empty($this->queue)) - { - $this->queue = new queue(); - $this->queue->init('jabber', phpbb::$config['jab_package_size']); - } - $use_queue = true; - } - - $addresses = array(); - foreach ($this->addresses['im'] as $type => $uid_ary) - { - $addresses[] = $uid_ary['uid']; - } - $addresses = array_unique($addresses); - - if (!$use_queue) - { - include_once(PHPBB_ROOT_PATH . 'includes/functions_jabber.' . PHP_EXT); - $this->jabber = new jabber(phpbb::$config['jab_host'], phpbb::$config['jab_port'], phpbb::$config['jab_username'], phpbb::$config['jab_password'], phpbb::$config['jab_use_ssl']); - - if (!$this->jabber->connect()) - { - self::error('JABBER', phpbb::$user->lang['ERR_JAB_CONNECT'] . '<br />' . $this->jabber->get_log()); - return false; - } - - if (!$this->jabber->login()) - { - self::error('JABBER', phpbb::$user->lang['ERR_JAB_AUTH'] . '<br />' . $this->jabber->get_log()); - return false; - } - - foreach ($addresses as $address) - { - $this->jabber->send_message($address, $this->msg, $this->subject); - } - - $this->jabber->disconnect(); - } - else - { - $this->queue->put('jabber', array( - 'addresses' => $addresses, - 'subject' => $this->subject, - 'msg' => $this->msg) - ); - } - unset($addresses); - return true; - } -} - -/** -* handling email and jabber queue -* @package phpBB3 -*/ -class queue -{ - private $data = array(); - private $queue_data = array(); - private $package_size = 0; - private $cache_file = ''; - - /** - * constructor - */ - function __construct() - { - $this->data = array(); - $this->cache_file = PHPBB_ROOT_PATH . 'cache/queue.' . PHP_EXT; - } - - /** - * Init a queue object - */ - public function init($object, $package_size) - { - $this->data[$object] = array(); - $this->data[$object]['package_size'] = $package_size; - $this->data[$object]['data'] = array(); - } - - /** - * Put object in queue - */ - public function put($object, $scope) - { - $this->data[$object]['data'][] = $scope; - } - - /** - * Process queue - * Using lock file - */ - public function process() - { - set_config('last_queue_run', time(), true); - - // Delete stale lock file - if (file_exists($this->cache_file . '.lock') && !file_exists($this->cache_file)) - { - @unlink($this->cache_file . '.lock'); - return; - } - - if (!file_exists($this->cache_file) || (file_exists($this->cache_file . '.lock') && filemtime($this->cache_file) > time() - phpbb::$config['queue_interval'])) - { - return; - } - - $fp = @fopen($this->cache_file . '.lock', 'wb'); - fclose($fp); - phpbb::$system->chmod($this->cache_file . '.lock', phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); - - include($this->cache_file); - - foreach ($this->queue_data as $object => $data_ary) - { - @set_time_limit(0); - - if (!isset($data_ary['package_size'])) - { - $data_ary['package_size'] = 0; - } - - $package_size = $data_ary['package_size']; - $num_items = (!$package_size || sizeof($data_ary['data']) < $package_size) ? sizeof($data_ary['data']) : $package_size; - - // If the amount of emails to be sent is way more than package_size than we need to increase it to prevent backlogs... - if (sizeof($data_ary['data']) > $package_size * 2.5) - { - $num_items = sizeof($data_ary['data']); - } - - switch ($object) - { - case 'email': - // Delete the email queued objects if mailing is disabled - if (!phpbb::$config['email_enable']) - { - unset($this->queue_data['email']); - continue 2; - } - break; - - case 'jabber': - if (!phpbb::$config['jab_enable']) - { - unset($this->queue_data['jabber']); - continue 2; - } - - include_once(PHPBB_ROOT_PATH . 'includes/functions_jabber.' . PHP_EXT); - $this->jabber = new jabber(phpbb::$config['jab_host'], phpbb::$config['jab_port'], phpbb::$config['jab_username'], phpbb::$config['jab_password'], phpbb::$config['jab_use_ssl']); - - if (!$this->jabber->connect()) - { - messenger::error('JABBER', phpbb::$user->lang['ERR_JAB_CONNECT']); - continue 2; - } - - if (!$this->jabber->login()) - { - messenger::error('JABBER', phpbb::$user->lang['ERR_JAB_AUTH']); - continue 2; - } - - break; - - default: - return; - } - - for ($i = 0; $i < $num_items; $i++) - { - // Make variables available... - extract(array_shift($this->queue_data[$object]['data'])); - - switch ($object) - { - case 'email': - $err_msg = ''; - $to = (!$to) ? 'undisclosed-recipients:;' : $to; - - if (phpbb::$config['smtp_delivery']) - { - $result = smtpmail($addresses, mail_encode($subject), wordwrap(utf8_wordwrap($msg), 997, "\n", true), $err_msg, $headers); - } - else - { - ob_start(); - $result = phpbb::$config['email_function_name']($to, mail_encode($subject), wordwrap(utf8_wordwrap($msg), 997, "\n", true), implode(PHP_EOL, $headers)); - $err_msg = ob_get_clean(); - } - - if (!$result) - { - @unlink($this->cache_file . '.lock'); - - messenger::error('EMAIL', $err_msg); - continue 2; - } - break; - - case 'jabber': - foreach ($addresses as $address) - { - if ($this->jabber->send_message($address, $msg, $subject) === false) - { - messenger::error('JABBER', $this->jabber->get_log()); - continue 3; - } - } - break; - } - } - - // No more data for this object? Unset it - if (!sizeof($this->queue_data[$object]['data'])) - { - unset($this->queue_data[$object]); - } - - // Post-object processing - switch ($object) - { - case 'jabber': - // Hang about a couple of secs to ensure the messages are - // handled, then disconnect - $this->jabber->disconnect(); - break; - } - } - - if (!sizeof($this->queue_data)) - { - @unlink($this->cache_file); - } - else - { - if ($fp = @fopen($this->cache_file, 'wb')) - { - @flock($fp, LOCK_EX); - fwrite($fp, "<?php\nif (!defined('IN_PHPBB')) exit;\n\$this->queue_data = unserialize(" . var_export(serialize($this->queue_data), true) . ");\n\n?>"); - @flock($fp, LOCK_UN); - fclose($fp); - - phpbb::$system->chmod($this->cache_file, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); - } - } - - @unlink($this->cache_file . '.lock'); - } - - /** - * Save queue - */ - public function save() - { - if (!sizeof($this->data)) - { - return; - } - - if (file_exists($this->cache_file)) - { - include($this->cache_file); - - foreach ($this->queue_data as $object => $data_ary) - { - if (isset($this->data[$object]) && sizeof($this->data[$object])) - { - $this->data[$object]['data'] = array_merge($data_ary['data'], $this->data[$object]['data']); - } - else - { - $this->data[$object]['data'] = $data_ary['data']; - } - } - } - - if ($fp = @fopen($this->cache_file, 'w')) - { - @flock($fp, LOCK_EX); - fwrite($fp, "<?php\nif (!defined('IN_PHPBB')) exit;\n\$this->queue_data = unserialize(" . var_export(serialize($this->data), true) . ");\n\n?>"); - @flock($fp, LOCK_UN); - fclose($fp); - - phpbb::$system->chmod($this->cache_file, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); - } - } -} - -/** -* Replacement or substitute for PHP's mail command -*/ -function smtpmail($addresses, $subject, $message, &$err_msg, $headers = false) -{ - // Fix any bare linefeeds in the message to make it RFC821 Compliant. - $message = preg_replace("#(?<!\r)\n#si", "\r\n", $message); - - if ($headers !== false) - { - if (!is_array($headers)) - { - // Make sure there are no bare linefeeds in the headers - $headers = preg_replace('#(?<!\r)\n#si', "\n", $headers); - $headers = explode("\n", $headers); - } - - // Ok this is rather confusing all things considered, - // but we have to grab bcc and cc headers and treat them differently - // Something we really didn't take into consideration originally - $headers_used = array(); - - foreach ($headers as $header) - { - if (strpos(strtolower($header), 'cc:') === 0 || strpos(strtolower($header), 'bcc:') === 0) - { - continue; - } - $headers_used[] = trim($header); - } - - $headers = chop(implode("\r\n", $headers_used)); - } - - if (trim($subject) == '') - { - $err_msg = (isset(phpbb::$user->lang['NO_EMAIL_SUBJECT'])) ? phpbb::$user->lang['NO_EMAIL_SUBJECT'] : 'No email subject specified'; - return false; - } - - if (trim($message) == '') - { - $err_msg = (isset(phpbb::$user->lang['NO_EMAIL_MESSAGE'])) ? phpbb::$user->lang['NO_EMAIL_MESSAGE'] : 'Email message was blank'; - return false; - } - - $mail_rcpt = $mail_to = $mail_cc = array(); - - // Build correct addresses for RCPT TO command and the client side display (TO, CC) - if (isset($addresses['to']) && sizeof($addresses['to'])) - { - foreach ($addresses['to'] as $which_ary) - { - $mail_to[] = ($which_ary['name'] != '') ? mail_encode(trim($which_ary['name'])) . ' <' . trim($which_ary['email']) . '>' : '<' . trim($which_ary['email']) . '>'; - $mail_rcpt['to'][] = '<' . trim($which_ary['email']) . '>'; - } - } - - if (isset($addresses['bcc']) && sizeof($addresses['bcc'])) - { - foreach ($addresses['bcc'] as $which_ary) - { - $mail_rcpt['bcc'][] = '<' . trim($which_ary['email']) . '>'; - } - } - - if (isset($addresses['cc']) && sizeof($addresses['cc'])) - { - foreach ($addresses['cc'] as $which_ary) - { - $mail_cc[] = ($which_ary['name'] != '') ? mail_encode(trim($which_ary['name'])) . ' <' . trim($which_ary['email']) . '>' : '<' . trim($which_ary['email']) . '>'; - $mail_rcpt['cc'][] = '<' . trim($which_ary['email']) . '>'; - } - } - - $smtp = new smtp_class(); - - $errno = 0; - $errstr = ''; - - $smtp->add_backtrace('Connecting to ' . phpbb::$config['smtp_host'] . ':' . phpbb::$config['smtp_port']); - - // Ok we have error checked as much as we can to this point let's get on it already. - ob_start(); - $smtp->socket = fsockopen(phpbb::$config['smtp_host'], phpbb::$config['smtp_port'], $errno, $errstr, 20); - $error_contents = ob_get_clean(); - - if (!$smtp->socket) - { - if ($errstr) - { - $errstr = utf8_convert_message($errstr); - } - - $err_msg = (isset(phpbb::$user->lang['NO_CONNECT_TO_SMTP_HOST'])) ? sprintf(phpbb::$user->lang['NO_CONNECT_TO_SMTP_HOST'], $errno, $errstr) : "Could not connect to smtp host : $errno : $errstr"; - $err_msg .= ($error_contents) ? '<br /><br />' . htmlspecialchars($error_contents) : ''; - return false; - } - - // Wait for reply - if ($err_msg = $smtp->server_parse('220', __LINE__)) - { - $smtp->close_session($err_msg); - return false; - } - - // Let me in. This function handles the complete authentication process - if ($err_msg = $smtp->log_into_server(phpbb::$config['smtp_host'], phpbb::$config['smtp_username'], phpbb::$config['smtp_password'], phpbb::$config['smtp_auth_method'])) - { - $smtp->close_session($err_msg); - return false; - } - - // From this point onward most server response codes should be 250 - // Specify who the mail is from.... - $smtp->server_send('MAIL FROM:<' . phpbb::$config['board_email'] . '>'); - if ($err_msg = $smtp->server_parse('250', __LINE__)) - { - $smtp->close_session($err_msg); - return false; - } - - // Specify each user to send to and build to header. - $to_header = implode(', ', $mail_to); - $cc_header = implode(', ', $mail_cc); - - // Now tell the MTA to send the Message to the following people... [TO, BCC, CC] - $rcpt = false; - foreach ($mail_rcpt as $type => $mail_to_addresses) - { - foreach ($mail_to_addresses as $mail_to_address) - { - // Add an additional bit of error checking to the To field. - if (preg_match('#[^ ]+\@[^ ]+#', $mail_to_address)) - { - $smtp->server_send("RCPT TO:$mail_to_address"); - if ($err_msg = $smtp->server_parse('250', __LINE__)) - { - // We continue... if users are not resolved we do not care - if ($smtp->numeric_response_code != 550) - { - $smtp->close_session($err_msg); - return false; - } - } - else - { - $rcpt = true; - } - } - } - } - - // We try to send messages even if a few people do not seem to have valid email addresses, but if no one has, we have to exit here. - if (!$rcpt) - { - phpbb::$user->session_begin(); - $err_msg .= '<br /><br />'; - $err_msg .= (isset(phpbb::$user->lang['INVALID_EMAIL_LOG'])) ? sprintf(phpbb::$user->lang['INVALID_EMAIL_LOG'], htmlspecialchars($mail_to_address)) : '<strong>' . htmlspecialchars($mail_to_address) . '</strong> possibly an invalid email address?'; - $smtp->close_session($err_msg); - return false; - } - - // Ok now we tell the server we are ready to start sending data - $smtp->server_send('DATA'); - - // This is the last response code we look for until the end of the message. - if ($err_msg = $smtp->server_parse('354', __LINE__)) - { - $smtp->close_session($err_msg); - return false; - } - - // Send the Subject Line... - $smtp->server_send("Subject: $subject"); - - // Now the To Header. - $to_header = ($to_header == '') ? 'undisclosed-recipients:;' : $to_header; - $smtp->server_send("To: $to_header"); - - // Now the CC Header. - if ($cc_header != '') - { - $smtp->server_send("CC: $cc_header"); - } - - // Now any custom headers.... - if ($headers !== false) - { - $smtp->server_send("$headers\r\n"); - } - - // Ok now we are ready for the message... - $smtp->server_send($message); - - // Ok the all the ingredients are mixed in let's cook this puppy... - $smtp->server_send('.'); - if ($err_msg = $smtp->server_parse('250', __LINE__)) - { - $smtp->close_session($err_msg); - return false; - } - - // Now tell the server we are done and close the socket... - $smtp->server_send('QUIT'); - $smtp->close_session($err_msg); - - return true; -} - -/** -* SMTP Class -* Auth Mechanisms originally taken from the AUTH Modules found within the PHP Extension and Application Repository (PEAR) -* See docs/AUTHORS for more details -* @package phpBB3 -*/ -class smtp_class -{ - private $server_response = ''; - public $socket = 0; - private $responses = array(); - private $commands = array(); - public $numeric_response_code = 0; - - private $backtrace = false; - private $backtrace_log = array(); - - function __construct() - { - // Always create a backtrace for admins to identify SMTP problems - $this->backtrace = true; - $this->backtrace_log = array(); - } - - /** - * Add backtrace message for debugging - */ - public function add_backtrace($message) - { - if ($this->backtrace) - { - $this->backtrace_log[] = utf8_htmlspecialchars($message); - } - } - - /** - * Send command to smtp server - */ - public function server_send($command, $private_info = false) - { - fputs($this->socket, $command . "\r\n"); - - (!$private_info) ? $this->add_backtrace("# $command") : $this->add_backtrace('# Omitting sensitive information'); - - // We could put additional code here - } - - /** - * We use the line to give the support people an indication at which command the error occurred - */ - public function server_parse($response, $line) - { - $this->server_response = ''; - $this->responses = array(); - $this->numeric_response_code = 0; - - while (substr($this->server_response, 3, 1) != ' ') - { - if (!($this->server_response = fgets($this->socket, 256))) - { - return (isset(phpbb::$user->lang['NO_EMAIL_RESPONSE_CODE'])) ? phpbb::$user->lang['NO_EMAIL_RESPONSE_CODE'] : 'Could not get mail server response codes'; - } - $this->responses[] = substr(rtrim($this->server_response), 4); - $this->numeric_response_code = (int) substr($this->server_response, 0, 3); - - $this->add_backtrace("LINE: $line <- {$this->server_response}"); - } - - if (!(substr($this->server_response, 0, 3) == $response)) - { - $this->numeric_response_code = (int) substr($this->server_response, 0, 3); - return (isset(phpbb::$user->lang['EMAIL_SMTP_ERROR_RESPONSE'])) ? sprintf(phpbb::$user->lang['EMAIL_SMTP_ERROR_RESPONSE'], $line, $this->server_response) : "Ran into problems sending Mail at <strong>Line $line</strong>. Response: $this->server_response"; - } - - return 0; - } - - /** - * Close session - */ - public function close_session(&$err_msg) - { - fclose($this->socket); - - if ($this->backtrace) - { - $message = '<h1>Backtrace</h1><p>' . implode('<br />', $this->backtrace_log) . '</p>'; - $err_msg .= $message; - } - } - - /** - * Log into server and get possible auth codes if neccessary - */ - public function log_into_server($hostname, $username, $password, $default_auth_method) - { - $err_msg = ''; - $local_host = (function_exists('php_uname')) ? gethostbyaddr(gethostbyname(php_uname('n'))) : phpbb::$user->system['host']; - - // If we are authenticating through pop-before-smtp, we - // have to login ones before we get authenticated - // NOTE: on some configurations the time between an update of the auth database takes so - // long that the first email send does not work. This is not a biggie on a live board (only - // the install mail will most likely fail) - but on a dynamic ip connection this might produce - // severe problems and is not fixable! - if ($default_auth_method == 'POP-BEFORE-SMTP' && $username && $password) - { - $errno = 0; - $errstr = ''; - - $this->server_send("QUIT"); - fclose($this->socket); - - $result = $this->pop_before_smtp($hostname, $username, $password); - $username = $password = $default_auth_method = ''; - - // We need to close the previous session, else the server is not - // able to get our ip for matching... - if (!$this->socket = @fsockopen(phpbb::$config['smtp_host'], phpbb::$config['smtp_port'], $errno, $errstr, 10)) - { - if ($errstr) - { - $errstr = utf8_convert_message($errstr); - } - - $err_msg = (isset(phpbb::$user->lang['NO_CONNECT_TO_SMTP_HOST'])) ? sprintf(phpbb::$user->lang['NO_CONNECT_TO_SMTP_HOST'], $errno, $errstr) : "Could not connect to smtp host : $errno : $errstr"; - return $err_msg; - } - - // Wait for reply - if ($err_msg = $this->server_parse('220', __LINE__)) - { - $this->close_session($err_msg); - return $err_msg; - } - } - - // Try EHLO first - $this->server_send("EHLO {$local_host}"); - if ($err_msg = $this->server_parse('250', __LINE__)) - { - // a 503 response code means that we're already authenticated - if ($this->numeric_response_code == 503) - { - return false; - } - - // If EHLO fails, we try HELO - $this->server_send("HELO {$local_host}"); - if ($err_msg = $this->server_parse('250', __LINE__)) - { - return ($this->numeric_response_code == 503) ? false : $err_msg; - } - } - - foreach ($this->responses as $response) - { - $response = explode(' ', $response); - $response_code = $response[0]; - unset($response[0]); - $this->commands[$response_code] = implode(' ', $response); - } - - // If we are not authenticated yet, something might be wrong if no username and passwd passed - if (!$username || !$password) - { - return false; - } - - if (!isset($this->commands['AUTH'])) - { - return (isset(phpbb::$user->lang['SMTP_NO_AUTH_SUPPORT'])) ? phpbb::$user->lang['SMTP_NO_AUTH_SUPPORT'] : 'SMTP server does not support authentication'; - } - - // Get best authentication method - $available_methods = explode(' ', $this->commands['AUTH']); - - // Define the auth ordering if the default auth method was not found - $auth_methods = array('PLAIN', 'LOGIN', 'CRAM-MD5', 'DIGEST-MD5'); - $method = ''; - - if (in_array($default_auth_method, $available_methods)) - { - $method = $default_auth_method; - } - else - { - foreach ($auth_methods as $_method) - { - if (in_array($_method, $available_methods)) - { - $method = $_method; - break; - } - } - } - - if (!$method) - { - return (isset(phpbb::$user->lang['NO_SUPPORTED_AUTH_METHODS'])) ? phpbb::$user->lang['NO_SUPPORTED_AUTH_METHODS'] : 'No supported authentication methods'; - } - - $method = strtolower(str_replace('-', '_', $method)); - return $this->$method($username, $password); - } - - /** - * Pop before smtp authentication - */ - private function pop_before_smtp($hostname, $username, $password) - { - if (!$this->socket = @fsockopen($hostname, 110, $errno, $errstr, 10)) - { - if ($errstr) - { - $errstr = utf8_convert_message($errstr); - } - - return (isset(phpbb::$user->lang['NO_CONNECT_TO_SMTP_HOST'])) ? sprintf(phpbb::$user->lang['NO_CONNECT_TO_SMTP_HOST'], $errno, $errstr) : "Could not connect to smtp host : $errno : $errstr"; - } - - $this->server_send("USER $username", true); - if ($err_msg = $this->server_parse('+OK', __LINE__)) - { - return $err_msg; - } - - $this->server_send("PASS $password", true); - if ($err_msg = $this->server_parse('+OK', __LINE__)) - { - return $err_msg; - } - - $this->server_send('QUIT'); - fclose($this->socket); - - return false; - } - - /** - * Plain authentication method - */ - private function plain($username, $password) - { - $this->server_send('AUTH PLAIN'); - if ($err_msg = $this->server_parse('334', __LINE__)) - { - return ($this->numeric_response_code == 503) ? false : $err_msg; - } - - $base64_method_plain = base64_encode("\0" . $username . "\0" . $password); - $this->server_send($base64_method_plain, true); - if ($err_msg = $this->server_parse('235', __LINE__)) - { - return $err_msg; - } - - return false; - } - - /** - * Login authentication method - */ - private function login($username, $password) - { - $this->server_send('AUTH LOGIN'); - if ($err_msg = $this->server_parse('334', __LINE__)) - { - return ($this->numeric_response_code == 503) ? false : $err_msg; - } - - $this->server_send(base64_encode($username), true); - if ($err_msg = $this->server_parse('334', __LINE__)) - { - return $err_msg; - } - - $this->server_send(base64_encode($password), true); - if ($err_msg = $this->server_parse('235', __LINE__)) - { - return $err_msg; - } - - return false; - } - - /** - * cram_md5 authentication method - */ - private function cram_md5($username, $password) - { - $this->server_send('AUTH CRAM-MD5'); - if ($err_msg = $this->server_parse('334', __LINE__)) - { - return ($this->numeric_response_code == 503) ? false : $err_msg; - } - - $md5_challenge = base64_decode($this->responses[0]); - $password = (strlen($password) > 64) ? pack('H32', md5($password)) : ((strlen($password) < 64) ? str_pad($password, 64, chr(0)) : $password); - $md5_digest = md5((substr($password, 0, 64) ^ str_repeat(chr(0x5C), 64)) . (pack('H32', md5((substr($password, 0, 64) ^ str_repeat(chr(0x36), 64)) . $md5_challenge)))); - - $base64_method_cram_md5 = base64_encode($username . ' ' . $md5_digest); - - $this->server_send($base64_method_cram_md5, true); - if ($err_msg = $this->server_parse('235', __LINE__)) - { - return $err_msg; - } - - return false; - } - - /** - * digest_md5 authentication method - * A real pain in the *** - */ - private function digest_md5($username, $password) - { - $this->server_send('AUTH DIGEST-MD5'); - if ($err_msg = $this->server_parse('334', __LINE__)) - { - return ($this->numeric_response_code == 503) ? false : $err_msg; - } - - $md5_challenge = base64_decode($this->responses[0]); - - // Parse the md5 challenge - from AUTH_SASL (PEAR) - $tokens = array(); - while (preg_match('/^([a-z-]+)=("[^"]+(?<!\\\)"|[^,]+)/i', $md5_challenge, $matches)) - { - // Ignore these as per rfc2831 - if ($matches[1] == 'opaque' || $matches[1] == 'domain') - { - $md5_challenge = substr($md5_challenge, strlen($matches[0]) + 1); - continue; - } - - // Allowed multiple "realm" and "auth-param" - if (!empty($tokens[$matches[1]]) && ($matches[1] == 'realm' || $matches[1] == 'auth-param')) - { - if (is_array($tokens[$matches[1]])) - { - $tokens[$matches[1]][] = preg_replace('/^"(.*)"$/', '\\1', $matches[2]); - } - else - { - $tokens[$matches[1]] = array($tokens[$matches[1]], preg_replace('/^"(.*)"$/', '\\1', $matches[2])); - } - } - else if (!empty($tokens[$matches[1]])) // Any other multiple instance = failure - { - $tokens = array(); - break; - } - else - { - $tokens[$matches[1]] = preg_replace('/^"(.*)"$/', '\\1', $matches[2]); - } - - // Remove the just parsed directive from the challenge - $md5_challenge = substr($md5_challenge, strlen($matches[0]) + 1); - } - - // Realm - if (empty($tokens['realm'])) - { - $tokens['realm'] = (function_exists('php_uname')) ? php_uname('n') : phpbb::$user->system['host']; - } - - // Maxbuf - if (empty($tokens['maxbuf'])) - { - $tokens['maxbuf'] = 65536; - } - - // Required: nonce, algorithm - if (empty($tokens['nonce']) || empty($tokens['algorithm'])) - { - $tokens = array(); - } - $md5_challenge = $tokens; - - if (!empty($md5_challenge)) - { - $str = ''; - for ($i = 0; $i < 32; $i++) - { - $str .= chr(mt_rand(0, 255)); - } - $cnonce = base64_encode($str); - - $digest_uri = 'smtp/' . phpbb::$config['smtp_host']; - - $auth_1 = sprintf('%s:%s:%s', pack('H32', md5(sprintf('%s:%s:%s', $username, $md5_challenge['realm'], $password))), $md5_challenge['nonce'], $cnonce); - $auth_2 = 'AUTHENTICATE:' . $digest_uri; - $response_value = md5(sprintf('%s:%s:00000001:%s:auth:%s', md5($auth_1), $md5_challenge['nonce'], $cnonce, md5($auth_2))); - - $input_string = sprintf('username="%s",realm="%s",nonce="%s",cnonce="%s",nc="00000001",qop=auth,digest-uri="%s",response=%s,%d', $username, $md5_challenge['realm'], $md5_challenge['nonce'], $cnonce, $digest_uri, $response_value, $md5_challenge['maxbuf']); - } - else - { - return (isset(phpbb::$user->lang['INVALID_DIGEST_CHALLENGE'])) ? phpbb::$user->lang['INVALID_DIGEST_CHALLENGE'] : 'Invalid digest challenge'; - } - - $base64_method_digest_md5 = base64_encode($input_string); - $this->server_send($base64_method_digest_md5, true); - if ($err_msg = $this->server_parse('334', __LINE__)) - { - return $err_msg; - } - - $this->server_send(' '); - if ($err_msg = $this->server_parse('235', __LINE__)) - { - return $err_msg; - } - - return false; - } -} - -/** -* Encodes the given string for proper display in UTF-8. -* -* This version is using base64 encoded data. The downside of this -* is if the mail client does not understand this encoding the user -* is basically doomed with an unreadable subject. -* -* Please note that this version fully supports RFC 2045 section 6.8. -*/ -function mail_encode($str) -{ - // define start delimimter, end delimiter and spacer - $start = "=?UTF-8?B?"; - $end = "?="; - $delimiter = "\r\n "; - - // Maximum length is 75. $split_length *must* be a multiple of 4, but <= 75 - strlen($start . $delimiter . $end)!!! - $split_length = 60; - $encoded_str = base64_encode($str); - - // If encoded string meets the limits, we just return with the correct data. - if (strlen($encoded_str) <= $split_length) - { - return $start . $encoded_str . $end; - } - - // If there is only ASCII data, we just return what we want, correctly splitting the lines. - if (strlen($str) === utf8_strlen($str)) - { - return $start . implode($end . $delimiter . $start, str_split($encoded_str, $split_length)) . $end; - } - - // UTF-8 data, compose encoded lines - $array = utf8_str_split($str); - $str = ''; - - while (sizeof($array)) - { - $text = ''; - - while (sizeof($array) && intval((strlen($text . $array[0]) + 2) / 3) << 2 <= $split_length) - { - $text .= array_shift($array); - } - - $str .= $start . base64_encode($text) . $end . $delimiter; - } - - return substr($str, 0, -strlen($delimiter)); -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/functions_module.php b/phpBB/includes/functions_module.php deleted file mode 100644 index c6c457aba4..0000000000 --- a/phpBB/includes/functions_module.php +++ /dev/null @@ -1,849 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Class handling all types of 'plugins' (a future term) -* @package phpBB3 -*/ -class p_master -{ - var $p_id; - var $p_class; - var $p_name; - var $p_mode; - var $p_parent; - - var $include_path = false; - var $active_module = false; - var $active_module_row_id = false; - var $acl_forum_id = false; - var $module_ary = array(); - - /** - * Constuctor - * Set module include path - */ - public function __construct($include_path = false) - { - $this->include_path = ($include_path !== false) ? $include_path : PHPBB_ROOT_PATH . 'modules/'; - - // Make sure the path ends with / - if (substr($this->include_path, -1) !== '/') - { - $this->include_path .= '/'; - } - } - - /** - * Set custom include path for modules - * Schema for inclusion is include_path . modulebase - * - * @param string $include_path include path to be used. - * @access public - */ - public function set_custom_include_path($include_path) - { - $this->include_path = $include_path; - - // Make sure the path ends with / - if (substr($this->include_path, -1) !== '/') - { - $this->include_path .= '/'; - } - } - - /** - * List modules - * - * This creates a list, stored in $this->module_ary of all available - * modules for the given class (ucp, mcp and acp). Additionally - * $this->module_y_ary is created with indentation information for - * displaying the module list appropriately. Only modules for which - * the user has access rights are included in these lists. - */ - function list_modules($p_class) - { - // Sanitise for future path use, it's escaped as appropriate for queries - $this->p_class = str_replace(array('.', '/', '\\'), '', basename($p_class)); - - // Get cached modules - if (($this->module_cache = phpbb::$acm->get('modules_' . $this->p_class)) === false) - { - // Get modules - $sql = 'SELECT * - FROM ' . MODULES_TABLE . " - WHERE module_class = '" . phpbb::$db->sql_escape($this->p_class) . "' - ORDER BY left_id ASC"; - $result = phpbb::$db->sql_query($sql); - - $rows = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $rows[$row['module_id']] = $row; - } - phpbb::$db->sql_freeresult($result); - - $this->module_cache = array(); - foreach ($rows as $module_id => $row) - { - $this->module_cache['modules'][] = $row; - $this->module_cache['parents'][$row['module_id']] = $this->get_parents($row['parent_id'], $row['left_id'], $row['right_id'], $rows); - } - unset($rows); - - phpbb::$acm->put('modules_' . $this->p_class, $this->module_cache); - } - - if (empty($this->module_cache)) - { - $this->module_cache = array('modules' => array(), 'parents' => array()); - } - - // We "could" build a true tree with this function - maybe mod authors want to use this... - // Functions for traversing and manipulating the tree are not available though - // We might re-structure the module system to use true trees in 3.2.x... - // $tree = $this->build_tree($this->module_cache['modules'], $this->module_cache['parents']); - - // Clean up module cache array to only let survive modules the user can access - $right_id = false; - foreach ($this->module_cache['modules'] as $key => $row) - { - // Not allowed to view module? - if (!$this->module_auth($row['module_auth'])) - { - unset($this->module_cache['modules'][$key]); - continue; - } - - // Category with no members, ignore - if (!$row['module_basename'] && ($row['left_id'] + 1 == $row['right_id'])) - { - unset($this->module_cache['modules'][$key]); - continue; - } - - // Skip branch - if ($right_id !== false) - { - if ($row['left_id'] < $right_id) - { - unset($this->module_cache['modules'][$key]); - continue; - } - - $right_id = false; - } - - // Not enabled? - if (!$row['module_enabled']) - { - // If category is disabled then disable every child too - unset($this->module_cache['modules'][$key]); - $right_id = $row['right_id']; - continue; - } - } - - // Re-index (this is needed, else we are not able to array_slice later) - $this->module_cache['modules'] = array_merge($this->module_cache['modules']); - - // Include MOD _info files for populating language entries within the menus - $this->add_mod_info($this->p_class); - - // Now build the module array, but exclude completely empty categories... - $right_id = false; - $names = array(); - - foreach ($this->module_cache['modules'] as $key => $row) - { - // Skip branch - if ($right_id !== false) - { - if ($row['left_id'] < $right_id) - { - continue; - } - - $right_id = false; - } - - // Category with no members on their way down (we have to check every level) - if (!$row['module_basename']) - { - $empty_category = true; - - // We go through the branch and look for an activated module - foreach (array_slice($this->module_cache['modules'], $key + 1) as $temp_row) - { - if ($temp_row['left_id'] > $row['left_id'] && $temp_row['left_id'] < $row['right_id']) - { - // Module there - if ($temp_row['module_basename'] && $temp_row['module_enabled']) - { - $empty_category = false; - break; - } - continue; - } - break; - } - - // Skip the branch - if ($empty_category) - { - $right_id = $row['right_id']; - continue; - } - } - - $depth = sizeof($this->module_cache['parents'][$row['module_id']]); - - // We need to prefix the functions to not create a naming conflict - - // Function for building 'url_extra' - $url_func = '_module_' . $row['module_basename'] . '_url'; - - // Function for building the language name - $lang_func = '_module_' . $row['module_basename'] . '_lang'; - - // Custom function for calling parameters on module init (for example assigning template variables) - $custom_func = '_module_' . $row['module_basename']; - - $names[$row['module_basename'] . '_' . $row['module_mode']][] = true; - - $module_row = array( - 'depth' => $depth, - - 'id' => (int) $row['module_id'], - 'parent' => (int) $row['parent_id'], - 'cat' => ($row['right_id'] > $row['left_id'] + 1) ? true : false, - - 'is_duplicate' => ($row['module_basename'] && sizeof($names[$row['module_basename'] . '_' . $row['module_mode']]) > 1) ? true : false, - - 'name' => (string) $row['module_basename'], - 'mode' => (string) $row['module_mode'], - 'display' => (int) $row['module_display'], - - 'url_extra' => (function_exists($url_func)) ? $url_func($row['module_mode'], $row) : '', - - 'lang' => ($row['module_basename'] && function_exists($lang_func)) ? $lang_func($row['module_mode'], $row['module_langname']) : phpbb::$user->lang($row['module_langname']), - 'langname' => $row['module_langname'], - - 'left' => $row['left_id'], - 'right' => $row['right_id'], - ); - - if (function_exists($custom_func)) - { - $custom_func($row['module_mode'], $module_row); - } - - $this->module_ary[] = $module_row; - } - - unset($this->module_cache['modules'], $names); - } - - /** - * Check if a certain main module is accessible/loaded - * By giving the module mode you are able to additionally check for only one mode within the main module - * - * @param string $module_basename The module base name, for example logs, reports, main (for the mcp). - * @param mixed $module_mode The module mode to check. If provided the mode will be checked in addition for presence. - * - * @return bool Returns true if module is loaded and accessible, else returns false - */ - function loaded($module_basename, $module_mode = false) - { - if (empty($this->loaded_cache)) - { - $this->loaded_cache = array(); - - foreach ($this->module_ary as $row) - { - if (!$row['name']) - { - continue; - } - - if (!isset($this->loaded_cache[$row['name']])) - { - $this->loaded_cache[$row['name']] = array(); - } - - if (!$row['mode']) - { - continue; - } - - $this->loaded_cache[$row['name']][$row['mode']] = true; - } - } - - if ($module_mode === false) - { - return (isset($this->loaded_cache[$module_basename])) ? true : false; - } - - return (!empty($this->loaded_cache[$module_basename][$module_mode])) ? true : false; - } - - /** - * Check module authorisation - */ - function module_auth($module_auth, $forum_id = false) - { - $module_auth = trim($module_auth); - - // Generally allowed to access module if module_auth is empty - if (!$module_auth) - { - return true; - } - - // With the code below we make sure only those elements get eval'd we really want to be checked - preg_match_all('/(?: - "[^"\\\\]*(?:\\\\.[^"\\\\]*)*" | - \'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*\' | - [(),] | - [^\s(),]+)/x', $module_auth, $match); - - $tokens = $match[0]; - for ($i = 0, $size = sizeof($tokens); $i < $size; $i++) - { - $token = &$tokens[$i]; - - switch ($token) - { - case ')': - case '(': - case '&&': - case '||': - case ',': - break; - - default: - if (!preg_match('#(?:acl_([a-z0-9_]+)(,\$id)?)|(?:\$id)|(?:aclf_([a-z0-9_]+))|(?:cfg_([a-z0-9_]+))|(?:request_([a-zA-Z0-9_]+))#', $token)) - { - $token = ''; - } - break; - } - } - - $module_auth = implode(' ', $tokens); - - // Make sure $id seperation is working fine - $module_auth = str_replace(' , ', ',', $module_auth); - - $forum_id = ($forum_id === false) ? $this->acl_forum_id : $forum_id; - - $is_auth = false; - eval('$is_auth = (int) (' . preg_replace(array('#acl_([a-z0-9_]+)(,\$id)?#', '#\$id#', '#aclf_([a-z0-9_]+)#', '#cfg_([a-z0-9_]+)#', '#request_([a-zA-Z0-9_]+)#'), array('(int) phpbb::$acl->acl_get(\'\\1\'\\2)', '(int) $forum_id', '(int) phpbb::$acl->acl_getf_global(\'\\1\')', '(int) phpbb::$config[\'\\1\']', 'phpbb_request::variable(\'\\1\', false)'), $module_auth) . ');'); - - return $is_auth; - } - - /** - * Set active module - */ - function set_active($id = false, $mode = false) - { - $icat = false; - $this->active_module = false; - - if (request_var('icat', '')) - { - $icat = $id; - $id = request_var('icat', ''); - } - - $category = false; - foreach ($this->module_ary as $row_id => $item_ary) - { - // If this is a module and it's selected, active - // If this is a category and the module is the first within it, active - // If this is a module and no mode selected, select first mode - // If no category or module selected, go active for first module in first category - if ( - (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && (($item_ary['mode'] == $mode && !$item_ary['cat']) || ($icat && $item_ary['cat']))) || - ($item_ary['parent'] === $category && !$item_ary['cat'] && !$icat && $item_ary['display']) || - (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && !$mode && !$item_ary['cat']) || - (!$id && !$mode && !$item_ary['cat'] && $item_ary['display']) - ) - { - if ($item_ary['cat']) - { - $id = $icat; - $icat = false; - - continue; - } - - $this->p_id = $item_ary['id']; - $this->p_parent = $item_ary['parent']; - $this->p_name = $item_ary['name']; - $this->p_mode = $item_ary['mode']; - $this->p_left = $item_ary['left']; - $this->p_right = $item_ary['right']; - - $this->module_cache['parents'] = $this->module_cache['parents'][$this->p_id]; - $this->active_module = $item_ary['id']; - $this->active_module_row_id = $row_id; - - break; - } - else if (($item_ary['cat'] && $item_ary['id'] === (int) $id) || ($item_ary['parent'] === $category && $item_ary['cat'])) - { - $category = $item_ary['id']; - } - } - } - - /** - * Loads currently active module - * - * This method loads a given module, passing it the relevant id and mode. - */ - function load_active($mode = false, $module_url = false, $execute_module = true) - { - $module_path = $this->include_path . $this->p_class; - $icat = request_var('icat', ''); - - if ($this->active_module === false) - { - trigger_error('Module not accessible', E_USER_ERROR); - } - - if (!class_exists("{$this->p_class}_$this->p_name")) - { - if (!file_exists("$module_path/{$this->p_class}_$this->p_name." . PHP_EXT)) - { - trigger_error("Cannot find module $module_path/{$this->p_class}_$this->p_name." . PHP_EXT, E_USER_ERROR); - } - - include("$module_path/{$this->p_class}_$this->p_name." . PHP_EXT); - - if (!class_exists("{$this->p_class}_$this->p_name")) - { - trigger_error("Module file $module_path/{$this->p_class}_$this->p_name." . PHP_EXT . " does not contain correct class [{$this->p_class}_$this->p_name]", E_USER_ERROR); - } - - if (!empty($mode)) - { - $this->p_mode = $mode; - } - - // Create a new instance of the desired module ... if it has a - // constructor it will of course be executed - $instance = "{$this->p_class}_$this->p_name"; - - $this->module = new $instance($this); - - // We pre-define the action parameter we are using all over the place - if (defined('IN_ADMIN')) - { - // Is first module automatically enabled a duplicate and the category not passed yet? - if (!$icat && $this->module_ary[$this->active_module_row_id]['is_duplicate']) - { - $icat = $this->module_ary[$this->active_module_row_id]['parent']; - } - - // Not being able to overwrite ;) - $this->module->u_action = phpbb::$url->append_sid(PHPBB_ADMIN_PATH . 'index.' . PHP_EXT, "i={$this->p_name}") . (($icat) ? '&icat=' . $icat : '') . "&mode={$this->p_mode}"; - } - else - { - // If user specified the module url we will use it... - if ($module_url !== false) - { - $this->module->u_action = $module_url; - } - else - { - $this->module->u_action = PHPBB_ROOT_PATH . ((phpbb::$user->page['page_dir']) ? phpbb::$user->page['page_dir'] . '/' : '') . phpbb::$user->page['page_name']; - } - - $this->module->u_action = phpbb::$url->append_sid($this->module->u_action, "i={$this->p_name}") . (($icat) ? '&icat=' . $icat : '') . "&mode={$this->p_mode}"; - } - - // Add url_extra parameter to u_action url - if (!empty($this->module_ary) && $this->active_module !== false && $this->module_ary[$this->active_module_row_id]['url_extra']) - { - $this->module->u_action .= $this->module_ary[$this->active_module_row_id]['url_extra']; - } - - // Assign the module path for re-usage - $this->module->module_path = $module_path . '/'; - - // Execute the main method for the new instance, we send the module id and mode as parameters - // Users are able to call the main method after this function to be able to assign additional parameters manually - if ($execute_module) - { - $this->module->main($this->p_name, $this->p_mode); - } - - return; - } - } - - /** - * Appending url parameter to the currently active module. - * - * This function is called for adding specific url parameters while executing the current module. - * It is doing the same as the _module_{name}_url() function, apart from being able to be called after - * having dynamically parsed specific parameters. This allows more freedom in choosing additional parameters. - * One example can be seen in /includes/mcp/mcp_notes.php - $this->p_master->adjust_url() call. - * - * @param string $url_extra Extra url parameters, e.g.: &u=$user_id - * - */ - function adjust_url($url_extra) - { - if (empty($this->module_ary[$this->active_module_row_id])) - { - return; - } - - $row = &$this->module_ary[$this->active_module_row_id]; - - // We check for the same url_extra in $row['url_extra'] to overcome doubled additions... - if (strpos($row['url_extra'], $url_extra) === false) - { - $row['url_extra'] .= $url_extra; - } - } - - /** - * Check if a module is active - */ - function is_active($id, $mode = false) - { - // If we find a name by this id and being enabled we have our active one... - foreach ($this->module_ary as $row_id => $item_ary) - { - if (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && $item_ary['display']) - { - if ($mode === false || $mode === $item_ary['mode']) - { - return true; - } - } - } - - return false; - } - - /** - * Get parents - */ - function get_parents($parent_id, $left_id, $right_id, &$all_parents) - { - $parents = array(); - - if ($parent_id > 0) - { - foreach ($all_parents as $module_id => $row) - { - if ($row['left_id'] < $left_id && $row['right_id'] > $right_id) - { - $parents[$module_id] = $row['parent_id']; - } - - if ($row['left_id'] > $left_id) - { - break; - } - } - } - - return $parents; - } - - /** - * Get tree branch - */ - function get_branch($left_id, $right_id, $remaining) - { - $branch = array(); - - foreach ($remaining as $key => $row) - { - if ($row['left_id'] > $left_id && $row['left_id'] < $right_id) - { - $branch[] = $row; - continue; - } - break; - } - - return $branch; - } - - /** - * Build true binary tree from given array - * Not in use - */ - function build_tree(&$modules, &$parents) - { - $tree = array(); - - foreach ($modules as $row) - { - $branch = &$tree; - - if ($row['parent_id']) - { - // Go through the tree to find our branch - $parent_tree = $parents[$row['module_id']]; - - foreach ($parent_tree as $id => $value) - { - if (!isset($branch[$id]) && isset($branch['child'])) - { - $branch = &$branch['child']; - } - $branch = &$branch[$id]; - } - $branch = &$branch['child']; - } - - $branch[$row['module_id']] = $row; - if (!isset($branch[$row['module_id']]['child'])) - { - $branch[$row['module_id']]['child'] = array(); - } - } - - return $tree; - } - - /** - * Build navigation structure - */ - function assign_tpl_vars($module_url) - { - $current_id = $right_id = false; - - // Make sure the module_url has a question mark set, effectively determining the delimiter to use - $delim = (strpos($module_url, '?') === false) ? '?' : '&'; - - $current_padding = $current_depth = 0; - $linear_offset = 'l_block1'; - $tabular_offset = 't_block2'; - - // Generate the list of modules, we'll do this in two ways ... - // 1) In a linear fashion - // 2) In a combined tabbed + linear fashion ... tabs for the categories - // and a linear list for subcategories/items - foreach ($this->module_ary as $row_id => $item_ary) - { - // Skip hidden modules - if (!$item_ary['display']) - { - continue; - } - - // Skip branch - if ($right_id !== false) - { - if ($item_ary['left'] < $right_id) - { - continue; - } - - $right_id = false; - } - - // Category with no members on their way down (we have to check every level) - if (!$item_ary['name']) - { - $empty_category = true; - - // We go through the branch and look for an activated module - foreach (array_slice($this->module_ary, $row_id + 1) as $temp_row) - { - if ($temp_row['left'] > $item_ary['left'] && $temp_row['left'] < $item_ary['right']) - { - // Module there and displayed? - if ($temp_row['name'] && $temp_row['display']) - { - $empty_category = false; - break; - } - continue; - } - break; - } - - // Skip the branch - if ($empty_category) - { - $right_id = $item_ary['right']; - continue; - } - } - - // Select first id we can get - if (!$current_id && (isset($this->module_cache['parents'][$item_ary['id']]) || $item_ary['id'] == $this->p_id)) - { - $current_id = $item_ary['id']; - } - - $depth = $item_ary['depth']; - - if ($depth > $current_depth) - { - $linear_offset = $linear_offset . '.l_block' . ($depth + 1); - $tabular_offset = ($depth + 1 > 2) ? $tabular_offset . '.t_block' . ($depth + 1) : $tabular_offset; - } - else if ($depth < $current_depth) - { - for ($i = $current_depth - $depth; $i > 0; $i--) - { - $linear_offset = substr($linear_offset, 0, strrpos($linear_offset, '.')); - $tabular_offset = ($i + $depth > 1) ? substr($tabular_offset, 0, strrpos($tabular_offset, '.')) : $tabular_offset; - } - } - - $u_title = $module_url . $delim . 'i=' . (($item_ary['cat']) ? $item_ary['id'] : $item_ary['name'] . (($item_ary['is_duplicate']) ? '&icat=' . $current_id : '') . '&mode=' . $item_ary['mode']); - - // Was not allowed in categories before - /*!$item_ary['cat'] && */ - $u_title .= (isset($item_ary['url_extra'])) ? $item_ary['url_extra'] : ''; - - // Only output a categories items if it's currently selected - if (!$depth || ($depth && (in_array($item_ary['parent'], array_values($this->module_cache['parents'])) || $item_ary['parent'] == $this->p_parent))) - { - $use_tabular_offset = (!$depth) ? 't_block1' : $tabular_offset; - - $tpl_ary = array( - 'L_TITLE' => $item_ary['lang'], - 'S_SELECTED' => (isset($this->module_cache['parents'][$item_ary['id']]) || $item_ary['id'] == $this->p_id) ? true : false, - 'U_TITLE' => $u_title - ); - - phpbb::$template->assign_block_vars($use_tabular_offset, array_merge($tpl_ary, array_change_key_case($item_ary, CASE_UPPER))); - } - - $tpl_ary = array( - 'L_TITLE' => $item_ary['lang'], - 'S_SELECTED' => (isset($this->module_cache['parents'][$item_ary['id']]) || $item_ary['id'] == $this->p_id) ? true : false, - 'U_TITLE' => $u_title - ); - - phpbb::$template->assign_block_vars($linear_offset, array_merge($tpl_ary, array_change_key_case($item_ary, CASE_UPPER))); - - $current_depth = $depth; - } - } - - /** - * Returns desired template name - */ - function get_tpl_name() - { - return $this->module->tpl_name . '.html'; - } - - /** - * Returns the desired page title - */ - function get_page_title() - { - if (!isset($this->module->page_title)) - { - return ''; - } - - return phpbb::$user->lang($this->module->page_title); - } - - /** - * Load module as the current active one without the need for registering it - */ - function load($class, $name, $mode = false) - { - $this->p_class = $class; - $this->p_name = $name; - - // Set active module to true instead of using the id - $this->active_module = true; - - $this->load_active($mode); - } - - /** - * Display module - */ - function display($page_title, $display_online_list = true) - { - page_header($page_title, $display_online_list); - - phpbb::$template->set_filenames(array( - 'body' => $this->get_tpl_name()) - ); - - page_footer(); - } - - /** - * Toggle whether this module will be displayed or not - */ - function set_display($id, $mode = false, $display = true) - { - foreach ($this->module_ary as $row_id => $item_ary) - { - if (($item_ary['name'] === $id || $item_ary['id'] === (int) $id) && (!$mode || $item_ary['mode'] === $mode)) - { - $this->module_ary[$row_id]['display'] = (int) $display; - } - } - } - - /** - * Add custom MOD info language file - */ - function add_mod_info($module_class) - { - if (file_exists(phpbb::$user->lang_path . phpbb::$user->lang_name . '/mods')) - { - $add_files = array(); - - $dir = @opendir(phpbb::$user->lang_path . phpbb::$user->lang_name . '/mods'); - - if ($dir) - { - while (($entry = readdir($dir)) !== false) - { - if (strpos($entry, 'info_' . strtolower($module_class) . '_') === 0 && substr(strrchr($entry, '.'), 1) == PHP_EXT) - { - $add_files[] = 'mods/' . substr(basename($entry), 0, -(strlen(PHP_EXT) + 1)); - } - } - closedir($dir); - } - - if (sizeof($add_files)) - { - phpbb::$user->add_lang($add_files); - } - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/functions_posting.php b/phpBB/includes/functions_posting.php deleted file mode 100644 index 1b5e434215..0000000000 --- a/phpBB/includes/functions_posting.php +++ /dev/null @@ -1,2508 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Fill smiley templates (or just the variables) with smilies, either in a window or inline -*/ -function generate_smilies($mode, $forum_id) -{ - if ($mode == 'window') - { - if ($forum_id) - { - $sql = 'SELECT forum_style - FROM ' . FORUMS_TABLE . " - WHERE forum_id = $forum_id"; - $result = phpbb::$db->sql_query_limit($sql, 1); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - phpbb::$user->setup('posting', (int) $row['forum_style']); - } - else - { - phpbb::$user->setup('posting'); - } - - page_header(phpbb::$user->lang['SMILIES']); - - phpbb::$template->set_filenames(array( - 'body' => 'posting_smilies.html', - )); - } - - $display_link = false; - if ($mode == 'inline') - { - $sql = 'SELECT smiley_id - FROM ' . SMILIES_TABLE . ' - WHERE display_on_posting = 0'; - $result = phpbb::$db->sql_query_limit($sql, 1, 0, 3600); - - if ($row = phpbb::$db->sql_fetchrow($result)) - { - $display_link = true; - } - phpbb::$db->sql_freeresult($result); - } - - $last_url = ''; - - $sql = 'SELECT * - FROM ' . SMILIES_TABLE . - (($mode == 'inline') ? ' WHERE display_on_posting = 1 ' : '') . ' - ORDER BY smiley_order'; - $result = phpbb::$db->sql_query($sql, 3600); - - $smilies = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if (empty($smilies[$row['smiley_url']])) - { - $smilies[$row['smiley_url']] = $row; - } - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($smilies)) - { - foreach ($smilies as $row) - { - phpbb::$template->assign_block_vars('smiley', array( - 'SMILEY_CODE' => $row['code'], - 'A_SMILEY_CODE' => addslashes($row['code']), - 'SMILEY_IMG' => PHPBB_ROOT_PATH . phpbb::$config['smilies_path'] . '/' . $row['smiley_url'], - 'SMILEY_WIDTH' => $row['smiley_width'], - 'SMILEY_HEIGHT' => $row['smiley_height'], - 'SMILEY_DESC' => $row['emotion'], - )); - } - } - - if ($mode == 'inline' && $display_link) - { - phpbb::$template->assign_vars(array( - 'S_SHOW_SMILEY_LINK' => true, - 'U_MORE_SMILIES' => append_sid('posting', 'mode=smilies&f=' . $forum_id), - )); - } - - if ($mode == 'window') - { - page_footer(); - } -} - -/** -* Update last post information -* Should be used instead of sync() if only the last post information are out of sync... faster -* -* @param string $type Can be forum|topic -* @param mixed $ids topic/forum ids -* @param bool $return_update_sql true: SQL query shall be returned, false: execute SQL -*/ -function update_post_information($type, $ids, $return_update_sql = false) -{ - if (empty($ids)) - { - return; - } - if (!is_array($ids)) - { - $ids = array($ids); - } - - - $update_sql = $empty_forums = $not_empty_forums = array(); - - if ($type != 'topic') - { - $topic_join = ', ' . TOPICS_TABLE . ' t'; - $topic_condition = 'AND t.topic_id = p.topic_id AND t.topic_approved = 1'; - } - else - { - $topic_join = ''; - $topic_condition = ''; - } - - if (sizeof($ids) == 1) - { - $sql = 'SELECT MAX(p.post_id) as last_post_id - FROM ' . POSTS_TABLE . " p $topic_join - WHERE " . phpbb::$db->sql_in_set('p.' . $type . '_id', $ids) . " - $topic_condition - AND p.post_approved = 1"; - } - else - { - $sql = 'SELECT p.' . $type . '_id, MAX(p.post_id) as last_post_id - FROM ' . POSTS_TABLE . " p $topic_join - WHERE " . phpbb::$db->sql_in_set('p.' . $type . '_id', $ids) . " - $topic_condition - AND p.post_approved = 1 - GROUP BY p.{$type}_id"; - } - $result = phpbb::$db->sql_query($sql); - - $last_post_ids = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if (sizeof($ids) == 1) - { - $row[$type . '_id'] = $ids[0]; - } - - if ($type == 'forum') - { - $not_empty_forums[] = $row['forum_id']; - - if (empty($row['last_post_id'])) - { - $empty_forums[] = $row['forum_id']; - } - } - - $last_post_ids[] = $row['last_post_id']; - } - phpbb::$db->sql_freeresult($result); - - if ($type == 'forum') - { - $empty_forums = array_merge($empty_forums, array_diff($ids, $not_empty_forums)); - - foreach ($empty_forums as $void => $forum_id) - { - $update_sql[$forum_id][] = 'forum_last_post_id = 0'; - $update_sql[$forum_id][] = "forum_last_post_subject = ''"; - $update_sql[$forum_id][] = 'forum_last_post_time = 0'; - $update_sql[$forum_id][] = 'forum_last_poster_id = 0'; - $update_sql[$forum_id][] = "forum_last_poster_name = ''"; - $update_sql[$forum_id][] = "forum_last_poster_colour = ''"; - } - } - - if (sizeof($last_post_ids)) - { - $sql = 'SELECT p.' . $type . '_id, p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour - FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u - WHERE p.poster_id = u.user_id - AND ' . phpbb::$db->sql_in_set('p.post_id', $last_post_ids); - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $update_sql[$row["{$type}_id"]][] = $type . '_last_post_id = ' . (int) $row['post_id']; - $update_sql[$row["{$type}_id"]][] = "{$type}_last_post_subject = '" . phpbb::$db->sql_escape($row['post_subject']) . "'"; - $update_sql[$row["{$type}_id"]][] = $type . '_last_post_time = ' . (int) $row['post_time']; - $update_sql[$row["{$type}_id"]][] = $type . '_last_poster_id = ' . (int) $row['poster_id']; - $update_sql[$row["{$type}_id"]][] = "{$type}_last_poster_colour = '" . phpbb::$db->sql_escape($row['user_colour']) . "'"; - $update_sql[$row["{$type}_id"]][] = "{$type}_last_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? phpbb::$db->sql_escape($row['post_username']) : phpbb::$db->sql_escape($row['username'])) . "'"; - } - phpbb::$db->sql_freeresult($result); - } - unset($empty_forums, $ids, $last_post_ids); - - if ($return_update_sql || !sizeof($update_sql)) - { - return $update_sql; - } - - $table = ($type == 'forum') ? FORUMS_TABLE : TOPICS_TABLE; - - foreach ($update_sql as $update_id => $update_sql_ary) - { - $sql = "UPDATE $table - SET " . implode(', ', $update_sql_ary) . " - WHERE {$type}_id = $update_id"; - phpbb::$db->sql_query($sql); - } - - return; -} - -/** -* Generate Topic Icons for display -*/ -function posting_gen_topic_icons($mode, $icon_id) -{ - // Grab icons - $icons = phpbb_cache::obtain_icons(); - - if (!$icon_id) - { - phpbb::$template->assign_var('S_NO_ICON_CHECKED', ' checked="checked"'); - } - - if (sizeof($icons)) - { - foreach ($icons as $id => $data) - { - if ($data['display']) - { - phpbb::$template->assign_block_vars('topic_icon', array( - 'ICON_ID' => $id, - 'ICON_IMG' => PHPBB_ROOT_PATH . phpbb::$config['icons_path'] . '/' . $data['img'], - 'ICON_WIDTH' => $data['width'], - 'ICON_HEIGHT' => $data['height'], - - 'S_CHECKED' => ($id == $icon_id) ? true : false, - 'S_ICON_CHECKED' => ($id == $icon_id) ? ' checked="checked"' : '', - )); - } - } - - return true; - } - - return false; -} - -/** -* Build topic types able to be selected -*/ -function posting_gen_topic_types($forum_id, $cur_topic_type = POST_NORMAL) -{ - global $topic_type; - - $toggle = false; - - $topic_types = array( - 'sticky' => array('const' => POST_STICKY, 'lang' => 'POST_STICKY'), - 'announce' => array('const' => POST_ANNOUNCE, 'lang' => 'POST_ANNOUNCEMENT'), - 'global' => array('const' => POST_GLOBAL, 'lang' => 'POST_GLOBAL') - ); - - $topic_type_array = array(); - - foreach ($topic_types as $auth_key => $topic_value) - { - // We do not have a special post global announcement permission - $auth_key = ($auth_key == 'global') ? 'announce' : $auth_key; - - if (phpbb::$acl->acl_get('f_' . $auth_key, $forum_id)) - { - $toggle = true; - - $topic_type_array[] = array( - 'VALUE' => $topic_value['const'], - 'S_CHECKED' => ($cur_topic_type == $topic_value['const'] || ($forum_id == 0 && $topic_value['const'] == POST_GLOBAL)) ? ' checked="checked"' : '', - 'L_TOPIC_TYPE' => phpbb::$user->lang[$topic_value['lang']] - ); - } - } - - if ($toggle) - { - $topic_type_array = array_merge(array(0 => array( - 'VALUE' => POST_NORMAL, - 'S_CHECKED' => ($topic_type == POST_NORMAL) ? ' checked="checked"' : '', - 'L_TOPIC_TYPE' => phpbb::$user->lang['POST_NORMAL'])), - - $topic_type_array - ); - - foreach ($topic_type_array as $array) - { - phpbb::$template->assign_block_vars('topic_type', $array); - } - - phpbb::$template->assign_vars(array( - 'S_TOPIC_TYPE_STICKY' => (phpbb::$acl->acl_get('f_sticky', $forum_id)), - 'S_TOPIC_TYPE_ANNOUNCE' => (phpbb::$acl->acl_get('f_announce', $forum_id)), - )); - } - - return $toggle; -} - -// -// Attachment related functions -// - -/** -* Upload Attachment - filedata is generated here -* Uses upload class -*/ -function upload_attachment($form_name, $forum_id, $local = false, $local_storage = '', $is_message = false, $local_filedata = false) -{ - $filedata = array( - 'error' => array() - ); - - include_once(PHPBB_ROOT_PATH . 'includes/functions_upload.' . PHP_EXT); - $upload = new fileupload(); - - if (phpbb::$config['check_attachment_content']) - { - $upload->set_disallowed_content(explode('|', phpbb::$config['mime_triggers'])); - } - - if (!$local) - { - $filedata['post_attach'] = ($upload->is_valid($form_name)) ? true : false; - } - else - { - $filedata['post_attach'] = true; - } - - if (!$filedata['post_attach']) - { - $filedata['error'][] = phpbb::$user->lang['NO_UPLOAD_FORM_FOUND']; - return $filedata; - } - - $extensions = ($is_message) ? phpbb_cache::obtain_extensions_pm() : phpbb_cache::obtain_extensions_forum($forum_id); - $upload->set_allowed_extensions(array_keys($extensions['_allowed_'])); - - $file = ($local) ? $upload->local_upload($local_storage, $local_filedata) : $upload->form_upload($form_name); - - if ($file->init_error) - { - $filedata['post_attach'] = false; - return $filedata; - } - - $cat_id = (isset($extensions[$file->get('extension')]['display_cat'])) ? $extensions[$file->get('extension')]['display_cat'] : ATTACHMENT_CATEGORY_NONE; - - // Make sure the image category only holds valid images... - if ($cat_id == ATTACHMENT_CATEGORY_IMAGE && !$file->is_image()) - { - $file->remove(); - - // If this error occurs a user tried to exploit an IE Bug by renaming extensions - // Since the image category is displaying content inline we need to catch this. - trigger_error(phpbb::$user->lang['ATTACHED_IMAGE_NOT_IMAGE']); - } - - // Do we have to create a thumbnail? - $filedata['thumbnail'] = ($cat_id == ATTACHMENT_CATEGORY_IMAGE && phpbb::$config['img_create_thumbnail']) ? 1 : 0; - - // Check Image Size, if it is an image - if (!phpbb::$acl->acl_get('a_') && !phpbb::$acl->acl_get('m_', $forum_id) && $cat_id == ATTACHMENT_CATEGORY_IMAGE) - { - $file->upload->set_allowed_dimensions(0, 0, phpbb::$config['img_max_width'], phpbb::$config['img_max_height']); - } - - // Admins and mods are allowed to exceed the allowed filesize - if (!phpbb::$acl->acl_get('a_') && !phpbb::$acl->acl_get('m_', $forum_id)) - { - if (!empty($extensions[$file->get('extension')]['max_filesize'])) - { - $allowed_filesize = $extensions[$file->get('extension')]['max_filesize']; - } - else - { - $allowed_filesize = ($is_message) ? phpbb::$config['max_filesize_pm'] : phpbb::$config['max_filesize']; - } - - $file->upload->set_max_filesize($allowed_filesize); - } - - $file->clean_filename('unique', phpbb::$user->data['user_id'] . '_'); - - // Are we uploading an image *and* this image being within the image category? Only then perform additional image checks. - $no_image = ($cat_id == ATTACHMENT_CATEGORY_IMAGE) ? false : true; - - $file->move_file(phpbb::$config['upload_path'], false, $no_image); - - if (sizeof($file->error)) - { - $file->remove(); - $filedata['error'] = array_merge($filedata['error'], $file->error); - $filedata['post_attach'] = false; - - return $filedata; - } - - $filedata['filesize'] = $file->get('filesize'); - $filedata['mimetype'] = $file->get('mimetype'); - $filedata['extension'] = $file->get('extension'); - $filedata['physical_filename'] = $file->get('realname'); - $filedata['real_filename'] = $file->get('uploadname'); - $filedata['filetime'] = time(); - - // Check our complete quota - if (phpbb::$config['attachment_quota']) - { - if (phpbb::$config['upload_dir_size'] + $file->get('filesize') > phpbb::$config['attachment_quota']) - { - $filedata['error'][] = phpbb::$user->lang['ATTACH_QUOTA_REACHED']; - $filedata['post_attach'] = false; - - $file->remove(); - - return $filedata; - } - } - - // Check free disk space - if ($free_space = @disk_free_space(PHPBB_ROOT_PATH . phpbb::$config['upload_path'])) - { - if ($free_space <= $file->get('filesize')) - { - $filedata['error'][] = phpbb::$user->lang['ATTACH_QUOTA_REACHED']; - $filedata['post_attach'] = false; - - $file->remove(); - - return $filedata; - } - } - - // Create Thumbnail - if ($filedata['thumbnail']) - { - $source = $file->get('destination_file'); - $destination = $file->get('destination_path') . '/thumb_' . $file->get('realname'); - - if (!create_thumbnail($source, $destination, $file->get('mimetype'))) - { - $filedata['thumbnail'] = 0; - } - } - - return $filedata; -} - -/** -* Calculate the needed size for Thumbnail -*/ -function get_img_size_format($width, $height) -{ - // Maximum Width the Image can take - $max_width = (phpbb::$config['img_max_thumb_width']) ? phpbb::$config['img_max_thumb_width'] : 400; - - if ($width > $height) - { - return array( - round($width * ($max_width / $width)), - round($height * ($max_width / $width)) - ); - } - else - { - return array( - round($width * ($max_width / $height)), - round($height * ($max_width / $height)) - ); - } -} - -/** -* Return supported image types -*/ -function get_supported_image_types($type = false) -{ - if (@extension_loaded('gd')) - { - $format = imagetypes(); - $new_type = 0; - - if ($type !== false) - { - // Type is one of the IMAGETYPE constants - it is fetched from getimagesize() - // We do not use the constants here, because some were not available in PHP 4.3.x - switch ($type) - { - // GIF - case 1: - $new_type = ($format & IMG_GIF) ? IMG_GIF : false; - break; - - // JPG, JPC, JP2 - case 2: - case 9: - case 10: - case 11: - case 12: - $new_type = ($format & IMG_JPG) ? IMG_JPG : false; - break; - - // PNG - case 3: - $new_type = ($format & IMG_PNG) ? IMG_PNG : false; - break; - - // WBMP - case 15: - $new_type = ($format & IMG_WBMP) ? IMG_WBMP : false; - break; - } - } - else - { - $new_type = array(); - $go_through_types = array(IMG_GIF, IMG_JPG, IMG_PNG, IMG_WBMP); - - foreach ($go_through_types as $check_type) - { - if ($format & $check_type) - { - $new_type[] = $check_type; - } - } - } - - return array( - 'gd' => ($new_type) ? true : false, - 'format' => $new_type, - 'version' => (function_exists('imagecreatetruecolor')) ? 2 : 1 - ); - } - - return array('gd' => false); -} - -/** -* Create Thumbnail -*/ -function create_thumbnail($source, $destination, $mimetype) -{ - $min_filesize = (int) phpbb::$config['img_min_thumb_filesize']; - $img_filesize = (file_exists($source)) ? @filesize($source) : false; - - if (!$img_filesize || $img_filesize <= $min_filesize) - { - return false; - } - - $dimension = @getimagesize($source); - - if ($dimension === false) - { - return false; - } - - list($width, $height, $type, ) = $dimension; - - if (empty($width) || empty($height)) - { - return false; - } - - list($new_width, $new_height) = get_img_size_format($width, $height); - - // Do not create a thumbnail if the resulting width/height is bigger than the original one - if ($new_width >= $width && $new_height >= $height) - { - return false; - } - - $used_imagick = false; - - // Only use imagemagick if defined and the passthru function not disabled - if (phpbb::$config['img_imagick'] && function_exists('passthru')) - { - if (substr(phpbb::$config['img_imagick'], -1) !== '/') - { - phpbb::$config['img_imagick'] .= '/'; - } - - @passthru(escapeshellcmd(phpbb::$config['img_imagick']) . 'convert' . ((defined('PHP_OS') && preg_match('#^win#i', PHP_OS)) ? '.exe' : '') . ' -quality 85 -geometry ' . $new_width . 'x' . $new_height . ' "' . str_replace('\\', '/', $source) . '" "' . str_replace('\\', '/', $destination) . '"'); - - if (file_exists($destination)) - { - $used_imagick = true; - } - } - - if (!$used_imagick) - { - $type = get_supported_image_types($type); - - if ($type['gd']) - { - // If the type is not supported, we are not able to create a thumbnail - if ($type['format'] === false) - { - return false; - } - - switch ($type['format']) - { - case IMG_GIF: - $image = @imagecreatefromgif($source); - break; - - case IMG_JPG: - $image = @imagecreatefromjpeg($source); - break; - - case IMG_PNG: - $image = @imagecreatefrompng($source); - break; - - case IMG_WBMP: - $image = @imagecreatefromwbmp($source); - break; - } - - if ($type['version'] == 1) - { - $new_image = imagecreate($new_width, $new_height); - - if ($new_image === false) - { - return false; - } - - imagecopyresized($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height); - } - else - { - $new_image = imagecreatetruecolor($new_width, $new_height); - - if ($new_image === false) - { - return false; - } - - // Preserve alpha transparency (png for example) - @imagealphablending($new_image, false); - @imagesavealpha($new_image, true); - - imagecopyresampled($new_image, $image, 0, 0, 0, 0, $new_width, $new_height, $width, $height); - } - - // If we are in safe mode create the destination file prior to using the gd functions to circumvent a PHP bug - if (@ini_get('safe_mode') || @strtolower(ini_get('safe_mode')) == 'on') - { - @touch($destination); - } - - switch ($type['format']) - { - case IMG_GIF: - imagegif($new_image, $destination); - break; - - case IMG_JPG: - imagejpeg($new_image, $destination, 90); - break; - - case IMG_PNG: - imagepng($new_image, $destination); - break; - - case IMG_WBMP: - imagewbmp($new_image, $destination); - break; - } - - imagedestroy($new_image); - } - else - { - return false; - } - } - - if (!file_exists($destination)) - { - return false; - } - - phpbb::$system->chmod($destination, phpbb::CHMOD_READ | phpbb::CHMOD_WRITE); - - return true; -} - -/** -* Assign Inline attachments (build option fields) -*/ -function posting_gen_inline_attachments(&$attachment_data) -{ - if (sizeof($attachment_data)) - { - $s_inline_attachment_options = ''; - - foreach ($attachment_data as $i => $attachment) - { - $s_inline_attachment_options .= '<option value="' . $i . '">' . basename($attachment['real_filename']) . '</option>'; - } - - phpbb::$template->assign_var('S_INLINE_ATTACHMENT_OPTIONS', $s_inline_attachment_options); - - return true; - } - - return false; -} - -/** -* Generate inline attachment entry -*/ -function posting_gen_attachment_entry($attachment_data, &$filename_data, $show_attach_box = true) -{ - // Some default template variables - phpbb::$template->assign_vars(array( - 'S_SHOW_ATTACH_BOX' => $show_attach_box, - 'S_HAS_ATTACHMENTS' => sizeof($attachment_data), - 'FILESIZE' => phpbb::$config['max_filesize'], - 'FILE_COMMENT' => (isset($filename_data['filecomment'])) ? $filename_data['filecomment'] : '', - )); - - if (sizeof($attachment_data)) - { - // We display the posted attachments within the desired order. - (phpbb::$config['display_order']) ? krsort($attachment_data) : ksort($attachment_data); - - foreach ($attachment_data as $count => $attach_row) - { - $hidden = ''; - $attach_row['real_filename'] = basename($attach_row['real_filename']); - - foreach ($attach_row as $key => $value) - { - $hidden .= '<input type="hidden" name="attachment_data[' . $count . '][' . $key . ']" value="' . $value . '" />'; - } - - $download_link = append_sid('download/file', 'mode=view&id=' . (int) $attach_row['attach_id'], true, ($attach_row['is_orphan']) ? phpbb::$user->session_id : false); - - phpbb::$template->assign_block_vars('attach_row', array( - 'FILENAME' => basename($attach_row['real_filename']), - 'A_FILENAME' => addslashes(basename($attach_row['real_filename'])), - 'FILE_COMMENT' => $attach_row['attach_comment'], - 'ATTACH_ID' => $attach_row['attach_id'], - 'S_IS_ORPHAN' => $attach_row['is_orphan'], - 'ASSOC_INDEX' => $count, - - 'U_VIEW_ATTACHMENT' => $download_link, - 'S_HIDDEN' => $hidden, - )); - } - } - - return sizeof($attachment_data); -} - -// -// General Post functions -// - -/** -* Load Drafts -*/ -function load_drafts($topic_id = 0, $forum_id = 0, $id = 0) -{ - $topic_ids = $forum_ids = $draft_rows = array(); - - // Load those drafts not connected to forums/topics - // If forum_id == 0 AND topic_id == 0 then this is a PM draft - if (!$topic_id && !$forum_id) - { - $sql_and = ' AND d.forum_id = 0 AND d.topic_id = 0'; - } - else - { - $sql_and = ''; - $sql_and .= ($forum_id) ? ' AND d.forum_id = ' . (int) $forum_id : ''; - $sql_and .= ($topic_id) ? ' AND d.topic_id = ' . (int) $topic_id : ''; - } - - $sql = 'SELECT d.*, f.forum_id, f.forum_name - FROM ' . DRAFTS_TABLE . ' d - LEFT JOIN ' . FORUMS_TABLE . ' f ON (f.forum_id = d.forum_id) - WHERE d.user_id = ' . phpbb::$user->data['user_id'] . " - $sql_and - ORDER BY d.save_time DESC"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($row['topic_id']) - { - $topic_ids[] = (int) $row['topic_id']; - } - $draft_rows[] = $row; - } - phpbb::$db->sql_freeresult($result); - - if (!sizeof($draft_rows)) - { - return; - } - - $topic_rows = array(); - if (sizeof($topic_ids)) - { - $sql = 'SELECT topic_id, forum_id, topic_title - FROM ' . TOPICS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('topic_id', array_unique($topic_ids)); - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $topic_rows[$row['topic_id']] = $row; - } - phpbb::$db->sql_freeresult($result); - } - unset($topic_ids); - - phpbb::$template->assign_var('S_SHOW_DRAFTS', true); - - foreach ($draft_rows as $draft) - { - $link_topic = $link_forum = $link_pm = false; - $insert_url = $view_url = $title = ''; - - if (isset($topic_rows[$draft['topic_id']]) - && ( - ($topic_rows[$draft['topic_id']]['forum_id'] && phpbb::$acl->acl_get('f_read', $topic_rows[$draft['topic_id']]['forum_id'])) - || - (!$topic_rows[$draft['topic_id']]['forum_id'] && phpbb::$acl->acl_getf_global('f_read')) - )) - { - $topic_forum_id = ($topic_rows[$draft['topic_id']]['forum_id']) ? $topic_rows[$draft['topic_id']]['forum_id'] : $forum_id; - - $link_topic = true; - $view_url = append_sid('viewtopic', 'f=' . $topic_forum_id . '&t=' . $draft['topic_id']); - $title = $topic_rows[$draft['topic_id']]['topic_title']; - - $insert_url = append_sid('posting', 'f=' . $topic_forum_id . '&t=' . $draft['topic_id'] . '&mode=reply&d=' . $draft['draft_id']); - } - else if ($draft['forum_id'] && phpbb::$acl->acl_get('f_read', $draft['forum_id'])) - { - $link_forum = true; - $view_url = append_sid('viewforum', 'f=' . $draft['forum_id']); - $title = $draft['forum_name']; - - $insert_url = append_sid('posting', 'f=' . $draft['forum_id'] . '&mode=post&d=' . $draft['draft_id']); - } - else - { - // Either display as PM draft if forum_id and topic_id are empty or if access to the forums has been denied afterwards... - $link_pm = true; - $insert_url = append_sid('ucp', "i=$id&mode=compose&d={$draft['draft_id']}"); - } - - phpbb::$template->assign_block_vars('draftrow', array( - 'DRAFT_ID' => $draft['draft_id'], - 'DATE' => phpbb::$user->format_date($draft['save_time']), - 'DRAFT_SUBJECT' => $draft['draft_subject'], - - 'TITLE' => $title, - 'U_VIEW' => $view_url, - 'U_INSERT' => $insert_url, - - 'S_LINK_PM' => $link_pm, - 'S_LINK_TOPIC' => $link_topic, - 'S_LINK_FORUM' => $link_forum, - )); - } -} - -/** -* Topic Review -*/ -function topic_review($topic_id, $forum_id, $mode = 'topic_review', $cur_post_id = 0, $show_quote_button = true) -{ - global $bbcode; - - // Go ahead and pull all data for this topic - $sql = 'SELECT p.post_id - FROM ' . POSTS_TABLE . ' p' . " - WHERE p.topic_id = $topic_id - " . ((!phpbb::$acl->acl_get('m_approve', $forum_id)) ? 'AND p.post_approved = 1' : '') . ' - ' . (($mode == 'post_review') ? " AND p.post_id > $cur_post_id" : '') . ' - ORDER BY p.post_time '; - $sql .= ($mode == 'post_review') ? 'ASC' : 'DESC'; - $result = phpbb::$db->sql_query_limit($sql, phpbb::$config['posts_per_page']); - - $post_list = array(); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $post_list[] = $row['post_id']; - } - phpbb::$db->sql_freeresult($result); - - if (!sizeof($post_list)) - { - return false; - } - - $sql = phpbb::$db->sql_build_query('SELECT', array( - 'SELECT' => 'u.username, u.user_id, u.user_colour, p.*, z.friend, z.foe', - - 'FROM' => array( - USERS_TABLE => 'u', - POSTS_TABLE => 'p', - ), - - 'LEFT_JOIN' => array( - array( - 'FROM' => array(ZEBRA_TABLE => 'z'), - 'ON' => 'z.user_id = ' . phpbb::$user->data['user_id'] . ' AND z.zebra_id = p.poster_id' - ) - ), - - 'WHERE' => phpbb::$db->sql_in_set('p.post_id', $post_list) . ' - AND u.user_id = p.poster_id' - )); - - $result = phpbb::$db->sql_query($sql); - - $bbcode_bitfield = ''; - $rowset = array(); - $has_attachments = false; - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $rowset[$row['post_id']] = $row; - $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']); - - if ($row['post_attachment']) - { - $has_attachments = true; - } - } - phpbb::$db->sql_freeresult($result); - - // Instantiate BBCode class - if (!isset($bbcode) && $bbcode_bitfield !== '') - { - include_once(PHPBB_ROOT_PATH . 'includes/bbcode.' . PHP_EXT); - $bbcode = new bbcode(base64_encode($bbcode_bitfield)); - } - - // Grab extensions - $extensions = $attachments = array(); - if ($has_attachments && phpbb::$acl->acl_get('u_download') && phpbb::$acl->acl_get('f_download', $forum_id)) - { - $extensions = phpbb_cache::obtain_extensions_forum($forum_id); - - // Get attachments... - $sql = 'SELECT * - FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('post_msg_id', $post_list) . ' - AND in_message = 0 - ORDER BY filetime DESC, post_msg_id ASC'; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $attachments[$row['post_msg_id']][] = $row; - } - phpbb::$db->sql_freeresult($result); - } - - for ($i = 0, $end = sizeof($post_list); $i < $end; ++$i) - { - // A non-existing rowset only happens if there was no user present for the entered poster_id - // This could be a broken posts table. - if (!isset($rowset[$post_list[$i]])) - { - continue; - } - - $row =& $rowset[$post_list[$i]]; - - $poster_id = $row['user_id']; - $post_subject = $row['post_subject']; - $message = censor_text($row['post_text']); - - $decoded_message = false; - - if ($show_quote_button && phpbb::$acl->acl_get('f_reply', $forum_id)) - { - $decoded_message = $message; - decode_message($decoded_message, $row['bbcode_uid']); - - $decoded_message = bbcode_nl2br($decoded_message); - } - - if ($row['bbcode_bitfield']) - { - $bbcode->bbcode_second_pass($message, $row['bbcode_uid'], $row['bbcode_bitfield']); - } - - $message = bbcode_nl2br($message); - $message = smiley_text($message, !$row['enable_smilies']); - - if (!empty($attachments[$row['post_id']])) - { - $update_count = array(); - parse_attachments($forum_id, $message, $attachments[$row['post_id']], $update_count); - } - - $post_subject = censor_text($post_subject); - - $post_anchor = ($mode == 'post_review') ? 'ppr' . $row['post_id'] : 'pr' . $row['post_id']; - $u_show_post = append_sid('viewtopic', "f=$forum_id&t=$topic_id&p={$row['post_id']}&view=show#p{$row['post_id']}"); - - phpbb::$template->assign_block_vars($mode . '_row', array( - 'POST_AUTHOR_FULL' => get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), - 'POST_AUTHOR_COLOUR' => get_username_string('colour', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), - 'POST_AUTHOR' => get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), - 'U_POST_AUTHOR' => get_username_string('profile', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), - - 'S_HAS_ATTACHMENTS' => (!empty($attachments[$row['post_id']])) ? true : false, - 'S_FRIEND' => ($row['friend']) ? true : false, - 'S_IGNORE_POST' => ($row['foe']) ? true : false, - 'L_IGNORE_POST' => ($row['foe']) ? phpbb::$user->lang('POST_BY_FOE', get_username_string('full', $poster_id, $row['username'], $row['user_colour'], $row['post_username']), "<a href=\"{$u_show_post}\" onclick=\"dE('{$post_anchor}', 1); return false;\">", '</a>') : '', - - 'POST_SUBJECT' => $post_subject, - 'MINI_POST_IMG' => phpbb::$user->img('icon_post_target', 'POST'), - 'POST_DATE' => phpbb::$user->format_date($row['post_time']), - 'MESSAGE' => $message, - 'DECODED_MESSAGE' => $decoded_message, - 'POST_ID' => $row['post_id'], - 'U_MINI_POST' => append_sid('viewtopic', 'p=' . $row['post_id']) . '#p' . $row['post_id'], - 'U_MCP_DETAILS' => (phpbb::$acl->acl_get('m_info', $forum_id)) ? append_sid('mcp', 'i=main&mode=post_details&f=' . $forum_id . '&p=' . $row['post_id'], true, phpbb::$user->session_id) : '', - 'POSTER_QUOTE' => ($show_quote_button && phpbb::$acl->acl_get('f_reply', $forum_id)) ? addslashes(get_username_string('username', $poster_id, $row['username'], $row['user_colour'], $row['post_username'])) : '', - )); - - // Display not already displayed Attachments for this post, we already parsed them. ;) - if (!empty($attachments[$row['post_id']])) - { - foreach ($attachments[$row['post_id']] as $attachment) - { - phpbb::$template->assign_block_vars($mode . '_row.attachment', array( - 'DISPLAY_ATTACHMENT' => $attachment, - )); - } - } - - unset($rowset[$i]); - } - - if ($mode == 'topic_review') - { - phpbb::$template->assign_var('QUOTE_IMG', phpbb::$user->img('icon_post_quote', 'REPLY_WITH_QUOTE')); - } - - return true; -} - -/** -* User Notification -*/ -function user_notification($mode, $subject, $topic_title, $forum_name, $forum_id, $topic_id, $post_id) -{ - $topic_notification = ($mode == 'reply' || $mode == 'quote') ? true : false; - $forum_notification = ($mode == 'post') ? true : false; - - if (!$topic_notification && !$forum_notification) - { - trigger_error('NO_MODE'); - } - - if (($topic_notification && !phpbb::$config['allow_topic_notify']) || ($forum_notification && !phpbb::$config['allow_forum_notify'])) - { - return; - } - - $topic_title = ($topic_notification) ? $topic_title : $subject; - $topic_title = censor_text($topic_title); - - // Get banned User ID's - $sql = 'SELECT ban_userid - FROM ' . BANLIST_TABLE . ' - WHERE ban_userid <> 0 - AND ban_exclude <> 1'; - $result = phpbb::$db->sql_query($sql); - - $sql_ignore_users = ANONYMOUS . ', ' . phpbb::$user->data['user_id']; - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $sql_ignore_users .= ', ' . (int) $row['ban_userid']; - } - phpbb::$db->sql_freeresult($result); - - $notify_rows = array(); - - // -- get forum_userids || topic_userids - $sql = 'SELECT u.user_id, u.username, u.user_email, u.user_lang, u.user_notify_type, u.user_jabber - FROM ' . (($topic_notification) ? TOPICS_WATCH_TABLE : FORUMS_WATCH_TABLE) . ' w, ' . USERS_TABLE . ' u - WHERE w.' . (($topic_notification) ? 'topic_id' : 'forum_id') . ' = ' . (($topic_notification) ? $topic_id : $forum_id) . " - AND w.user_id NOT IN ($sql_ignore_users) - AND w.notify_status = 0 - AND u.user_type IN (" . phpbb::USER_NORMAL . ', ' . phpbb::USER_FOUNDER . ') - AND u.user_id = w.user_id'; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $notify_rows[$row['user_id']] = array( - 'user_id' => $row['user_id'], - 'username' => $row['username'], - 'user_email' => $row['user_email'], - 'user_jabber' => $row['user_jabber'], - 'user_lang' => $row['user_lang'], - 'notify_type' => ($topic_notification) ? 'topic' : 'forum', - 'template' => ($topic_notification) ? 'topic_notify' : 'newtopic_notify', - 'method' => $row['user_notify_type'], - 'allowed' => false - ); - } - phpbb::$db->sql_freeresult($result); - - // forum notification is sent to those not already receiving topic notifications - if ($topic_notification) - { - if (sizeof($notify_rows)) - { - $sql_ignore_users .= ', ' . implode(', ', array_keys($notify_rows)); - } - - $sql = 'SELECT u.user_id, u.username, u.user_email, u.user_lang, u.user_notify_type, u.user_jabber - FROM ' . FORUMS_WATCH_TABLE . ' fw, ' . USERS_TABLE . " u - WHERE fw.forum_id = $forum_id - AND fw.user_id NOT IN ($sql_ignore_users) - AND fw.notify_status = 0 - AND u.user_type IN (" . phpbb::USER_NORMAL . ', ' . phpbb::USER_FOUNDER . ') - AND u.user_id = fw.user_id'; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $notify_rows[$row['user_id']] = array( - 'user_id' => $row['user_id'], - 'username' => $row['username'], - 'user_email' => $row['user_email'], - 'user_jabber' => $row['user_jabber'], - 'user_lang' => $row['user_lang'], - 'notify_type' => 'forum', - 'template' => 'forum_notify', - 'method' => $row['user_notify_type'], - 'allowed' => false - ); - } - phpbb::$db->sql_freeresult($result); - } - - if (!sizeof($notify_rows)) - { - return; - } - - // Make sure users are allowed to read the forum - foreach (phpbb::$acl->acl_get_list(array_keys($notify_rows), 'f_read', $forum_id) as $forum_id => $forum_ary) - { - foreach ($forum_ary as $auth_option => $user_ary) - { - foreach ($user_ary as $user_id) - { - $notify_rows[$user_id]['allowed'] = true; - } - } - } - - - // Now, we have to do a little step before really sending, we need to distinguish our users a little bit. ;) - $msg_users = $delete_ids = $update_notification = array(); - foreach ($notify_rows as $user_id => $row) - { - if (!$row['allowed'] || !trim($row['user_email'])) - { - $delete_ids[$row['notify_type']][] = $row['user_id']; - } - else - { - $msg_users[] = $row; - $update_notification[$row['notify_type']][] = $row['user_id']; - } - } - unset($notify_rows); - - // Now, we are able to really send out notifications - if (sizeof($msg_users)) - { - include_once(PHPBB_ROOT_PATH . 'includes/functions_messenger.' . PHP_EXT); - $messenger = new messenger(); - - $msg_list_ary = array(); - foreach ($msg_users as $row) - { - $pos = (!isset($msg_list_ary[$row['template']])) ? 0 : sizeof($msg_list_ary[$row['template']]); - - $msg_list_ary[$row['template']][$pos]['method'] = $row['method']; - $msg_list_ary[$row['template']][$pos]['email'] = $row['user_email']; - $msg_list_ary[$row['template']][$pos]['jabber'] = $row['user_jabber']; - $msg_list_ary[$row['template']][$pos]['name'] = $row['username']; - $msg_list_ary[$row['template']][$pos]['lang'] = $row['user_lang']; - $msg_list_ary[$row['template']][$pos]['user_id']= $row['user_id']; - } - unset($msg_users); - - foreach ($msg_list_ary as $email_template => $email_list) - { - foreach ($email_list as $addr) - { - $messenger->template($email_template, $addr['lang']); - - $messenger->to($addr['email'], $addr['name']); - $messenger->im($addr['jabber'], $addr['name']); - - $messenger->assign_vars(array( - 'USERNAME' => htmlspecialchars_decode($addr['name']), - 'TOPIC_TITLE' => htmlspecialchars_decode($topic_title), - 'FORUM_NAME' => htmlspecialchars_decode($forum_name), - - 'U_FORUM' => generate_board_url() . '/viewforum.' . PHP_EXT . "?f=$forum_id", - 'U_TOPIC' => generate_board_url() . '/viewtopic.' . PHP_EXT . "?f=$forum_id&t=$topic_id", - 'U_NEWEST_POST' => generate_board_url() . '/viewtopic.' . PHP_EXT . "?f=$forum_id&t=$topic_id&p=$post_id&e=$post_id", - 'U_STOP_WATCHING_TOPIC' => generate_board_url() . '/viewtopic.' . PHP_EXT . "?uid={$addr['user_id']}&f=$forum_id&t=$topic_id&unwatch=topic", - 'U_STOP_WATCHING_FORUM' => generate_board_url() . '/viewforum.' . PHP_EXT . "?uid={$addr['user_id']}&f=$forum_id&unwatch=forum", - )); - - $messenger->send($addr['method']); - } - } - unset($msg_list_ary); - - $messenger->save_queue(); - } - - // Handle the DB updates - phpbb::$db->sql_transaction('begin'); - - if (!empty($update_notification['topic'])) - { - $sql = 'UPDATE ' . TOPICS_WATCH_TABLE . " - SET notify_status = 1 - WHERE topic_id = $topic_id - AND " . phpbb::$db->sql_in_set('user_id', $update_notification['topic']); - phpbb::$db->sql_query($sql); - } - - if (!empty($update_notification['forum'])) - { - $sql = 'UPDATE ' . FORUMS_WATCH_TABLE . " - SET notify_status = 1 - WHERE forum_id = $forum_id - AND " . phpbb::$db->sql_in_set('user_id', $update_notification['forum']); - phpbb::$db->sql_query($sql); - } - - // Now delete the user_ids not authorised to receive notifications on this topic/forum - if (!empty($delete_ids['topic'])) - { - $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . " - WHERE topic_id = $topic_id - AND " . phpbb::$db->sql_in_set('user_id', $delete_ids['topic']); - phpbb::$db->sql_query($sql); - } - - if (!empty($delete_ids['forum'])) - { - $sql = 'DELETE FROM ' . FORUMS_WATCH_TABLE . " - WHERE forum_id = $forum_id - AND " . phpbb::$db->sql_in_set('user_id', $delete_ids['forum']); - phpbb::$db->sql_query($sql); - } - - phpbb::$db->sql_transaction('commit'); -} - -// -// Post handling functions -// - -/** -* Delete Post -*/ -function delete_post($forum_id, $topic_id, $post_id, &$data) -{ - // Specify our post mode - $post_mode = 'delete'; - if (($data['topic_first_post_id'] === $data['topic_last_post_id']) && $data['topic_replies_real'] == 0) - { - $post_mode = 'delete_topic'; - } - else if ($data['topic_first_post_id'] == $post_id) - { - $post_mode = 'delete_first_post'; - } - else if ($data['topic_last_post_id'] == $post_id) - { - $post_mode = 'delete_last_post'; - } - $sql_data = array(); - $next_post_id = false; - - include_once(PHPBB_ROOT_PATH . 'includes/functions_admin.' . PHP_EXT); - - phpbb::$db->sql_transaction('begin'); - - // we must make sure to update forums that contain the shadow'd topic - if ($post_mode == 'delete_topic') - { - $shadow_forum_ids = array(); - - $sql = 'SELECT forum_id - FROM ' . TOPICS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('topic_moved_id', $topic_id); - $result = phpbb::$db->sql_query($sql); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if (!isset($shadow_forum_ids[(int) $row['forum_id']])) - { - $shadow_forum_ids[(int) $row['forum_id']] = 1; - } - else - { - $shadow_forum_ids[(int) $row['forum_id']]++; - } - } - phpbb::$db->sql_freeresult($result); - } - - if (!delete_posts('post_id', array($post_id), false, false)) - { - // Try to delete topic, we may had an previous error causing inconsistency - if ($post_mode == 'delete_topic') - { - delete_topics('topic_id', array($topic_id), false); - } - trigger_error('ALREADY_DELETED'); - } - - phpbb::$db->sql_transaction('commit'); - - // Collect the necessary information for updating the tables - $sql_data[FORUMS_TABLE] = ''; - switch ($post_mode) - { - case 'delete_topic': - - foreach ($shadow_forum_ids as $updated_forum => $topic_count) - { - // counting is fun! we only have to do sizeof($forum_ids) number of queries, - // even if the topic is moved back to where its shadow lives (we count how many times it is in a forum) - phpbb::$db->sql_query('UPDATE ' . FORUMS_TABLE . ' SET forum_topics_real = forum_topics_real - ' . $topic_count . ', forum_topics = forum_topics - ' . $topic_count . ' WHERE forum_id = ' . $updated_forum); - update_post_information('forum', $updated_forum); - } - - delete_topics('topic_id', array($topic_id), false); - - if ($data['topic_type'] != POST_GLOBAL) - { - $sql_data[FORUMS_TABLE] .= 'forum_topics_real = forum_topics_real - 1'; - $sql_data[FORUMS_TABLE] .= ($data['topic_approved']) ? ', forum_posts = forum_posts - 1, forum_topics = forum_topics - 1' : ''; - } - - $update_sql = update_post_information('forum', $forum_id, true); - if (sizeof($update_sql)) - { - $sql_data[FORUMS_TABLE] .= ($sql_data[FORUMS_TABLE]) ? ', ' : ''; - $sql_data[FORUMS_TABLE] .= implode(', ', $update_sql[$forum_id]); - } - break; - - case 'delete_first_post': - $sql = 'SELECT p.post_id, p.poster_id, p.post_username, u.username, u.user_colour - FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . " u - WHERE p.topic_id = $topic_id - AND p.poster_id = u.user_id - ORDER BY p.post_time ASC"; - $result = phpbb::$db->sql_query_limit($sql, 1); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ($data['topic_type'] != POST_GLOBAL) - { - $sql_data[FORUMS_TABLE] = ($data['post_approved']) ? 'forum_posts = forum_posts - 1' : ''; - } - - $sql_data[TOPICS_TABLE] = 'topic_poster = ' . intval($row['poster_id']) . ', topic_first_post_id = ' . intval($row['post_id']) . ", topic_first_poster_colour = '" . phpbb::$db->sql_escape($row['user_colour']) . "', topic_first_poster_name = '" . (($row['poster_id'] == ANONYMOUS) ? phpbb::$db->sql_escape($row['post_username']) : phpbb::$db->sql_escape($row['username'])) . "'"; - - // Decrementing topic_replies here is fine because this case only happens if there is more than one post within the topic - basically removing one "reply" - $sql_data[TOPICS_TABLE] .= ', topic_replies_real = topic_replies_real - 1' . (($data['post_approved']) ? ', topic_replies = topic_replies - 1' : ''); - - $next_post_id = (int) $row['post_id']; - break; - - case 'delete_last_post': - if ($data['topic_type'] != POST_GLOBAL) - { - $sql_data[FORUMS_TABLE] = ($data['post_approved']) ? 'forum_posts = forum_posts - 1' : ''; - } - - $update_sql = update_post_information('forum', $forum_id, true); - if (sizeof($update_sql)) - { - $sql_data[FORUMS_TABLE] .= ($sql_data[FORUMS_TABLE]) ? ', ' : ''; - $sql_data[FORUMS_TABLE] .= implode(', ', $update_sql[$forum_id]); - } - - $sql_data[TOPICS_TABLE] = 'topic_bumped = 0, topic_bumper = 0, topic_replies_real = topic_replies_real - 1' . (($data['post_approved']) ? ', topic_replies = topic_replies - 1' : ''); - - $update_sql = update_post_information('topic', $topic_id, true); - if (sizeof($update_sql)) - { - $sql_data[TOPICS_TABLE] .= ', ' . implode(', ', $update_sql[$topic_id]); - $next_post_id = (int) str_replace('topic_last_post_id = ', '', $update_sql[$topic_id][0]); - } - else - { - $sql = 'SELECT MAX(post_id) as last_post_id - FROM ' . POSTS_TABLE . " - WHERE topic_id = $topic_id " . - ((!phpbb::$acl->acl_get('m_approve', $forum_id)) ? 'AND post_approved = 1' : ''); - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - $next_post_id = (int) $row['last_post_id']; - } - break; - - case 'delete': - $sql = 'SELECT post_id - FROM ' . POSTS_TABLE . " - WHERE topic_id = $topic_id " . - ((!phpbb::$acl->acl_get('m_approve', $forum_id)) ? 'AND post_approved = 1' : '') . ' - AND post_time > ' . $data['post_time'] . ' - ORDER BY post_time ASC'; - $result = phpbb::$db->sql_query_limit($sql, 1); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ($data['topic_type'] != POST_GLOBAL) - { - $sql_data[FORUMS_TABLE] = ($data['post_approved']) ? 'forum_posts = forum_posts - 1' : ''; - } - - $sql_data[TOPICS_TABLE] = 'topic_replies_real = topic_replies_real - 1' . (($data['post_approved']) ? ', topic_replies = topic_replies - 1' : ''); - $next_post_id = (int) $row['post_id']; - break; - } - -// $sql_data[USERS_TABLE] = ($data['post_postcount']) ? 'user_posts = user_posts - 1' : ''; - - phpbb::$db->sql_transaction('begin'); - - $where_sql = array( - FORUMS_TABLE => "forum_id = $forum_id", - TOPICS_TABLE => "topic_id = $topic_id", - USERS_TABLE => 'user_id = ' . $data['poster_id'] - ); - - foreach ($sql_data as $table => $update_sql) - { - if ($update_sql) - { - phpbb::$db->sql_query("UPDATE $table SET $update_sql WHERE " . $where_sql[$table]); - } - } - - // Adjust posted info for this user by looking for a post by him/her within this topic... - if ($post_mode != 'delete_topic' && phpbb::$config['load_db_track'] && $data['poster_id'] != ANONYMOUS) - { - $sql = 'SELECT poster_id - FROM ' . POSTS_TABLE . ' - WHERE topic_id = ' . $topic_id . ' - AND poster_id = ' . $data['poster_id']; - $result = phpbb::$db->sql_query_limit($sql, 1); - $poster_id = (int) phpbb::$db->sql_fetchfield('poster_id'); - phpbb::$db->sql_freeresult($result); - - // The user is not having any more posts within this topic - if (!$poster_id) - { - $sql = 'DELETE FROM ' . TOPICS_POSTED_TABLE . ' - WHERE topic_id = ' . $topic_id . ' - AND user_id = ' . $data['poster_id']; - phpbb::$db->sql_query($sql); - } - } - - phpbb::$db->sql_transaction('commit'); - - if ($data['post_reported'] && ($post_mode != 'delete_topic')) - { - sync('topic_reported', 'topic_id', array($topic_id)); - } - - return $next_post_id; -} - -/** -* Submit Post -*/ -function submit_post($mode, $subject, $username, $topic_type, &$poll, &$data, $update_message = true) -{ - // We do not handle erasing posts here - if ($mode == 'delete') - { - return false; - } - - $current_time = time(); - - if ($mode == 'post') - { - $post_mode = 'post'; - $update_message = true; - } - else if ($mode != 'edit') - { - $post_mode = 'reply'; - $update_message = true; - } - else if ($mode == 'edit') - { - $post_mode = ($data['topic_replies_real'] == 0) ? 'edit_topic' : (($data['topic_first_post_id'] == $data['post_id']) ? 'edit_first_post' : (($data['topic_last_post_id'] == $data['post_id']) ? 'edit_last_post' : 'edit')); - } - - // First of all make sure the subject and topic title are having the correct length. - // To achieve this without cutting off between special chars we convert to an array and then count the elements. - $subject = truncate_string($subject); - $data['topic_title'] = truncate_string($data['topic_title']); - - // Collect some basic information about which tables and which rows to update/insert - $sql_data = $topic_row = array(); - $poster_id = ($mode == 'edit') ? $data['poster_id'] : (int) phpbb::$user->data['user_id']; - - // Retrieve some additional information if not present - if ($mode == 'edit' && (!isset($data['post_approved']) || !isset($data['topic_approved']) || $data['post_approved'] === false || $data['topic_approved'] === false)) - { - $sql = 'SELECT p.post_approved, t.topic_type, t.topic_replies, t.topic_replies_real, t.topic_approved - FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . ' p - WHERE t.topic_id = p.topic_id - AND p.post_id = ' . $data['post_id']; - $result = phpbb::$db->sql_query($sql); - $topic_row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - $data['topic_approved'] = $topic_row['topic_approved']; - $data['post_approved'] = $topic_row['post_approved']; - } - - // This variable indicates if the user is able to post or put into the queue - it is used later for all code decisions regarding approval - $post_approval = 1; - - // Check the permissions for post approval, as well as the queue trigger where users are put on approval with a post count lower than specified. Moderators are not affected. - if (((phpbb::$config['enable_queue_trigger'] && phpbb::$user->data['user_posts'] < phpbb::$config['queue_trigger_posts']) || !phpbb::$acl->acl_get('f_noapprove', $data['forum_id'])) && !phpbb::$acl->acl_get('m_approve', $data['forum_id'])) - { - $post_approval = 0; - } - - // Start the transaction here - phpbb::$db->sql_transaction('begin'); - - // Collect Information - switch ($post_mode) - { - case 'post': - case 'reply': - $sql_data[POSTS_TABLE]['sql'] = array( - 'forum_id' => ($topic_type == POST_GLOBAL) ? 0 : $data['forum_id'], - 'poster_id' => (int) phpbb::$user->data['user_id'], - 'icon_id' => $data['icon_id'], - 'poster_ip' => phpbb::$user->ip, - 'post_time' => $current_time, - 'post_approved' => $post_approval, - 'enable_bbcode' => $data['enable_bbcode'], - 'enable_smilies' => $data['enable_smilies'], - 'enable_magic_url' => $data['enable_urls'], - 'enable_sig' => $data['enable_sig'], - 'post_username' => (!phpbb::$user->is_registered) ? $username : '', - 'post_subject' => $subject, - 'post_text' => $data['message'], - 'post_checksum' => $data['message_md5'], - 'post_attachment' => (!empty($data['attachment_data'])) ? 1 : 0, - 'bbcode_bitfield' => $data['bbcode_bitfield'], - 'bbcode_uid' => $data['bbcode_uid'], - 'post_postcount' => (phpbb::$acl->acl_get('f_postcount', $data['forum_id'])) ? 1 : 0, - 'post_edit_locked' => $data['post_edit_locked'] - ); - break; - - case 'edit_first_post': - case 'edit': - - case 'edit_last_post': - case 'edit_topic': - - // If edit reason is given always display edit info - - // If editing last post then display no edit info - // If m_edit permission then display no edit info - // If normal edit display edit info - - // Display edit info if edit reason given or user is editing his post, which is not the last within the topic. - if ($data['post_edit_reason'] || (!phpbb::$acl->acl_get('m_edit', $data['forum_id']) && ($post_mode == 'edit' || $post_mode == 'edit_first_post'))) - { - $data['post_edit_reason'] = truncate_string($data['post_edit_reason'], 255, 255, false); - - $sql_data[POSTS_TABLE]['sql'] = array( - 'post_edit_time' => $current_time, - 'post_edit_reason' => $data['post_edit_reason'], - 'post_edit_user' => (int) $data['post_edit_user'], - ); - - $sql_data[POSTS_TABLE]['stat'][] = 'post_edit_count = post_edit_count + 1'; - } - else if (!$data['post_edit_reason'] && $mode == 'edit' && phpbb::$acl->acl_get('m_edit', $data['forum_id'])) - { - $sql_data[POSTS_TABLE]['sql'] = array( - 'post_edit_reason' => '', - ); - } - - // If the person editing this post is different to the one having posted then we will add a log entry stating the edit - // Could be simplified by only adding to the log if the edit is not tracked - but this may confuse admins/mods - if (phpbb::$user->data['user_id'] != $poster_id) - { - $log_subject = ($subject) ? $subject : $data['topic_title']; - add_log('mod', $data['forum_id'], $data['topic_id'], 'LOG_POST_EDITED', $log_subject, (!empty($username)) ? $username : phpbb::$user->lang['GUEST']); - } - - if (!isset($sql_data[POSTS_TABLE]['sql'])) - { - $sql_data[POSTS_TABLE]['sql'] = array(); - } - - $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array( - 'forum_id' => ($topic_type == POST_GLOBAL) ? 0 : $data['forum_id'], - 'poster_id' => $data['poster_id'], - 'icon_id' => $data['icon_id'], - 'post_approved' => (!$post_approval) ? 0 : $data['post_approved'], - 'enable_bbcode' => $data['enable_bbcode'], - 'enable_smilies' => $data['enable_smilies'], - 'enable_magic_url' => $data['enable_urls'], - 'enable_sig' => $data['enable_sig'], - 'post_username' => ($username && $data['poster_id'] == ANONYMOUS) ? $username : '', - 'post_subject' => $subject, - 'post_checksum' => $data['message_md5'], - 'post_attachment' => (!empty($data['attachment_data'])) ? 1 : 0, - 'bbcode_bitfield' => $data['bbcode_bitfield'], - 'bbcode_uid' => $data['bbcode_uid'], - 'post_edit_locked' => $data['post_edit_locked']) - ); - - if ($update_message) - { - $sql_data[POSTS_TABLE]['sql']['post_text'] = $data['message']; - } - - break; - } - - $post_approved = $sql_data[POSTS_TABLE]['sql']['post_approved']; - $topic_row = array(); - - // And the topic ladies and gentlemen - switch ($post_mode) - { - case 'post': - $sql_data[TOPICS_TABLE]['sql'] = array( - 'topic_poster' => (int) phpbb::$user->data['user_id'], - 'topic_time' => $current_time, - 'topic_last_view_time' => $current_time, - 'forum_id' => ($topic_type == POST_GLOBAL) ? 0 : $data['forum_id'], - 'icon_id' => $data['icon_id'], - 'topic_approved' => $post_approval, - 'topic_title' => $subject, - 'topic_first_poster_name' => (!phpbb::$user->is_registered && $username) ? $username : ((!phpbb::$user->is_guest) ? phpbb::$user->data['username'] : ''), - 'topic_first_poster_colour' => phpbb::$user->data['user_colour'], - 'topic_type' => $topic_type, - 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0, - 'topic_attachment' => (!empty($data['attachment_data'])) ? 1 : 0, - ); - - if (isset($poll['poll_options']) && !empty($poll['poll_options'])) - { - $poll_start = ($poll['poll_start']) ? $poll['poll_start'] : $current_time; - $poll_length = $poll['poll_length'] * 86400; - if ($poll_length < 0) - { - $poll_start = $poll_start + $poll_length; - if ($poll_start < 0) - { - $poll_start = 0; - } - $poll_length = 1; - } - - $sql_data[TOPICS_TABLE]['sql'] = array_merge($sql_data[TOPICS_TABLE]['sql'], array( - 'poll_title' => $poll['poll_title'], - 'poll_start' => $poll_start, - 'poll_max_options' => $poll['poll_max_options'], - 'poll_length' => $poll_length, - 'poll_vote_change' => $poll['poll_vote_change']) - ); - } - - $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . ((phpbb::$acl->acl_get('f_postcount', $data['forum_id']) && $post_approval) ? ', user_posts = user_posts + 1' : ''); - - if ($topic_type != POST_GLOBAL) - { - if ($post_approval) - { - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts + 1'; - } - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_real = forum_topics_real + 1' . (($post_approval) ? ', forum_topics = forum_topics + 1' : ''); - } - break; - - case 'reply': - $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_view_time = ' . $current_time . ', - topic_replies_real = topic_replies_real + 1, - topic_bumped = 0, - topic_bumper = 0' . - (($post_approval) ? ', topic_replies = topic_replies + 1' : '') . - ((!empty($data['attachment_data']) || (isset($data['topic_attachment']) && $data['topic_attachment'])) ? ', topic_attachment = 1' : ''); - - $sql_data[USERS_TABLE]['stat'][] = "user_lastpost_time = $current_time" . ((phpbb::$acl->acl_get('f_postcount', $data['forum_id']) && $post_approval) ? ', user_posts = user_posts + 1' : ''); - - if ($post_approval && $topic_type != POST_GLOBAL) - { - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts + 1'; - } - break; - - case 'edit_topic': - case 'edit_first_post': - if (isset($poll['poll_options']) && !empty($poll['poll_options'])) - { - $poll_start = ($poll['poll_start']) ? $poll['poll_start'] : $current_time; - $poll_length = $poll['poll_length'] * 86400; - if ($poll_length < 0) - { - $poll_start = $poll_start + $poll_length; - if ($poll_start < 0) - { - $poll_start = 0; - } - $poll_length = 1; - } - } - - $sql_data[TOPICS_TABLE]['sql'] = array( - 'forum_id' => ($topic_type == POST_GLOBAL) ? 0 : $data['forum_id'], - 'icon_id' => $data['icon_id'], - 'topic_approved' => (!$post_approval) ? 0 : $data['topic_approved'], - 'topic_title' => $subject, - 'topic_first_poster_name' => $username, - 'topic_type' => $topic_type, - 'topic_time_limit' => ($topic_type == POST_STICKY || $topic_type == POST_ANNOUNCE) ? ($data['topic_time_limit'] * 86400) : 0, - 'poll_title' => (isset($poll['poll_options'])) ? $poll['poll_title'] : '', - 'poll_start' => (isset($poll['poll_options'])) ? $poll_start : 0, - 'poll_max_options' => (isset($poll['poll_options'])) ? $poll['poll_max_options'] : 1, - 'poll_length' => (isset($poll['poll_options'])) ? $poll_length : 0, - 'poll_vote_change' => (isset($poll['poll_vote_change'])) ? $poll['poll_vote_change'] : 0, - 'topic_last_view_time' => $current_time, - - 'topic_attachment' => (!empty($data['attachment_data'])) ? 1 : (isset($data['topic_attachment']) ? $data['topic_attachment'] : 0), - ); - - // Correctly set back the topic replies and forum posts... only if the topic was approved before and now gets disapproved - if (!$post_approval && $data['topic_approved']) - { - // Do we need to grab some topic informations? - if (!sizeof($topic_row)) - { - $sql = 'SELECT topic_type, topic_replies, topic_replies_real, topic_approved - FROM ' . TOPICS_TABLE . ' - WHERE topic_id = ' . $data['topic_id']; - $result = phpbb::$db->sql_query($sql); - $topic_row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - } - - // If this is the only post remaining we do not need to decrement topic_replies. - // Also do not decrement if first post - then the topic_replies will not be adjusted if approving the topic again. - - // If this is an edited topic or the first post the topic gets completely disapproved later on... - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics = forum_topics - 1'; - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts - ' . ($topic_row['topic_replies'] + 1); - - set_config_count('num_topics', -1, true); - set_config_count('num_posts', ($topic_row['topic_replies'] + 1) * (-1), true); - - // Only decrement this post, since this is the one non-approved now - if (phpbb::$acl->acl_get('f_postcount', $data['forum_id'])) - { - $sql_data[USERS_TABLE]['stat'][] = 'user_posts = user_posts - 1'; - } - } - - break; - - case 'edit': - case 'edit_last_post': - - // Correctly set back the topic replies and forum posts... but only if the post was approved before. - if (!$post_approval && $data['post_approved']) - { - $sql_data[TOPICS_TABLE]['stat'][] = 'topic_replies = topic_replies - 1, topic_last_view_time = ' . $current_time; - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts - 1'; - - set_config_count('num_posts', -1, true); - - if (phpbb::$acl->acl_get('f_postcount', $data['forum_id'])) - { - $sql_data[USERS_TABLE]['stat'][] = 'user_posts = user_posts - 1'; - } - } - - break; - } - - // Submit new topic - if ($post_mode == 'post') - { - $sql = 'INSERT INTO ' . TOPICS_TABLE . ' ' . - phpbb::$db->sql_build_array('INSERT', $sql_data[TOPICS_TABLE]['sql']); - phpbb::$db->sql_query($sql); - - $data['topic_id'] = phpbb::$db->sql_nextid(); - - $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array( - 'topic_id' => $data['topic_id']) - ); - unset($sql_data[TOPICS_TABLE]['sql']); - } - - // Submit new post - if ($post_mode == 'post' || $post_mode == 'reply') - { - if ($post_mode == 'reply') - { - $sql_data[POSTS_TABLE]['sql'] = array_merge($sql_data[POSTS_TABLE]['sql'], array( - 'topic_id' => $data['topic_id']) - ); - } - - $sql = 'INSERT INTO ' . POSTS_TABLE . ' ' . phpbb::$db->sql_build_array('INSERT', $sql_data[POSTS_TABLE]['sql']); - phpbb::$db->sql_query($sql); - $data['post_id'] = phpbb::$db->sql_nextid(); - - if ($post_mode == 'post') - { - $sql_data[TOPICS_TABLE]['sql'] = array( - 'topic_first_post_id' => $data['post_id'], - 'topic_last_post_id' => $data['post_id'], - 'topic_last_post_time' => $current_time, - 'topic_last_poster_id' => (int) phpbb::$user->data['user_id'], - 'topic_last_poster_name' => (!phpbb::$user->is_registered && $username) ? $username : ((!phpbb::$user->is_guest) ? phpbb::$user->data['username'] : ''), - 'topic_last_poster_colour' => phpbb::$user->data['user_colour'], - 'topic_last_post_subject' => (string) $subject, - ); - } - - unset($sql_data[POSTS_TABLE]['sql']); - } - - $make_global = false; - - // Are we globalising or unglobalising? - if ($post_mode == 'edit_first_post' || $post_mode == 'edit_topic') - { - if (!sizeof($topic_row)) - { - $sql = 'SELECT topic_type, topic_replies, topic_replies_real, topic_approved, topic_last_post_id - FROM ' . TOPICS_TABLE . ' - WHERE topic_id = ' . $data['topic_id']; - $result = phpbb::$db->sql_query($sql); - $topic_row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - } - - // globalise/unglobalise? - if (($topic_row['topic_type'] != POST_GLOBAL && $topic_type == POST_GLOBAL) || ($topic_row['topic_type'] == POST_GLOBAL && $topic_type != POST_GLOBAL)) - { - if (!empty($sql_data[FORUMS_TABLE]['stat']) && implode('', $sql_data[FORUMS_TABLE]['stat'])) - { - phpbb::$db->sql_query('UPDATE ' . FORUMS_TABLE . ' SET ' . implode(', ', $sql_data[FORUMS_TABLE]['stat']) . ' WHERE forum_id = ' . $data['forum_id']); - } - - $make_global = true; - $sql_data[FORUMS_TABLE]['stat'] = array(); - } - - // globalise - if ($topic_row['topic_type'] != POST_GLOBAL && $topic_type == POST_GLOBAL) - { - // Decrement topic/post count - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts - ' . ($topic_row['topic_replies_real'] + 1); - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_real = forum_topics_real - 1' . (($topic_row['topic_approved']) ? ', forum_topics = forum_topics - 1' : ''); - - // Update forum_ids for all posts - $sql = 'UPDATE ' . POSTS_TABLE . ' - SET forum_id = 0 - WHERE topic_id = ' . $data['topic_id']; - phpbb::$db->sql_query($sql); - } - // unglobalise - else if ($topic_row['topic_type'] == POST_GLOBAL && $topic_type != POST_GLOBAL) - { - // Increment topic/post count - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_posts = forum_posts + ' . ($topic_row['topic_replies_real'] + 1); - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_topics_real = forum_topics_real + 1' . (($topic_row['topic_approved']) ? ', forum_topics = forum_topics + 1' : ''); - - // Update forum_ids for all posts - $sql = 'UPDATE ' . POSTS_TABLE . ' - SET forum_id = ' . $data['forum_id'] . ' - WHERE topic_id = ' . $data['topic_id']; - phpbb::$db->sql_query($sql); - } - } - - // Update the topics table - if (isset($sql_data[TOPICS_TABLE]['sql'])) - { - $sql = 'UPDATE ' . TOPICS_TABLE . ' - SET ' . phpbb::$db->sql_build_array('UPDATE', $sql_data[TOPICS_TABLE]['sql']) . ' - WHERE topic_id = ' . $data['topic_id']; - phpbb::$db->sql_query($sql); - } - - // Update the posts table - if (isset($sql_data[POSTS_TABLE]['sql'])) - { - $sql = 'UPDATE ' . POSTS_TABLE . ' - SET ' . phpbb::$db->sql_build_array('UPDATE', $sql_data[POSTS_TABLE]['sql']) . ' - WHERE post_id = ' . $data['post_id']; - phpbb::$db->sql_query($sql); - } - - // Update Poll Tables - if (isset($poll['poll_options']) && !empty($poll['poll_options'])) - { - $cur_poll_options = array(); - - if ($poll['poll_start'] && $mode == 'edit') - { - $sql = 'SELECT * - FROM ' . POLL_OPTIONS_TABLE . ' - WHERE topic_id = ' . $data['topic_id'] . ' - ORDER BY poll_option_id'; - $result = phpbb::$db->sql_query($sql); - - $cur_poll_options = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $cur_poll_options[] = $row; - } - phpbb::$db->sql_freeresult($result); - } - - $sql_insert_ary = array(); - - for ($i = 0, $size = sizeof($poll['poll_options']); $i < $size; $i++) - { - if (strlen(trim($poll['poll_options'][$i]))) - { - if (empty($cur_poll_options[$i])) - { - // If we add options we need to put them to the end to be able to preserve votes... - $sql_insert_ary[] = array( - 'poll_option_id' => (int) sizeof($cur_poll_options) + 1 + sizeof($sql_insert_ary), - 'topic_id' => (int) $data['topic_id'], - 'poll_option_text' => (string) $poll['poll_options'][$i] - ); - } - else if ($poll['poll_options'][$i] != $cur_poll_options[$i]) - { - $sql = 'UPDATE ' . POLL_OPTIONS_TABLE . " - SET poll_option_text = '" . phpbb::$db->sql_escape($poll['poll_options'][$i]) . "' - WHERE poll_option_id = " . $cur_poll_options[$i]['poll_option_id'] . ' - AND topic_id = ' . $data['topic_id']; - phpbb::$db->sql_query($sql); - } - } - } - - phpbb::$db->sql_multi_insert(POLL_OPTIONS_TABLE, $sql_insert_ary); - - if (sizeof($poll['poll_options']) < sizeof($cur_poll_options)) - { - $sql = 'DELETE FROM ' . POLL_OPTIONS_TABLE . ' - WHERE poll_option_id > ' . sizeof($poll['poll_options']) . ' - AND topic_id = ' . $data['topic_id']; - phpbb::$db->sql_query($sql); - } - - // If edited, we would need to reset votes (since options can be re-ordered above, you can't be sure if the change is for changing the text or adding an option - if ($mode == 'edit' && sizeof($poll['poll_options']) != sizeof($cur_poll_options)) - { - phpbb::$db->sql_query('DELETE FROM ' . POLL_VOTES_TABLE . ' WHERE topic_id = ' . $data['topic_id']); - phpbb::$db->sql_query('UPDATE ' . POLL_OPTIONS_TABLE . ' SET poll_option_total = 0 WHERE topic_id = ' . $data['topic_id']); - } - } - - // Submit Attachments - if (!empty($data['attachment_data']) && $data['post_id'] && in_array($mode, array('post', 'reply', 'quote', 'edit'))) - { - $space_taken = $files_added = 0; - $orphan_rows = array(); - - foreach ($data['attachment_data'] as $pos => $attach_row) - { - $orphan_rows[(int) $attach_row['attach_id']] = array(); - } - - if (sizeof($orphan_rows)) - { - $sql = 'SELECT attach_id, filesize, physical_filename - FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('attach_id', array_keys($orphan_rows)) . ' - AND is_orphan = 1 - AND poster_id = ' . phpbb::$user->data['user_id']; - $result = phpbb::$db->sql_query($sql); - - $orphan_rows = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $orphan_rows[$row['attach_id']] = $row; - } - phpbb::$db->sql_freeresult($result); - } - - foreach ($data['attachment_data'] as $pos => $attach_row) - { - if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']])) - { - continue; - } - - if (!$attach_row['is_orphan']) - { - // update entry in db if attachment already stored in db and filespace - $sql = 'UPDATE ' . ATTACHMENTS_TABLE . " - SET attach_comment = '" . phpbb::$db->sql_escape($attach_row['attach_comment']) . "' - WHERE attach_id = " . (int) $attach_row['attach_id'] . ' - AND is_orphan = 0'; - phpbb::$db->sql_query($sql); - } - else - { - // insert attachment into db - if (!@file_exists(PHPBB_ROOT_PATH . phpbb::$config['upload_path'] . '/' . basename($orphan_rows[$attach_row['attach_id']]['physical_filename']))) - { - continue; - } - - $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize']; - $files_added++; - - $attach_sql = array( - 'post_msg_id' => $data['post_id'], - 'topic_id' => $data['topic_id'], - 'is_orphan' => 0, - 'poster_id' => $poster_id, - 'attach_comment' => $attach_row['attach_comment'], - ); - - $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . phpbb::$db->sql_build_array('UPDATE', $attach_sql) . ' - WHERE attach_id = ' . $attach_row['attach_id'] . ' - AND is_orphan = 1 - AND poster_id = ' . phpbb::$user->data['user_id']; - phpbb::$db->sql_query($sql); - } - } - - if ($space_taken && $files_added) - { - set_config_count('upload_dir_size', $space_taken, true); - set_config_count('num_files', $files_added, true); - } - } - - // we need to update the last forum information - // only applicable if the topic is not global and it is approved - // we also check to make sure we are not dealing with globaling the latest topic (pretty rare but still needs to be checked) - if ($topic_type != POST_GLOBAL && !$make_global && ($post_approved != $data['post_approved'])) - { - // the last post makes us update the forum table. This can happen if... - // We make a new topic - // We reply to a topic - // We edit the last post in a topic and this post is the latest in the forum (maybe) - // We edit the only post in the topic - // We edit the first post in the topic and all the other posts are not approved - if (($post_mode == 'post' || $post_mode == 'reply') && $post_approved) - { - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . $data['post_id']; - $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . phpbb::$db->sql_escape($subject) . "'"; - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . $current_time; - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) phpbb::$user->data['user_id']; - $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . phpbb::$db->sql_escape((!phpbb::$user->is_registered && $username) ? $username : ((!phpbb::$user->is_guest) ? phpbb::$user->data['username'] : '')) . "'"; - $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . phpbb::$db->sql_escape(phpbb::$user->data['user_colour']) . "'"; - } - else if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || ($post_mode == 'edit_first_post' && !$data['topic_replies'])) - { - // this does not _necessarily_ mean that we must update the info again, - // it just means that we might have to - $sql = 'SELECT forum_last_post_id, forum_last_post_subject - FROM ' . FORUMS_TABLE . ' - WHERE forum_id = ' . (int) $data['forum_id']; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - // this post is the latest post in the forum, better update - if ($row['forum_last_post_id'] == $data['post_id']) - { - // If post approved and subject changed, or poster is anonymous, we need to update the forum_last* rows - if ($post_approved && ($row['forum_last_post_subject'] !== $subject || $data['poster_id'] == ANONYMOUS)) - { - // the post's subject changed - if ($row['forum_last_post_subject'] !== $subject) - { - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_subject = \'' . phpbb::$db->sql_escape($subject) . '\''; - } - - // Update the user name if poster is anonymous... just in case an admin changed it - if ($data['poster_id'] == ANONYMOUS) - { - $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . phpbb::$db->sql_escape($username) . "'"; - } - } - else if ($data['post_approved'] !== $post_approved) - { - // we need a fresh change of socks, everything has become invalidated - $sql = 'SELECT MAX(topic_last_post_id) as last_post_id - FROM ' . TOPICS_TABLE . ' - WHERE forum_id = ' . (int) $data['forum_id'] . ' - AND topic_approved = 1'; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - // any posts left in this forum? - if (!empty($row['last_post_id'])) - { - $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour - FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u - WHERE p.poster_id = u.user_id - AND p.post_id = ' . (int) $row['last_post_id']; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - // salvation, a post is found! jam it into the forums table - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . (int) $row['post_id']; - $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . phpbb::$db->sql_escape($row['post_subject']) . "'"; - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . (int) $row['post_time']; - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $row['poster_id']; - $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . phpbb::$db->sql_escape(($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']) . "'"; - $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . phpbb::$db->sql_escape($row['user_colour']) . "'"; - } - else - { - // just our luck, the last topic in the forum has just been turned unapproved... - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = 0'; - $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = ''"; - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = 0'; - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = 0'; - $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = ''"; - $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = ''"; - } - } - } - } - } - else if ($make_global) - { - // somebody decided to be a party pooper, we must recalculate the whole shebang (maybe) - $sql = 'SELECT forum_last_post_id - FROM ' . FORUMS_TABLE . ' - WHERE forum_id = ' . (int) $data['forum_id']; - $result = phpbb::$db->sql_query($sql); - $forum_row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - // we made a topic global, go get new data - if ($topic_row['topic_type'] != POST_GLOBAL && $topic_type == POST_GLOBAL && $forum_row['forum_last_post_id'] == $topic_row['topic_last_post_id']) - { - // we need a fresh change of socks, everything has become invalidated - $sql = 'SELECT MAX(topic_last_post_id) as last_post_id - FROM ' . TOPICS_TABLE . ' - WHERE forum_id = ' . (int) $data['forum_id'] . ' - AND topic_approved = 1'; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - // any posts left in this forum? - if (!empty($row['last_post_id'])) - { - $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour - FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u - WHERE p.poster_id = u.user_id - AND p.post_id = ' . (int) $row['last_post_id']; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - // salvation, a post is found! jam it into the forums table - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . (int) $row['post_id']; - $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . phpbb::$db->sql_escape($row['post_subject']) . "'"; - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . (int) $row['post_time']; - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $row['poster_id']; - $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . phpbb::$db->sql_escape(($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']) . "'"; - $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . phpbb::$db->sql_escape($row['user_colour']) . "'"; - } - else - { - // just our luck, the last topic in the forum has just been globalized... - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = 0'; - $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = ''"; - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = 0'; - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = 0'; - $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = ''"; - $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = ''"; - } - } - else if ($topic_row['topic_type'] == POST_GLOBAL && $topic_type != POST_GLOBAL && $forum_row['forum_last_post_id'] < $topic_row['topic_last_post_id']) - { - // this post has a higher id, it is newer - $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour - FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u - WHERE p.poster_id = u.user_id - AND p.post_id = ' . (int) $topic_row['topic_last_post_id']; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - // salvation, a post is found! jam it into the forums table - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_id = ' . (int) $row['post_id']; - $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_post_subject = '" . phpbb::$db->sql_escape($row['post_subject']) . "'"; - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_post_time = ' . (int) $row['post_time']; - $sql_data[FORUMS_TABLE]['stat'][] = 'forum_last_poster_id = ' . (int) $row['poster_id']; - $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_name = '" . phpbb::$db->sql_escape(($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']) . "'"; - $sql_data[FORUMS_TABLE]['stat'][] = "forum_last_poster_colour = '" . phpbb::$db->sql_escape($row['user_colour']) . "'"; - } - } - - // topic sync time! - // simply, we update if it is a reply or the last post is edited - if ($post_approved) - { - // reply requires the whole thing - if ($post_mode == 'reply') - { - $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_id = ' . (int) $data['post_id']; - $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_poster_id = ' . (int) phpbb::$user->data['user_id']; - $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . phpbb::$db->sql_escape((!phpbb::$user->is_registered && $username) ? $username : ((!phpbb::$user->is_guest) ? phpbb::$user->data['username'] : '')) . "'"; - $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_colour = '" . ((!phpbb::$user->is_guest) ? phpbb::$db->sql_escape(phpbb::$user->data['user_colour']) : '') . "'"; - $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . phpbb::$db->sql_escape($subject) . "'"; - $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_time = ' . (int) $current_time; - } - else if ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || ($post_mode == 'edit_first_post' && !$data['topic_replies'])) - { - // only the subject can be changed from edit - $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . phpbb::$db->sql_escape($subject) . "'"; - - // Maybe not only the subject, but also changing anonymous usernames. ;) - if ($data['poster_id'] == ANONYMOUS) - { - $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . phpbb::$db->sql_escape($username) . "'"; - } - } - } - else if (!$data['post_approved'] && ($post_mode == 'edit_last_post' || $post_mode == 'edit_topic' || ($post_mode == 'edit_first_post' && !$data['topic_replies']))) - { - // like having the rug pulled from under us - $sql = 'SELECT MAX(post_id) as last_post_id - FROM ' . POSTS_TABLE . ' - WHERE topic_id = ' . (int) $data['topic_id'] . ' - AND post_approved = 1'; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - // any posts left in this forum? - if (!empty($row['last_post_id'])) - { - $sql = 'SELECT p.post_id, p.post_subject, p.post_time, p.poster_id, p.post_username, u.user_id, u.username, u.user_colour - FROM ' . POSTS_TABLE . ' p, ' . USERS_TABLE . ' u - WHERE p.poster_id = u.user_id - AND p.post_id = ' . (int) $row['last_post_id']; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - // salvation, a post is found! jam it into the topics table - $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_id = ' . (int) $row['post_id']; - $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_post_subject = '" . phpbb::$db->sql_escape($row['post_subject']) . "'"; - $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_post_time = ' . (int) $row['post_time']; - $sql_data[TOPICS_TABLE]['stat'][] = 'topic_last_poster_id = ' . (int) $row['poster_id']; - $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_name = '" . phpbb::$db->sql_escape(($row['poster_id'] == ANONYMOUS) ? $row['post_username'] : $row['username']) . "'"; - $sql_data[TOPICS_TABLE]['stat'][] = "topic_last_poster_colour = '" . phpbb::$db->sql_escape($row['user_colour']) . "'"; - } - } - - // Update total post count, do not consider moderated posts/topics - if ($post_approval) - { - if ($post_mode == 'post') - { - set_config_count('num_topics', 1, true); - set_config_count('num_posts', 1, true); - } - - if ($post_mode == 'reply') - { - set_config_count('num_posts', 1, true); - } - } - - // Update forum stats - $where_sql = array(POSTS_TABLE => 'post_id = ' . $data['post_id'], TOPICS_TABLE => 'topic_id = ' . $data['topic_id'], FORUMS_TABLE => 'forum_id = ' . $data['forum_id'], USERS_TABLE => 'user_id = ' . $poster_id); - - foreach ($sql_data as $table => $update_ary) - { - if (isset($update_ary['stat']) && implode('', $update_ary['stat'])) - { - $sql = "UPDATE $table SET " . implode(', ', $update_ary['stat']) . ' WHERE ' . $where_sql[$table]; - phpbb::$db->sql_query($sql); - } - } - - // Delete topic shadows (if any exist). We do not need a shadow topic for an global announcement - if ($make_global) - { - $sql = 'DELETE FROM ' . TOPICS_TABLE . ' - WHERE topic_moved_id = ' . $data['topic_id']; - phpbb::$db->sql_query($sql); - } - - // Committing the transaction before updating search index - phpbb::$db->sql_transaction('commit'); - - // Delete draft if post was loaded... - $draft_id = request_var('draft_loaded', 0); - if ($draft_id) - { - $sql = 'DELETE FROM ' . DRAFTS_TABLE . " - WHERE draft_id = $draft_id - AND user_id = " . phpbb::$user->data['user_id']; - phpbb::$db->sql_query($sql); - } - - // Index message contents - if ($update_message && $data['enable_indexing']) - { - // Select the search method and do some additional checks to ensure it can actually be utilised - $search_type = basename(phpbb::$config['search_type']); - - if (!file_exists(PHPBB_ROOT_PATH . 'includes/search/' . $search_type . '.' . PHP_EXT)) - { - trigger_error('NO_SUCH_SEARCH_MODULE'); - } - - if (!class_exists($search_type)) - { - include(PHPBB_ROOT_PATH . "includes/search/$search_type." . PHP_EXT); - } - - $error = false; - $search = new $search_type($error); - - if ($error) - { - trigger_error($error); - } - - $search->index($mode, $data['post_id'], $data['message'], $subject, $poster_id, ($topic_type == POST_GLOBAL) ? 0 : $data['forum_id']); - } - - // Topic Notification, do not change if moderator is changing other users posts... - if (phpbb::$user->data['user_id'] == $poster_id) - { - if (!$data['notify_set'] && $data['notify']) - { - $sql = 'INSERT INTO ' . TOPICS_WATCH_TABLE . ' (user_id, topic_id) - VALUES (' . phpbb::$user->data['user_id'] . ', ' . $data['topic_id'] . ')'; - phpbb::$db->sql_query($sql); - } - else if ($data['notify_set'] && !$data['notify']) - { - $sql = 'DELETE FROM ' . TOPICS_WATCH_TABLE . ' - WHERE user_id = ' . phpbb::$user->data['user_id'] . ' - AND topic_id = ' . $data['topic_id']; - phpbb::$db->sql_query($sql); - } - } - - if ($mode == 'post' || $mode == 'reply' || $mode == 'quote') - { - // Mark this topic as posted to - markread('post', $data['forum_id'], $data['topic_id'], $data['post_time']); - } - - // Mark this topic as read - // We do not use post_time here, this is intended (post_time can have a date in the past if editing a message) - markread('topic', $data['forum_id'], $data['topic_id'], time()); - - // - if (phpbb::$config['load_db_lastread'] && phpbb::$user->is_registered) - { - $sql = 'SELECT mark_time - FROM ' . FORUMS_TRACK_TABLE . ' - WHERE user_id = ' . phpbb::$user->data['user_id'] . ' - AND forum_id = ' . $data['forum_id']; - $result = phpbb::$db->sql_query($sql); - $f_mark_time = (int) phpbb::$db->sql_fetchfield('mark_time'); - phpbb::$db->sql_freeresult($result); - } - else if (phpbb::$config['load_anon_lastread'] || phpbb::$user->is_registered) - { - $f_mark_time = false; - } - - if ((phpbb::$config['load_db_lastread'] && phpbb::$user->is_registered) || phpbb::$config['load_anon_lastread'] || phpbb::$user->is_registered) - { - // Update forum info - $sql = 'SELECT forum_last_post_time - FROM ' . FORUMS_TABLE . ' - WHERE forum_id = ' . $data['forum_id']; - $result = phpbb::$db->sql_query($sql); - $forum_last_post_time = (int) phpbb::$db->sql_fetchfield('forum_last_post_time'); - phpbb::$db->sql_freeresult($result); - - update_forum_tracking_info($data['forum_id'], $forum_last_post_time, $f_mark_time, false); - } - - // Send Notifications - if ($mode != 'edit' && $mode != 'delete' && $post_approval) - { - user_notification($mode, $subject, $data['topic_title'], $data['forum_name'], $data['forum_id'], $data['topic_id'], $data['post_id']); - } - - $params = $add_anchor = ''; - - if ($post_approval) - { - $params .= '&t=' . $data['topic_id']; - - if ($mode != 'post') - { - $params .= '&p=' . $data['post_id']; - $add_anchor = '#p' . $data['post_id']; - } - } - else if ($mode != 'post' && $post_mode != 'edit_first_post' && $post_mode != 'edit_topic') - { - $params .= '&t=' . $data['topic_id']; - } - - $url = (!$params) ? 'viewforum' : 'viewtopic'; - $url = append_sid($url, 'f=' . $data['forum_id'] . $params) . $add_anchor; - - return $url; -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/functions_privmsgs.php b/phpBB/includes/functions_privmsgs.php deleted file mode 100644 index 90060519db..0000000000 --- a/phpBB/includes/functions_privmsgs.php +++ /dev/null @@ -1,1832 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/* - Ability to simply add own rules by doing three things: - 1) Add an appropriate constant - 2) Add a new check array to the global_privmsgs_rules variable and the condition array (if one is required) - 3) Add a new language variable to ucp.php - - The user is then able to select the new rule. It will be checked against and handled as specified. - To add new actions (yes, checks can be added here too) to the rule management, the core code has to be modified. -*/ - -define('RULE_IS_LIKE', 1); // Is Like -define('RULE_IS_NOT_LIKE', 2); // Is Not Like -define('RULE_IS', 3); // Is -define('RULE_IS_NOT', 4); // Is Not -define('RULE_BEGINS_WITH', 5); // Begins with -define('RULE_ENDS_WITH', 6); // Ends with -define('RULE_IS_FRIEND', 7); // Is Friend -define('RULE_IS_FOE', 8); // Is Foe -define('RULE_IS_USER', 9); // Is User -define('RULE_IS_GROUP', 10); // Is In Usergroup -define('RULE_ANSWERED', 11); // Answered -define('RULE_FORWARDED', 12); // Forwarded -define('RULE_TO_GROUP', 14); // Usergroup -define('RULE_TO_ME', 15); // Me - -define('ACTION_PLACE_INTO_FOLDER', 1); -define('ACTION_MARK_AS_READ', 2); -define('ACTION_MARK_AS_IMPORTANT', 3); -define('ACTION_DELETE_MESSAGE', 4); - -define('CHECK_SUBJECT', 1); -define('CHECK_SENDER', 2); -define('CHECK_MESSAGE', 3); -define('CHECK_STATUS', 4); -define('CHECK_TO', 5); - -/** -* Global private message rules -* These rules define what to do if a rule is hit -*/ -$global_privmsgs_rules = array( - CHECK_SUBJECT => array( - RULE_IS_LIKE => array('check0' => 'message_subject', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0})'), - RULE_IS_NOT_LIKE => array('check0' => 'message_subject', 'function' => '!(preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0}))'), - RULE_IS => array('check0' => 'message_subject', 'function' => '{CHECK0} == {STRING}'), - RULE_IS_NOT => array('check0' => 'message_subject', 'function' => '{CHECK0} != {STRING}'), - RULE_BEGINS_WITH => array('check0' => 'message_subject', 'function' => 'preg_match("/^" . preg_quote({STRING}, "/") . "/i", {CHECK0})'), - RULE_ENDS_WITH => array('check0' => 'message_subject', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "$/i", {CHECK0})'), - ), - - CHECK_SENDER => array( - RULE_IS_LIKE => array('check0' => 'username', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0})'), - RULE_IS_NOT_LIKE => array('check0' => 'username', 'function' => '!(preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0}))'), - RULE_IS => array('check0' => 'username', 'function' => '{CHECK0} == {STRING}'), - RULE_IS_NOT => array('check0' => 'username', 'function' => '{CHECK0} != {STRING}'), - RULE_BEGINS_WITH => array('check0' => 'username', 'function' => 'preg_match("/^" . preg_quote({STRING}, "/") . "/i", {CHECK0})'), - RULE_ENDS_WITH => array('check0' => 'username', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "$/i", {CHECK0})'), - RULE_IS_FRIEND => array('check0' => 'friend', 'function' => '{CHECK0} == 1'), - RULE_IS_FOE => array('check0' => 'foe', 'function' => '{CHECK0} == 1'), - RULE_IS_USER => array('check0' => 'author_id', 'function' => '{CHECK0} == {USER_ID}'), - RULE_IS_GROUP => array('check0' => 'author_in_group', 'function' => 'in_array({GROUP_ID}, {CHECK0})'), - ), - - CHECK_MESSAGE => array( - RULE_IS_LIKE => array('check0' => 'message_text', 'function' => 'preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0})'), - RULE_IS_NOT_LIKE => array('check0' => 'message_text', 'function' => '!(preg_match("/" . preg_quote({STRING}, "/") . "/i", {CHECK0}))'), - RULE_IS => array('check0' => 'message_text', 'function' => '{CHECK0} == {STRING}'), - RULE_IS_NOT => array('check0' => 'message_text', 'function' => '{CHECK0} != {STRING}'), - ), - - CHECK_STATUS => array( - RULE_ANSWERED => array('check0' => 'pm_replied', 'function' => '{CHECK0} == 1'), - RULE_FORWARDED => array('check0' => 'pm_forwarded', 'function' => '{CHECK0} == 1'), - ), - - CHECK_TO => array( - RULE_TO_GROUP => array('check0' => 'to', 'check1' => 'bcc', 'check2' => 'user_in_group', 'function' => 'in_array("g_" . {CHECK2}, {CHECK0}) || in_array("g_" . {CHECK2}, {CHECK1})'), - RULE_TO_ME => array('check0' => 'to', 'check1' => 'bcc', 'function' => 'in_array("u_" . $user_id, {CHECK0}) || in_array("u_" . $user_id, {CHECK1})'), - ) -); - -/** -* This is for defining which condition fields to show for which Rule -*/ -$global_rule_conditions = array( - RULE_IS_LIKE => 'text', - RULE_IS_NOT_LIKE => 'text', - RULE_IS => 'text', - RULE_IS_NOT => 'text', - RULE_BEGINS_WITH => 'text', - RULE_ENDS_WITH => 'text', - RULE_IS_USER => 'user', - RULE_IS_GROUP => 'group' -); - -/** -* Get all folder -*/ -function get_folder($user_id, $folder_id = false) -{ - $folder = array(); - - // Get folder information - $sql = 'SELECT folder_id, COUNT(msg_id) as num_messages, SUM(pm_unread) as num_unread - FROM ' . PRIVMSGS_TO_TABLE . " - WHERE user_id = $user_id - AND folder_id <> " . PRIVMSGS_NO_BOX . ' - GROUP BY folder_id'; - $result = phpbb::$db->sql_query($sql); - - $num_messages = $num_unread = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $num_messages[(int) $row['folder_id']] = $row['num_messages']; - $num_unread[(int) $row['folder_id']] = $row['num_unread']; - } - phpbb::$db->sql_freeresult($result); - - // Make sure the default boxes are defined - $available_folder = array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX); - - foreach ($available_folder as $default_folder) - { - if (!isset($num_messages[$default_folder])) - { - $num_messages[$default_folder] = 0; - } - - if (!isset($num_unread[$default_folder])) - { - $num_unread[$default_folder] = 0; - } - } - - // Adjust unread status for outbox - $num_unread[PRIVMSGS_OUTBOX] = $num_messages[PRIVMSGS_OUTBOX]; - - $folder[PRIVMSGS_INBOX] = array( - 'folder_name' => phpbb::$user->lang['PM_INBOX'], - 'num_messages' => $num_messages[PRIVMSGS_INBOX], - 'unread_messages' => $num_unread[PRIVMSGS_INBOX] - ); - - // Custom Folder - $sql = 'SELECT folder_id, folder_name, pm_count - FROM ' . PRIVMSGS_FOLDER_TABLE . " - WHERE user_id = $user_id"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $folder[$row['folder_id']] = array( - 'folder_name' => $row['folder_name'], - 'num_messages' => $row['pm_count'], - 'unread_messages' => ((isset($num_unread[$row['folder_id']])) ? $num_unread[$row['folder_id']] : 0) - ); - } - phpbb::$db->sql_freeresult($result); - - $folder[PRIVMSGS_OUTBOX] = array( - 'folder_name' => phpbb::$user->lang['PM_OUTBOX'], - 'num_messages' => $num_messages[PRIVMSGS_OUTBOX], - 'unread_messages' => $num_unread[PRIVMSGS_OUTBOX] - ); - - $folder[PRIVMSGS_SENTBOX] = array( - 'folder_name' => phpbb::$user->lang['PM_SENTBOX'], - 'num_messages' => $num_messages[PRIVMSGS_SENTBOX], - 'unread_messages' => $num_unread[PRIVMSGS_SENTBOX] - ); - - // Define Folder Array for template designers (and for making custom folders usable by the template too) - foreach ($folder as $f_id => $folder_ary) - { - $folder_id_name = ($f_id == PRIVMSGS_INBOX) ? 'inbox' : (($f_id == PRIVMSGS_OUTBOX) ? 'outbox' : 'sentbox'); - - phpbb::$template->assign_block_vars('folder', array( - 'FOLDER_ID' => $f_id, - 'FOLDER_NAME' => $folder_ary['folder_name'], - 'NUM_MESSAGES' => $folder_ary['num_messages'], - 'UNREAD_MESSAGES' => $folder_ary['unread_messages'], - - 'U_FOLDER' => ($f_id > 0) ? append_sid('ucp', 'i=pm&folder=' . $f_id) : append_sid('ucp', 'i=pm&folder=' . $folder_id_name), - - 'S_CUR_FOLDER' => ($f_id === $folder_id) ? true : false, - 'S_UNREAD_MESSAGES' => ($folder_ary['unread_messages']) ? true : false, - 'S_CUSTOM_FOLDER' => ($f_id > 0) ? true : false, - )); - } - - if ($folder_id !== false && !isset($folder[$folder_id])) - { - trigger_error('UNKNOWN_FOLDER'); - } - - return $folder; -} - -/** -* Delete Messages From Sentbox -* we are doing this here because this saves us a bunch of checks and queries -*/ -function clean_sentbox($num_sentbox_messages) -{ - // Check Message Limit - if (phpbb::$user->data['message_limit'] && $num_sentbox_messages > phpbb::$user->data['message_limit']) - { - // Delete old messages - $sql = 'SELECT t.msg_id - FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p - WHERE t.msg_id = p.msg_id - AND t.user_id = ' . phpbb::$user->data['user_id'] . ' - AND t.folder_id = ' . PRIVMSGS_SENTBOX . ' - ORDER BY p.message_time ASC'; - $result = phpbb::$db->sql_query_limit($sql, ($num_sentbox_messages - phpbb::$user->data['message_limit'])); - - $delete_ids = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $delete_ids[] = $row['msg_id']; - } - phpbb::$db->sql_freeresult($result); - delete_pm(phpbb::$user->data['user_id'], $delete_ids, PRIVMSGS_SENTBOX); - } -} - -/** -* Check Rule against Message Information -*/ -function check_rule(&$rules, &$rule_row, &$message_row, $user_id) -{ - if (!isset($rules[$rule_row['rule_check']][$rule_row['rule_connection']])) - { - return false; - } - - $check_ary = $rules[$rule_row['rule_check']][$rule_row['rule_connection']]; - - // Replace Check Literals - $evaluate = $check_ary['function']; - $evaluate = preg_replace('/{(CHECK[0-9])}/', '$message_row[$check_ary[strtolower("\1")]]', $evaluate); - - // Replace Rule Literals - $evaluate = preg_replace('/{(STRING|USER_ID|GROUP_ID)}/', '$rule_row["rule_" . strtolower("\1")]', $evaluate); - - // Evil Statement - $result = false; - eval('$result = (' . $evaluate . ') ? true : false;'); - - if (!$result) - { - return false; - } - - switch ($rule_row['rule_action']) - { - case ACTION_PLACE_INTO_FOLDER: - return array('action' => $rule_row['rule_action'], 'folder_id' => $rule_row['rule_folder_id']); - break; - - case ACTION_MARK_AS_READ: - case ACTION_MARK_AS_IMPORTANT: - return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']); - break; - - case ACTION_DELETE_MESSAGE: - // Check for admins/mods - users are not allowed to remove those messages... - // We do the check here to make sure the data we use is consistent - $sql = 'SELECT user_id, user_type, user_permissions - FROM ' . USERS_TABLE . ' - WHERE user_id = ' . (int) $message_row['author_id']; - $result = phpbb::$db->sql_query($sql); - $userdata = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - $auth2 = new auth(); - $auth2->acl($userdata); - - if (!$auth2->acl_get('a_') && !$auth2->acl_get('m_') && !$auth2->acl_getf_global('m_')) - { - return array('action' => $rule_row['rule_action'], 'pm_unread' => $message_row['pm_unread'], 'pm_marked' => $message_row['pm_marked']); - } - - return false; - break; - - default: - return false; - } - - return false; -} - -/** -* Update user PM count -*/ -function update_pm_counts() -{ - // Update unread count - $sql = 'SELECT COUNT(msg_id) as num_messages - FROM ' . PRIVMSGS_TO_TABLE . ' - WHERE pm_unread = 1 - AND folder_id <> ' . PRIVMSGS_OUTBOX . ' - AND user_id = ' . phpbb::$user->data['user_id']; - $result = phpbb::$db->sql_query($sql); - phpbb::$user->data['user_unread_privmsg'] = (int) phpbb::$db->sql_fetchfield('num_messages'); - phpbb::$db->sql_freeresult($result); - - // Update new pm count - $sql = 'SELECT COUNT(msg_id) as num_messages - FROM ' . PRIVMSGS_TO_TABLE . ' - WHERE pm_new = 1 - AND folder_id IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ') - AND user_id = ' . phpbb::$user->data['user_id']; - $result = phpbb::$db->sql_query($sql); - phpbb::$user->data['user_new_privmsg'] = (int) phpbb::$db->sql_fetchfield('num_messages'); - phpbb::$db->sql_freeresult($result); - - phpbb::$db->sql_query('UPDATE ' . USERS_TABLE . ' SET ' . phpbb::$db->sql_build_array('UPDATE', array( - 'user_unread_privmsg' => (int) phpbb::$user->data['user_unread_privmsg'], - 'user_new_privmsg' => (int) phpbb::$user->data['user_new_privmsg'], - )) . ' WHERE user_id = ' . phpbb::$user->data['user_id']); - - // Ok, here we need to repair something, other boxes than privmsgs_no_box and privmsgs_hold_box should not carry the pm_new flag. - if (!phpbb::$user->data['user_new_privmsg']) - { - $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' - SET pm_new = 0 - WHERE pm_new = 1 - AND folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ') - AND user_id = ' . phpbb::$user->data['user_id']; - phpbb::$db->sql_query($sql); - } -} - -/** -* Place new messages into appropriate folder -*/ -function place_pm_into_folder(&$global_privmsgs_rules, $release = false) -{ - if (!phpbb::$user->data['user_new_privmsg']) - { - return array('not_moved' => 0, 'removed' => 0); - } - - $user_message_rules = (int) phpbb::$user->data['user_message_rules']; - $user_id = (int) phpbb::$user->data['user_id']; - - $action_ary = $move_into_folder = array(); - $num_removed = 0; - - // Newly processing on-hold messages - if ($release) - { - $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' - SET folder_id = ' . PRIVMSGS_NO_BOX . ' - WHERE folder_id = ' . PRIVMSGS_HOLD_BOX . " - AND user_id = $user_id"; - phpbb::$db->sql_query($sql); - } - - // Get those messages not yet placed into any box - $retrieve_sql = 'SELECT t.*, p.*, u.username, u.user_id, u.group_id - FROM ' . PRIVMSGS_TO_TABLE . ' t, ' . PRIVMSGS_TABLE . ' p, ' . USERS_TABLE . " u - WHERE t.user_id = $user_id - AND p.author_id = u.user_id - AND t.folder_id = " . PRIVMSGS_NO_BOX . ' - AND t.msg_id = p.msg_id'; - - // Just place into the appropriate arrays if no rules need to be checked - if (!$user_message_rules) - { - $result = phpbb::$db->sql_query($retrieve_sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $action_ary[$row['msg_id']][] = array('action' => false); - } - phpbb::$db->sql_freeresult($result); - } - else - { - $user_rules = $zebra = $check_rows = array(); - $user_ids = $memberships = array(); - - // First of all, grab all rules and retrieve friends/foes - $sql = 'SELECT * - FROM ' . PRIVMSGS_RULES_TABLE . " - WHERE user_id = $user_id"; - $result = phpbb::$db->sql_query($sql); - $user_rules = phpbb::$db->sql_fetchrowset($result); - phpbb::$db->sql_freeresult($result); - - if (sizeof($user_rules)) - { - $sql = 'SELECT zebra_id, friend, foe - FROM ' . ZEBRA_TABLE . " - WHERE user_id = $user_id"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $zebra[$row['zebra_id']] = $row; - } - phpbb::$db->sql_freeresult($result); - } - - // Now build a bare-bone check_row array - $result = phpbb::$db->sql_query($retrieve_sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $check_rows[] = array_merge($row, array( - 'to' => explode(':', $row['to_address']), - 'bcc' => explode(':', $row['bcc_address']), - 'friend' => (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['friend'] : 0, - 'foe' => (isset($zebra[$row['author_id']])) ? $zebra[$row['author_id']]['foe'] : 0, - 'user_in_group' => array(phpbb::$user->data['group_id']), - 'author_in_group' => array()) - ); - - $user_ids[] = $row['user_id']; - } - phpbb::$db->sql_freeresult($result); - - // Retrieve user memberships - if (sizeof($user_ids)) - { - $sql = 'SELECT * - FROM ' . USER_GROUP_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('user_id', $user_ids) . ' - AND user_pending = 0'; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $memberships[$row['user_id']][] = $row['group_id']; - } - phpbb::$db->sql_freeresult($result); - } - - // Now place into the appropriate folder - foreach ($check_rows as $row) - { - // Add membership if set - if (isset($memberships[$row['author_id']])) - { - $row['author_in_group'] = $memberships[$row['user_id']]; - } - - // Check Rule - this should be very quick since we have all information we need - $is_match = false; - foreach ($user_rules as $rule_row) - { - if (($action = check_rule($global_privmsgs_rules, $rule_row, $row, $user_id)) !== false) - { - $is_match = true; - $action_ary[$row['msg_id']][] = $action; - } - } - - if (!$is_match) - { - $action_ary[$row['msg_id']][] = array('action' => false); - } - } - - unset($user_rules, $zebra, $check_rows, $user_ids, $memberships); - } - - // We place actions into arrays, to save queries. - $sql = $unread_ids = $delete_ids = $important_ids = array(); - - foreach ($action_ary as $msg_id => $msg_ary) - { - // It is allowed to execute actions more than once, except placing messages into folder - $folder_action = $message_removed = false; - - foreach ($msg_ary as $pos => $rule_ary) - { - if ($folder_action && $rule_ary['action'] == ACTION_PLACE_INTO_FOLDER) - { - continue; - } - - switch ($rule_ary['action']) - { - case ACTION_PLACE_INTO_FOLDER: - // Folder actions have precedence, so we will remove any other ones - $folder_action = true; - $move_into_folder[(int) $rule_ary['folder_id']][] = $msg_id; - break; - - case ACTION_MARK_AS_READ: - if ($rule_ary['pm_unread']) - { - $unread_ids[] = $msg_id; - } - break; - - case ACTION_DELETE_MESSAGE: - $delete_ids[] = $msg_id; - $message_removed = true; - break; - - case ACTION_MARK_AS_IMPORTANT: - if (!$rule_ary['pm_marked']) - { - $important_ids[] = $msg_id; - } - break; - } - } - - // We place this here because it could happen that the messages are doubled if a rule marks a message and then moves it into a specific - // folder. Here we simply move the message into the INBOX if it gets not removed and also not put into a custom folder. - if (!$folder_action && !$message_removed) - { - $move_into_folder[PRIVMSGS_INBOX][] = $msg_id; - } - } - - // Do not change the order of processing - // The number of queries needed to be executed here highly depends on the defined rules and are - // only gone through if new messages arrive. - - // Delete messages - if (sizeof($delete_ids)) - { - $num_removed += sizeof($delete_ids); - delete_pm($user_id, $delete_ids, PRIVMSGS_NO_BOX); - } - - // Set messages to Unread - if (sizeof($unread_ids)) - { - $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' - SET pm_unread = 0 - WHERE ' . phpbb::$db->sql_in_set('msg_id', $unread_ids) . " - AND user_id = $user_id - AND folder_id = " . PRIVMSGS_NO_BOX; - phpbb::$db->sql_query($sql); - } - - // mark messages as important - if (sizeof($important_ids)) - { - $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' - SET pm_marked = 1 - pm_marked - WHERE folder_id = ' . PRIVMSGS_NO_BOX . " - AND user_id = $user_id - AND " . phpbb::$db->sql_in_set('msg_id', $important_ids); - phpbb::$db->sql_query($sql); - } - - // Move into folder - $folder = array(); - - if (sizeof($move_into_folder)) - { - // Determine Full Folder Action - we need the move to folder id later eventually - $full_folder_action = (phpbb::$user->data['user_full_folder'] == FULL_FOLDER_NONE) ? (phpbb::$config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : phpbb::$user->data['user_full_folder']; - - $sql_folder = array_keys($move_into_folder); - if ($full_folder_action >= 0) - { - $sql_folder[] = $full_folder_action; - } - - $sql = 'SELECT folder_id, pm_count - FROM ' . PRIVMSGS_FOLDER_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('folder_id', $sql_folder) . " - AND user_id = $user_id"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $folder[(int) $row['folder_id']] = (int) $row['pm_count']; - } - phpbb::$db->sql_freeresult($result); - - unset($sql_folder); - - if (isset($move_into_folder[PRIVMSGS_INBOX])) - { - $sql = 'SELECT COUNT(msg_id) as num_messages - FROM ' . PRIVMSGS_TO_TABLE . " - WHERE user_id = $user_id - AND folder_id = " . PRIVMSGS_INBOX; - $result = phpbb::$db->sql_query($sql); - $folder[PRIVMSGS_INBOX] = (int) phpbb::$db->sql_fetchfield('num_messages'); - phpbb::$db->sql_freeresult($result); - } - } - - // Here we have ideally only one folder to move into - foreach ($move_into_folder as $folder_id => $msg_ary) - { - $dest_folder = $folder_id; - $full_folder_action = FULL_FOLDER_NONE; - - // Check Message Limit - we calculate with the complete array, most of the time it is one message - // But we are making sure that the other way around works too (more messages in queue than allowed to be stored) - if (phpbb::$user->data['message_limit'] && $folder[$folder_id] && ($folder[$folder_id] + sizeof($msg_ary)) > phpbb::$user->data['message_limit']) - { - $full_folder_action = (phpbb::$user->data['user_full_folder'] == FULL_FOLDER_NONE) ? (phpbb::$config['full_folder_action'] - (FULL_FOLDER_NONE*(-1))) : phpbb::$user->data['user_full_folder']; - - // If destination folder itself is full... - if ($full_folder_action >= 0 && ($folder[$full_folder_action] + sizeof($msg_ary)) > phpbb::$user->data['message_limit']) - { - $full_folder_action = phpbb::$config['full_folder_action'] - (FULL_FOLDER_NONE*(-1)); - } - - // If Full Folder Action is to move to another folder, we simply adjust the destination folder - if ($full_folder_action >= 0) - { - $dest_folder = $full_folder_action; - } - else if ($full_folder_action == FULL_FOLDER_DELETE) - { - // Delete some messages. NOTE: Ordered by msg_id here instead of message_time! - $sql = 'SELECT msg_id - FROM ' . PRIVMSGS_TO_TABLE . " - WHERE user_id = $user_id - AND folder_id = $dest_folder - ORDER BY msg_id ASC"; - $result = phpbb::$db->sql_query_limit($sql, (($folder[$dest_folder] + sizeof($msg_ary)) - phpbb::$user->data['message_limit'])); - - $delete_ids = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $delete_ids[] = $row['msg_id']; - } - phpbb::$db->sql_freeresult($result); - - $num_removed += sizeof($delete_ids); - delete_pm($user_id, $delete_ids, $dest_folder); - } - } - - // - if ($full_folder_action == FULL_FOLDER_HOLD) - { - $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' - SET folder_id = ' . PRIVMSGS_HOLD_BOX . ' - WHERE folder_id = ' . PRIVMSGS_NO_BOX . " - AND user_id = $user_id - AND " . phpbb::$db->sql_in_set('msg_id', $msg_ary); - phpbb::$db->sql_query($sql); - } - else - { - $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " - SET folder_id = $dest_folder, pm_new = 0 - WHERE folder_id = " . PRIVMSGS_NO_BOX . " - AND user_id = $user_id - AND pm_new = 1 - AND " . phpbb::$db->sql_in_set('msg_id', $msg_ary); - phpbb::$db->sql_query($sql); - - if ($dest_folder != PRIVMSGS_INBOX) - { - $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . ' - SET pm_count = pm_count + ' . (int) phpbb::$db->sql_affectedrows() . " - WHERE folder_id = $dest_folder - AND user_id = $user_id"; - phpbb::$db->sql_query($sql); - } - } - } - - if (sizeof($action_ary)) - { - // Move from OUTBOX to SENTBOX - // We are not checking any full folder status here... SENTBOX is a special treatment (old messages get deleted) - $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' - SET folder_id = ' . PRIVMSGS_SENTBOX . ' - WHERE folder_id = ' . PRIVMSGS_OUTBOX . ' - AND ' . phpbb::$db->sql_in_set('msg_id', array_keys($action_ary)); - phpbb::$db->sql_query($sql); - } - - // Update new/unread count - update_pm_counts(); - - // Now check how many messages got not moved... - $sql = 'SELECT COUNT(msg_id) as num_messages - FROM ' . PRIVMSGS_TO_TABLE . " - WHERE user_id = $user_id - AND folder_id = " . PRIVMSGS_HOLD_BOX; - $result = phpbb::$db->sql_query($sql); - $num_not_moved = (int) phpbb::$db->sql_fetchfield('num_messages'); - phpbb::$db->sql_freeresult($result); - - return array('not_moved' => $num_not_moved, 'removed' => $num_removed); -} - -/** -* Move PM from one to another folder -*/ -function move_pm($user_id, $message_limit, $move_msg_ids, $dest_folder, $cur_folder_id) -{ - $num_moved = 0; - - if (!is_array($move_msg_ids)) - { - $move_msg_ids = array($move_msg_ids); - } - - if (sizeof($move_msg_ids) && !in_array($dest_folder, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX)) && - !in_array($cur_folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX)) && $cur_folder_id != $dest_folder) - { - // We have to check the destination folder ;) - if ($dest_folder != PRIVMSGS_INBOX) - { - $sql = 'SELECT folder_id, folder_name, pm_count - FROM ' . PRIVMSGS_FOLDER_TABLE . " - WHERE folder_id = $dest_folder - AND user_id = $user_id"; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if (!$row) - { - trigger_error('NOT_AUTHORISED'); - } - - if ($message_limit && $row['pm_count'] + sizeof($move_msg_ids) > $message_limit) - { - $message = sprintf(phpbb::$user->lang['NOT_ENOUGH_SPACE_FOLDER'], $row['folder_name']) . '<br /><br />'; - $message .= sprintf(phpbb::$user->lang['CLICK_RETURN_FOLDER'], '<a href="' . append_sid('ucp', 'i=pm&folder=' . $row['folder_id']) . '">', '</a>', $row['folder_name']); - trigger_error($message); - } - } - else - { - $sql = 'SELECT COUNT(msg_id) as num_messages - FROM ' . PRIVMSGS_TO_TABLE . ' - WHERE folder_id = ' . PRIVMSGS_INBOX . " - AND user_id = $user_id"; - $result = phpbb::$db->sql_query($sql); - $num_messages = (int) phpbb::$db->sql_fetchfield('num_messages'); - phpbb::$db->sql_freeresult($result); - - if ($message_limit && $num_messages + sizeof($move_msg_ids) > $message_limit) - { - $message = sprintf(phpbb::$user->lang['NOT_ENOUGH_SPACE_FOLDER'], phpbb::$user->lang['PM_INBOX']) . '<br /><br />'; - $message .= sprintf(phpbb::$user->lang['CLICK_RETURN_FOLDER'], '<a href="' . append_sid('ucp', 'i=pm&folder=inbox') . '">', '</a>', phpbb::$user->lang['PM_INBOX']); - trigger_error($message); - } - } - - $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " - SET folder_id = $dest_folder - WHERE folder_id = $cur_folder_id - AND user_id = $user_id - AND " . phpbb::$db->sql_in_set('msg_id', $move_msg_ids); - phpbb::$db->sql_query($sql); - $num_moved = phpbb::$db->sql_affectedrows(); - - // Update pm counts - if ($num_moved) - { - if (!in_array($cur_folder_id, array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX))) - { - $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . " - SET pm_count = pm_count - $num_moved - WHERE folder_id = $cur_folder_id - AND user_id = $user_id"; - phpbb::$db->sql_query($sql); - } - - if ($dest_folder != PRIVMSGS_INBOX) - { - $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . " - SET pm_count = pm_count + $num_moved - WHERE folder_id = $dest_folder - AND user_id = $user_id"; - phpbb::$db->sql_query($sql); - } - } - } - else if (in_array($cur_folder_id, array(PRIVMSGS_NO_BOX, PRIVMSGS_OUTBOX))) - { - trigger_error('CANNOT_MOVE_SPECIAL'); - } - - return $num_moved; -} - -/** -* Update unread message status -*/ -function update_unread_status($unread, $msg_id, $user_id, $folder_id) -{ - if (!$unread) - { - return; - } - - $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " - SET pm_unread = 0 - WHERE msg_id = $msg_id - AND user_id = $user_id - AND folder_id = $folder_id"; - phpbb::$db->sql_query($sql); - - $sql = 'UPDATE ' . USERS_TABLE . " - SET user_unread_privmsg = user_unread_privmsg - 1 - WHERE user_id = $user_id"; - phpbb::$db->sql_query($sql); - - if (phpbb::$user->data['user_id'] == $user_id) - { - phpbb::$user->data['user_unread_privmsg']--; - - // Try to cope with previous wrong conversions... - if (phpbb::$user->data['user_unread_privmsg'] < 0) - { - $sql = 'UPDATE ' . USERS_TABLE . " - SET user_unread_privmsg = 0 - WHERE user_id = $user_id"; - phpbb::$db->sql_query($sql); - - phpbb::$user->data['user_unread_privmsg'] = 0; - } - } -} - -/** -* Handle all actions possible with marked messages -*/ -function handle_mark_actions($user_id, $mark_action) -{ - $msg_ids = request_var('marked_msg_id', array(0)); - $cur_folder_id = request_var('cur_folder_id', PRIVMSGS_NO_BOX); - $confirm = phpbb_request::is_set_post('confirm'); - - if (!sizeof($msg_ids)) - { - return false; - } - - switch ($mark_action) - { - case 'mark_important': - - $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . " - SET pm_marked = 1 - pm_marked - WHERE folder_id = $cur_folder_id - AND user_id = $user_id - AND " . phpbb::$db->sql_in_set('msg_id', $msg_ids); - phpbb::$db->sql_query($sql); - - break; - - case 'delete_marked': - - if (confirm_box(true)) - { - delete_pm($user_id, $msg_ids, $cur_folder_id); - - $success_msg = (sizeof($msg_ids) == 1) ? 'MESSAGE_DELETED' : 'MESSAGES_DELETED'; - $redirect = append_sid('ucp', 'i=pm&folder=' . $cur_folder_id); - - meta_refresh(3, $redirect); - trigger_error(phpbb::$user->lang[$success_msg] . '<br /><br />' . sprintf(phpbb::$user->lang['RETURN_FOLDER'], '<a href="' . $redirect . '">', '</a>')); - } - else - { - $s_hidden_fields = array( - 'cur_folder_id' => $cur_folder_id, - 'mark_option' => 'delete_marked', - 'submit_mark' => true, - 'marked_msg_id' => $msg_ids - ); - - confirm_box(false, 'DELETE_MARKED_PM', build_hidden_fields($s_hidden_fields)); - } - - break; - - default: - return false; - } - - return true; -} - -/** -* Delete PM(s) -*/ -function delete_pm($user_id, $msg_ids, $folder_id) -{ - $user_id = (int) $user_id; - $folder_id = (int) $folder_id; - - if (!$user_id) - { - return false; - } - - if (!is_array($msg_ids)) - { - if (!$msg_ids) - { - return false; - } - $msg_ids = array($msg_ids); - } - - if (!sizeof($msg_ids)) - { - return false; - } - - // Get PM Information for later deleting - $sql = 'SELECT msg_id, pm_unread, pm_new - FROM ' . PRIVMSGS_TO_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('msg_id', array_map('intval', $msg_ids)) . " - AND folder_id = $folder_id - AND user_id = $user_id"; - $result = phpbb::$db->sql_query($sql); - - $delete_rows = array(); - $num_unread = $num_new = $num_deleted = 0; - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $num_unread += (int) $row['pm_unread']; - $num_new += (int) $row['pm_new']; - - $delete_rows[$row['msg_id']] = 1; - } - phpbb::$db->sql_freeresult($result); - unset($msg_ids); - - if (!sizeof($delete_rows)) - { - return false; - } - - phpbb::$db->sql_transaction('begin'); - - // if no one has read the message yet (meaning it is in users outbox) - // then mark the message as deleted... - if ($folder_id == PRIVMSGS_OUTBOX) - { - // Remove PM from Outbox - $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . " - WHERE user_id = $user_id AND folder_id = " . PRIVMSGS_OUTBOX . ' - AND ' . phpbb::$db->sql_in_set('msg_id', array_keys($delete_rows)); - phpbb::$db->sql_query($sql); - - // Update PM Information for safety - $sql = 'UPDATE ' . PRIVMSGS_TABLE . " SET message_text = '' - WHERE " . phpbb::$db->sql_in_set('msg_id', array_keys($delete_rows)); - phpbb::$db->sql_query($sql); - - // Set delete flag for those intended to receive the PM - // We do not remove the message actually, to retain some basic information (sent time for example) - $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' - SET pm_deleted = 1 - WHERE ' . phpbb::$db->sql_in_set('msg_id', array_keys($delete_rows)); - phpbb::$db->sql_query($sql); - - $num_deleted = phpbb::$db->sql_affectedrows(); - } - else - { - // Delete private message data - $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . " - WHERE user_id = $user_id - AND folder_id = $folder_id - AND " . phpbb::$db->sql_in_set('msg_id', array_keys($delete_rows)); - phpbb::$db->sql_query($sql); - $num_deleted = phpbb::$db->sql_affectedrows(); - } - - // if folder id is user defined folder then decrease pm_count - if (!in_array($folder_id, array(PRIVMSGS_INBOX, PRIVMSGS_OUTBOX, PRIVMSGS_SENTBOX, PRIVMSGS_NO_BOX))) - { - $sql = 'UPDATE ' . PRIVMSGS_FOLDER_TABLE . " - SET pm_count = pm_count - $num_deleted - WHERE folder_id = $folder_id"; - phpbb::$db->sql_query($sql); - } - - // Update unread and new status field - if ($num_unread || $num_new) - { - $set_sql = ($num_unread) ? 'user_unread_privmsg = user_unread_privmsg - ' . $num_unread : ''; - - if ($num_new) - { - $set_sql .= ($set_sql != '') ? ', ' : ''; - $set_sql .= 'user_new_privmsg = user_new_privmsg - ' . $num_new; - } - - phpbb::$db->sql_query('UPDATE ' . USERS_TABLE . " SET $set_sql WHERE user_id = $user_id"); - - phpbb::$user->data['user_new_privmsg'] -= $num_new; - phpbb::$user->data['user_unread_privmsg'] -= $num_unread; - } - - // Now we have to check which messages we can delete completely - $sql = 'SELECT msg_id - FROM ' . PRIVMSGS_TO_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('msg_id', array_keys($delete_rows)); - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - unset($delete_rows[$row['msg_id']]); - } - phpbb::$db->sql_freeresult($result); - - $delete_ids = array_keys($delete_rows); - - if (sizeof($delete_ids)) - { - // Check if there are any attachments we need to remove - if (!function_exists('delete_attachments')) - { - include(PHPBB_ROOT_PATH . 'includes/functions_admin.' . PHP_EXT); - } - - delete_attachments('message', $delete_ids, false); - - $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('msg_id', $delete_ids); - phpbb::$db->sql_query($sql); - } - - phpbb::$db->sql_transaction('commit'); - - return true; -} - -/** -* Rebuild message header -*/ -function rebuild_header($check_ary) -{ - $address = array(); - - foreach ($check_ary as $check_type => $address_field) - { - // Split Addresses into users and groups - preg_match_all('/:?(u|g)_([0-9]+):?/', $address_field, $match); - - $u = $g = array(); - foreach ($match[1] as $id => $type) - { - ${$type}[] = (int) $match[2][$id]; - } - - $_types = array('u', 'g'); - foreach ($_types as $type) - { - if (sizeof($$type)) - { - foreach ($$type as $id) - { - $address[$type][$id] = $check_type; - } - } - } - } - - return $address; -} - -/** -* Print out/assign recipient information -*/ -function write_pm_addresses($check_ary, $author_id, $plaintext = false) -{ - $addresses = array(); - - foreach ($check_ary as $check_type => $address_field) - { - if (!is_array($address_field)) - { - // Split Addresses into users and groups - preg_match_all('/:?(u|g)_([0-9]+):?/', $address_field, $match); - - $u = $g = array(); - foreach ($match[1] as $id => $type) - { - ${$type}[] = (int) $match[2][$id]; - } - } - else - { - $u = $address_field['u']; - $g = $address_field['g']; - } - - $address = array(); - if (sizeof($u)) - { - $sql = 'SELECT user_id, username, user_colour - FROM ' . USERS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('user_id', $u) . ' - AND user_type IN (' . phpbb::USER_NORMAL . ', ' . phpbb::USER_FOUNDER . ')'; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($check_type == 'to' || $author_id == phpbb::$user->data['user_id'] || $row['user_id'] == phpbb::$user->data['user_id']) - { - if ($plaintext) - { - $address[] = $row['username']; - } - else - { - $address['user'][$row['user_id']] = array('name' => $row['username'], 'colour' => $row['user_colour']); - } - } - } - phpbb::$db->sql_freeresult($result); - } - - if (sizeof($g)) - { - if ($plaintext) - { - $sql = 'SELECT group_name, group_type - FROM ' . GROUPS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('group_id', $g); - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($check_type == 'to' || $author_id == phpbb::$user->data['user_id'] || $row['user_id'] == phpbb::$user->data['user_id']) - { - $address[] = ($row['group_type'] == GROUP_SPECIAL) ? phpbb::$user->lang['G_' . $row['group_name']] : $row['group_name']; - } - } - phpbb::$db->sql_freeresult($result); - } - else - { - $sql = 'SELECT g.group_id, g.group_name, g.group_colour, g.group_type, ug.user_id - FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug - WHERE ' . phpbb::$db->sql_in_set('g.group_id', $g) . ' - AND g.group_id = ug.group_id - AND ug.user_pending = 0'; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if (!isset($address['group'][$row['group_id']])) - { - if ($check_type == 'to' || $author_id == phpbb::$user->data['user_id'] || $row['user_id'] == phpbb::$user->data['user_id']) - { - $row['group_name'] = ($row['group_type'] == GROUP_SPECIAL) ? phpbb::$user->lang['G_' . $row['group_name']] : $row['group_name']; - $address['group'][$row['group_id']] = array('name' => $row['group_name'], 'colour' => $row['group_colour']); - } - } - - if (isset($address['user'][$row['user_id']])) - { - $address['user'][$row['user_id']]['in_group'] = $row['group_id']; - } - } - phpbb::$db->sql_freeresult($result); - } - } - - if (sizeof($address) && !$plaintext) - { - phpbb::$template->assign_var('S_' . strtoupper($check_type) . '_RECIPIENT', true); - - foreach ($address as $type => $adr_ary) - { - foreach ($adr_ary as $id => $row) - { - $tpl_ary = array( - 'IS_GROUP' => ($type == 'group') ? true : false, - 'IS_USER' => ($type == 'user') ? true : false, - 'UG_ID' => $id, - 'NAME' => $row['name'], - 'COLOUR' => ($row['colour']) ? '#' . $row['colour'] : '', - 'TYPE' => $type, - ); - - if ($type == 'user') - { - $tpl_ary = array_merge($tpl_ary, array( - 'U_VIEW' => get_username_string('profile', $id, $row['name'], $row['colour']), - 'NAME_FULL' => get_username_string('full', $id, $row['name'], $row['colour']), - )); - } - else - { - $tpl_ary = array_merge($tpl_ary, array( - 'U_VIEW' => append_sid('memberlist', 'mode=group&g=' . $id), - )); - } - - phpbb::$template->assign_block_vars($check_type . '_recipient', $tpl_ary); - } - } - } - - $addresses[$check_type] = $address; - } - - return $addresses; -} - -/** -* Get folder status -*/ -function get_folder_status($folder_id, $folder) -{ - if (isset($folder[$folder_id])) - { - $folder = $folder[$folder_id]; - } - else - { - return false; - } - - $return = array( - 'folder_name' => $folder['folder_name'], - 'cur' => $folder['num_messages'], - 'remaining' => (phpbb::$user->data['message_limit']) ? phpbb::$user->data['message_limit'] - $folder['num_messages'] : 0, - 'max' => phpbb::$user->data['message_limit'], - 'percent' => (phpbb::$user->data['message_limit']) ? ((phpbb::$user->data['message_limit'] > 0) ? round(($folder['num_messages'] / phpbb::$user->data['message_limit']) * 100) : 100) : 0, - ); - - $return['message'] = sprintf(phpbb::$user->lang['FOLDER_STATUS_MSG'], $return['percent'], $return['cur'], $return['max']); - - return $return; -} - -// -// COMPOSE MESSAGES -// - -/** -* Submit PM -*/ -function submit_pm($mode, $subject, &$data, $put_in_outbox = true) -{ - // We do not handle erasing pms here - if ($mode == 'delete') - { - return false; - } - - $current_time = time(); - - // Collect some basic information about which tables and which rows to update/insert - $sql_data = array(); - $root_level = 0; - - // Recipient Information - $recipients = $to = $bcc = array(); - - if ($mode != 'edit') - { - // Build Recipient List - // u|g => array($user_id => 'to'|'bcc') - $_types = array('u', 'g'); - foreach ($_types as $ug_type) - { - if (isset($data['address_list'][$ug_type]) && sizeof($data['address_list'][$ug_type])) - { - foreach ($data['address_list'][$ug_type] as $id => $field) - { - $id = (int) $id; - - // Do not rely on the address list being "valid" - if (!$id || ($ug_type == 'u' && $id == ANONYMOUS)) - { - continue; - } - - $field = ($field == 'to') ? 'to' : 'bcc'; - if ($ug_type == 'u') - { - $recipients[$id] = $field; - } - ${$field}[] = $ug_type . '_' . $id; - } - } - } - - if (isset($data['address_list']['g']) && sizeof($data['address_list']['g'])) - { - // We need to check the PM status of group members (do they want to receive PM's?) - // Only check if not a moderator or admin, since they are allowed to override this user setting - $sql_allow_pm = (!phpbb::$acl->acl_gets('a_', 'm_') && !phpbb::$acl->acl_getf_global('m_')) ? ' AND u.user_allow_pm = 1' : ''; - - $sql = 'SELECT u.user_type, ug.group_id, ug.user_id - FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . ' ug - WHERE ' . phpbb::$db->sql_in_set('ug.group_id', array_keys($data['address_list']['g'])) . ' - AND ug.user_pending = 0 - AND u.user_id = ug.user_id - AND u.user_type IN (' . phpbb::USER_NORMAL . ', ' . phpbb::USER_FOUNDER . ')' . - $sql_allow_pm; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $field = ($data['address_list']['g'][$row['group_id']] == 'to') ? 'to' : 'bcc'; - $recipients[$row['user_id']] = $field; - } - phpbb::$db->sql_freeresult($result); - } - - if (!sizeof($recipients)) - { - trigger_error('NO_RECIPIENT'); - } - } - - phpbb::$db->sql_transaction('begin'); - - $sql = ''; - - switch ($mode) - { - case 'reply': - case 'quote': - $root_level = ($data['reply_from_root_level']) ? $data['reply_from_root_level'] : $data['reply_from_msg_id']; - - // Set message_replied switch for this user - $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' - SET pm_replied = 1 - WHERE user_id = ' . $data['from_user_id'] . ' - AND msg_id = ' . $data['reply_from_msg_id']; - - // no break - - case 'forward': - case 'post': - case 'quotepost': - $sql_data = array( - 'root_level' => $root_level, - 'author_id' => $data['from_user_id'], - 'icon_id' => $data['icon_id'], - 'author_ip' => $data['from_user_ip'], - 'message_time' => $current_time, - 'enable_bbcode' => $data['enable_bbcode'], - 'enable_smilies' => $data['enable_smilies'], - 'enable_magic_url' => $data['enable_urls'], - 'enable_sig' => $data['enable_sig'], - 'message_subject' => $subject, - 'message_text' => $data['message'], - 'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0, - 'bbcode_bitfield' => $data['bbcode_bitfield'], - 'bbcode_uid' => $data['bbcode_uid'], - 'to_address' => implode(':', $to), - 'bcc_address' => implode(':', $bcc) - ); - break; - - case 'edit': - $sql_data = array( - 'icon_id' => $data['icon_id'], - 'message_edit_time' => $current_time, - 'enable_bbcode' => $data['enable_bbcode'], - 'enable_smilies' => $data['enable_smilies'], - 'enable_magic_url' => $data['enable_urls'], - 'enable_sig' => $data['enable_sig'], - 'message_subject' => $subject, - 'message_text' => $data['message'], - 'message_attachment'=> (!empty($data['attachment_data'])) ? 1 : 0, - 'bbcode_bitfield' => $data['bbcode_bitfield'], - 'bbcode_uid' => $data['bbcode_uid'] - ); - break; - } - - if (sizeof($sql_data)) - { - $query = ''; - - if ($mode == 'post' || $mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward') - { - phpbb::$db->sql_query('INSERT INTO ' . PRIVMSGS_TABLE . ' ' . phpbb::$db->sql_build_array('INSERT', $sql_data)); - $data['msg_id'] = phpbb::$db->sql_nextid(); - } - else if ($mode == 'edit') - { - $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' - SET message_edit_count = message_edit_count + 1, ' . phpbb::$db->sql_build_array('UPDATE', $sql_data) . ' - WHERE msg_id = ' . $data['msg_id']; - phpbb::$db->sql_query($sql); - } - } - - if ($mode != 'edit') - { - if ($sql) - { - phpbb::$db->sql_query($sql); - } - unset($sql); - - $sql_ary = array(); - foreach ($recipients as $user_id => $type) - { - $sql_ary[] = array( - 'msg_id' => (int) $data['msg_id'], - 'user_id' => (int) $user_id, - 'author_id' => (int) $data['from_user_id'], - 'folder_id' => PRIVMSGS_NO_BOX, - 'pm_new' => 1, - 'pm_unread' => 1, - 'pm_forwarded' => ($mode == 'forward') ? 1 : 0 - ); - } - - phpbb::$db->sql_multi_insert(PRIVMSGS_TO_TABLE, $sql_ary); - - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_new_privmsg = user_new_privmsg + 1, user_unread_privmsg = user_unread_privmsg + 1, user_last_privmsg = ' . time() . ' - WHERE ' . phpbb::$db->sql_in_set('user_id', array_keys($recipients)); - phpbb::$db->sql_query($sql); - - // Put PM into outbox - if ($put_in_outbox) - { - phpbb::$db->sql_query('INSERT INTO ' . PRIVMSGS_TO_TABLE . ' ' . phpbb::$db->sql_build_array('INSERT', array( - 'msg_id' => (int) $data['msg_id'], - 'user_id' => (int) $data['from_user_id'], - 'author_id' => (int) $data['from_user_id'], - 'folder_id' => PRIVMSGS_OUTBOX, - 'pm_new' => 0, - 'pm_unread' => 0, - 'pm_forwarded' => ($mode == 'forward') ? 1 : 0)) - ); - } - } - - // Set user last post time - if ($mode == 'reply' || $mode == 'quote' || $mode == 'quotepost' || $mode == 'forward' || $mode == 'post') - { - $sql = 'UPDATE ' . USERS_TABLE . " - SET user_lastpost_time = $current_time - WHERE user_id = " . $data['from_user_id']; - phpbb::$db->sql_query($sql); - } - - // Submit Attachments - if (!empty($data['attachment_data']) && $data['msg_id'] && in_array($mode, array('post', 'reply', 'quote', 'quotepost', 'edit', 'forward'))) - { - $space_taken = $files_added = 0; - $orphan_rows = array(); - - foreach ($data['attachment_data'] as $pos => $attach_row) - { - $orphan_rows[(int) $attach_row['attach_id']] = array(); - } - - if (sizeof($orphan_rows)) - { - $sql = 'SELECT attach_id, filesize, physical_filename - FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('attach_id', array_keys($orphan_rows)) . ' - AND in_message = 1 - AND is_orphan = 1 - AND poster_id = ' . phpbb::$user->data['user_id']; - $result = phpbb::$db->sql_query($sql); - - $orphan_rows = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $orphan_rows[$row['attach_id']] = $row; - } - phpbb::$db->sql_freeresult($result); - } - - foreach ($data['attachment_data'] as $pos => $attach_row) - { - if ($attach_row['is_orphan'] && !isset($orphan_rows[$attach_row['attach_id']])) - { - continue; - } - - if (!$attach_row['is_orphan']) - { - // update entry in db if attachment already stored in db and filespace - $sql = 'UPDATE ' . ATTACHMENTS_TABLE . " - SET attach_comment = '" . phpbb::$db->sql_escape($attach_row['attach_comment']) . "' - WHERE attach_id = " . (int) $attach_row['attach_id'] . ' - AND is_orphan = 0'; - phpbb::$db->sql_query($sql); - } - else - { - // insert attachment into db - if (!@file_exists(PHPBB_ROOT_PATH . phpbb::$config['upload_path'] . '/' . basename($orphan_rows[$attach_row['attach_id']]['physical_filename']))) - { - continue; - } - - $space_taken += $orphan_rows[$attach_row['attach_id']]['filesize']; - $files_added++; - - $attach_sql = array( - 'post_msg_id' => $data['msg_id'], - 'topic_id' => 0, - 'is_orphan' => 0, - 'poster_id' => $data['from_user_id'], - 'attach_comment' => $attach_row['attach_comment'], - ); - - $sql = 'UPDATE ' . ATTACHMENTS_TABLE . ' SET ' . phpbb::$db->sql_build_array('UPDATE', $attach_sql) . ' - WHERE attach_id = ' . $attach_row['attach_id'] . ' - AND is_orphan = 1 - AND poster_id = ' . phpbb::$user->data['user_id']; - phpbb::$db->sql_query($sql); - } - } - - if ($space_taken && $files_added) - { - set_config_count('upload_dir_size', $space_taken, true); - set_config_count('num_files', $files_added, true); - } - } - - // Delete draft if post was loaded... - $draft_id = request_var('draft_loaded', 0); - if ($draft_id) - { - $sql = 'DELETE FROM ' . DRAFTS_TABLE . " - WHERE draft_id = $draft_id - AND user_id = " . $data['from_user_id']; - phpbb::$db->sql_query($sql); - } - - phpbb::$db->sql_transaction('commit'); - - // Send Notifications - if ($mode != 'edit') - { - pm_notification($mode, $data['from_username'], $recipients, $subject, $data['message']); - } - - return $data['msg_id']; -} - -/** -* PM Notification -*/ -function pm_notification($mode, $author, $recipients, $subject, $message) -{ - $subject = censor_text($subject); - - unset($recipients[ANONYMOUS], $recipients[phpbb::$user->data['user_id']]); - - if (!sizeof($recipients)) - { - return; - } - - // Get banned User ID's - $sql = 'SELECT ban_userid - FROM ' . BANLIST_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('ban_userid', array_map('intval', array_keys($recipients))) . ' - AND ban_exclude = 0'; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - unset($recipients[$row['ban_userid']]); - } - phpbb::$db->sql_freeresult($result); - - if (!sizeof($recipients)) - { - return; - } - - $sql = 'SELECT user_id, username, user_email, user_lang, user_notify_pm, user_notify_type, user_jabber - FROM ' . USERS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('user_id', array_map('intval', array_keys($recipients))); - $result = phpbb::$db->sql_query($sql); - - $msg_list_ary = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($row['user_notify_pm'] == 1 && trim($row['user_email'])) - { - $msg_list_ary[] = array( - 'method' => $row['user_notify_type'], - 'email' => $row['user_email'], - 'jabber' => $row['user_jabber'], - 'name' => $row['username'], - 'lang' => $row['user_lang'] - ); - } - } - phpbb::$db->sql_freeresult($result); - - if (!sizeof($msg_list_ary)) - { - return; - } - - include_once(PHPBB_ROOT_PATH . 'includes/functions_messenger.' . PHP_EXT); - $messenger = new messenger(); - - foreach ($msg_list_ary as $pos => $addr) - { - $messenger->template('privmsg_notify', $addr['lang']); - - $messenger->to($addr['email'], $addr['name']); - $messenger->im($addr['jabber'], $addr['name']); - - $messenger->assign_vars(array( - 'SUBJECT' => htmlspecialchars_decode($subject), - 'AUTHOR_NAME' => htmlspecialchars_decode($author), - 'USERNAME' => htmlspecialchars_decode($addr['name']), - - 'U_INBOX' => generate_board_url() . '/ucp.' . PHP_EXT . '?i=pm&folder=inbox') - ); - - $messenger->send($addr['method']); - } - unset($msg_list_ary); - - $messenger->save_queue(); - - unset($messenger); -} - -/** -* Display Message History -*/ -function message_history($msg_id, $user_id, $message_row, $folder, $in_post_mode = false) -{ - global $bbcode; - - // Get History Messages (could be newer) - $sql = 'SELECT t.*, p.*, u.* - FROM ' . PRIVMSGS_TABLE . ' p, ' . PRIVMSGS_TO_TABLE . ' t, ' . USERS_TABLE . ' u - WHERE t.msg_id = p.msg_id - AND p.author_id = u.user_id - AND t.folder_id NOT IN (' . PRIVMSGS_NO_BOX . ', ' . PRIVMSGS_HOLD_BOX . ") - AND t.user_id = $user_id"; - - if (!$message_row['root_level']) - { - $sql .= " AND (p.root_level = $msg_id OR (p.root_level = 0 AND p.msg_id = $msg_id))"; - } - else - { - $sql .= " AND (p.root_level = " . $message_row['root_level'] . ' OR p.msg_id = ' . $message_row['root_level'] . ')'; - } - $sql .= ' ORDER BY p.message_time DESC'; - - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - - if (!$row) - { - phpbb::$db->sql_freeresult($result); - return false; - } - - $rowset = array(); - $bbcode_bitfield = ''; - $folder_url = append_sid('ucp', 'i=pm') . '&folder='; - - do - { - $folder_id = (int) $row['folder_id']; - - $row['folder'][] = (isset($folder[$folder_id])) ? '<a href="' . $folder_url . $folder_id . '">' . $folder[$folder_id]['folder_name'] . '</a>' : phpbb::$user->lang['UNKNOWN_FOLDER']; - - if (isset($rowset[$row['msg_id']])) - { - $rowset[$row['msg_id']]['folder'][] = (isset($folder[$folder_id])) ? '<a href="' . $folder_url . $folder_id . '">' . $folder[$folder_id]['folder_name'] . '</a>' : phpbb::$user->lang['UNKNOWN_FOLDER']; - } - else - { - $rowset[$row['msg_id']] = $row; - $bbcode_bitfield = $bbcode_bitfield | base64_decode($row['bbcode_bitfield']); - } - } - while ($row = phpbb::$db->sql_fetchrow($result)); - phpbb::$db->sql_freeresult($result); - - $title = $row['message_subject']; - - if (sizeof($rowset) == 1 && !$in_post_mode) - { - return false; - } - - // Instantiate BBCode class - if ((empty($bbcode) || $bbcode === false) && $bbcode_bitfield !== '') - { - if (!class_exists('bbcode')) - { - include(PHPBB_ROOT_PATH . 'includes/bbcode.' . PHP_EXT); - } - $bbcode = new bbcode(base64_encode($bbcode_bitfield)); - } - - $title = censor_text($title); - - $url = append_sid('ucp', 'i=pm'); - $next_history_pm = $previous_history_pm = $prev_id = 0; - - // Re-order rowset to be able to get the next/prev message rows... - $rowset = array_values($rowset); - - for ($i = 0, $size = sizeof($rowset); $i < $size; $i++) - { - $row = &$rowset[$i]; - $id = (int) $row['msg_id']; - - $author_id = $row['author_id']; - $folder_id = (int) $row['folder_id']; - - $subject = $row['message_subject']; - $message = $row['message_text']; - - $message = censor_text($message); - - $decoded_message = false; - - if ($in_post_mode && phpbb::$acl->acl_get('u_sendpm') && $author_id != ANONYMOUS && $author_id != phpbb::$user->data['user_id']) - { - $decoded_message = $message; - decode_message($decoded_message, $row['bbcode_uid']); - - $decoded_message = bbcode_nl2br($decoded_message); - } - - if ($row['bbcode_bitfield']) - { - $bbcode->bbcode_second_pass($message, $row['bbcode_uid'], $row['bbcode_bitfield']); - } - - $message = bbcode_nl2br($message); - $message = smiley_text($message, !$row['enable_smilies']); - - $subject = censor_text($subject); - - if ($id == $msg_id) - { - $next_history_pm = (isset($rowset[$i + 1])) ? (int) $rowset[$i + 1]['msg_id'] : 0; - $previous_history_pm = $prev_id; - } - - phpbb::$template->assign_block_vars('history_row', array( - 'MESSAGE_AUTHOR_QUOTE' => (($decoded_message) ? addslashes(get_username_string('username', $author_id, $row['username'], $row['user_colour'], $row['username'])) : ''), - 'MESSAGE_AUTHOR_FULL' => get_username_string('full', $author_id, $row['username'], $row['user_colour'], $row['username']), - 'MESSAGE_AUTHOR_COLOUR' => get_username_string('colour', $author_id, $row['username'], $row['user_colour'], $row['username']), - 'MESSAGE_AUTHOR' => get_username_string('username', $author_id, $row['username'], $row['user_colour'], $row['username']), - 'U_MESSAGE_AUTHOR' => get_username_string('profile', $author_id, $row['username'], $row['user_colour'], $row['username']), - - 'SUBJECT' => $subject, - 'SENT_DATE' => phpbb::$user->format_date($row['message_time']), - 'MESSAGE' => $message, - 'FOLDER' => implode(', ', $row['folder']), - 'DECODED_MESSAGE' => $decoded_message, - - 'S_CURRENT_MSG' => ($row['msg_id'] == $msg_id), - 'S_AUTHOR_DELETED' => ($author_id == ANONYMOUS) ? true : false, - 'S_IN_POST_MODE' => $in_post_mode, - - 'MSG_ID' => $row['msg_id'], - 'U_VIEW_MESSAGE' => "$url&f=$folder_id&p=" . $row['msg_id'], - 'U_QUOTE' => (!$in_post_mode && phpbb::$acl->acl_get('u_sendpm') && $author_id != ANONYMOUS && $author_id != phpbb::$user->data['user_id']) ? "$url&mode=compose&action=quote&f=" . $folder_id . "&p=" . $row['msg_id'] : '', - 'U_POST_REPLY_PM' => ($author_id != phpbb::$user->data['user_id'] && $author_id != ANONYMOUS && phpbb::$acl->acl_get('u_sendpm')) ? "$url&mode=compose&action=reply&f=$folder_id&p=" . $row['msg_id'] : '', - )); - unset($rowset[$id]); - $prev_id = $id; - } - - phpbb::$template->assign_vars(array( - 'QUOTE_IMG' => phpbb::$user->img('icon_post_quote', 'REPLY_WITH_QUOTE'), - 'HISTORY_TITLE' => $title, - - 'U_VIEW_NEXT_HISTORY' => ($next_history_pm) ? "$url&p=" . $next_history_pm : '', - 'U_VIEW_PREVIOUS_HISTORY' => ($previous_history_pm) ? "$url&p=" . $previous_history_pm : '', - )); - - return true; -} - -/** -* Set correct users max messages in PM folder. -* If several group memberships define different amount of messages, the highest will be chosen. -*/ -function set_user_message_limit() -{ - // Get maximum about from user memberships - if it is 0, there is no limit set and we use the maximum value within the config. - $sql = 'SELECT MAX(g.group_message_limit) as max_message_limit - FROM ' . GROUPS_TABLE . ' g, ' . USER_GROUP_TABLE . ' ug - WHERE ug.user_id = ' . phpbb::$user->data['user_id'] . ' - AND ug.user_pending = 0 - AND ug.group_id = g.group_id'; - $result = phpbb::$db->sql_query($sql); - $message_limit = (int) phpbb::$db->sql_fetchfield('max_message_limit'); - phpbb::$db->sql_freeresult($result); - - phpbb::$user->data['message_limit'] = (!$message_limit) ? phpbb::$config['pm_max_msgs'] : $message_limit; -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/functions_profile_fields.php b/phpBB/includes/functions_profile_fields.php deleted file mode 100644 index 32c3782941..0000000000 --- a/phpBB/includes/functions_profile_fields.php +++ /dev/null @@ -1,1050 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Custom Profile Fields -* @package phpBB3 -*/ -class custom_profile -{ - public static $profile_types = array(FIELD_INT => 'int', FIELD_STRING => 'string', FIELD_TEXT => 'text', FIELD_BOOL => 'bool', FIELD_DROPDOWN => 'dropdown', FIELD_DATE => 'date'); - private $profile_cache = array(); - private $options_lang = array(); - - /** - * Assign editable fields to template, mode can be profile (for profile change) or register (for registration) - * Called by ucp_profile and ucp_register - * @access public - */ - public function generate_profile_fields($mode, $lang_id) - { - $sql_where = ''; - switch ($mode) - { - case 'register': - // If the field is required we show it on the registration page - $sql_where .= ' AND f.field_show_on_reg = 1'; - break; - - case 'profile': - // Show hidden fields to moderators/admins - if (!phpbb::$acl->acl_gets('a_', 'm_') && !phpbb::$acl->acl_getf_global('m_')) - { - $sql_where .= ' AND f.field_hide = 0'; - } - break; - - default: - trigger_error('Wrong profile mode specified', E_USER_ERROR); - break; - } - - $sql = 'SELECT l.*, f.* - FROM ' . PROFILE_LANG_TABLE . ' l, ' . PROFILE_FIELDS_TABLE . " f - WHERE f.field_active = 1 - $sql_where - AND l.lang_id = $lang_id - AND l.field_id = f.field_id - ORDER BY f.field_order"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - // Return templated field - $tpl_snippet = $this->process_field_row('change', $row); - - // Some types are multivalue, we can't give them a field_id as we would not know which to pick - $type = (int) $row['field_type']; - - phpbb::$template->assign_block_vars('profile_fields', array( - 'LANG_NAME' => $row['lang_name'], - 'LANG_EXPLAIN' => $row['lang_explain'], - 'FIELD' => $tpl_snippet, - 'FIELD_ID' => ($type == FIELD_DATE || ($type == FIELD_BOOL && $row['field_length'] == '1')) ? '' : 'pf_' . $row['field_ident'], - 'S_REQUIRED' => ($row['field_required']) ? true : false, - )); - } - phpbb::$db->sql_freeresult($result); - } - - /** - * Validate entered profile field data - * @access public - */ - public function validate_profile_field($field_type, &$field_value, $field_data) - { - switch ($field_type) - { - case FIELD_INT: - case FIELD_DROPDOWN: - $field_value = (int) $field_value; - break; - - case FIELD_BOOL: - $field_value = (bool) $field_value; - break; - } - - switch ($field_type) - { - case FIELD_DATE: - $field_validate = explode('-', $field_value); - - $day = (isset($field_validate[0])) ? (int) $field_validate[0] : 0; - $month = (isset($field_validate[1])) ? (int) $field_validate[1] : 0; - $year = (isset($field_validate[2])) ? (int) $field_validate[2] : 0; - - if ((!$day || !$month || !$year) && !$field_data['field_required']) - { - return false; - } - - if ((!$day || !$month || !$year) && $field_data['field_required']) - { - return 'FIELD_REQUIRED'; - } - - if ($day < 0 || $day > 31 || $month < 0 || $month > 12 || ($year < 1901 && $year > 0) || $year > gmdate('Y', time()) + 50) - { - return 'FIELD_INVALID_DATE'; - } - - if (checkdate($month, $day, $year) === false) - { - return 'FIELD_INVALID_DATE'; - } - break; - - case FIELD_BOOL: - if (!$field_value && $field_data['field_required']) - { - return 'FIELD_REQUIRED'; - } - break; - - case FIELD_INT: - if (empty($field_value) && !$field_data['field_required']) - { - return false; - } - - if ($field_value < $field_data['field_minlen']) - { - return 'FIELD_TOO_SMALL'; - } - else if ($field_value > $field_data['field_maxlen']) - { - return 'FIELD_TOO_LARGE'; - } - break; - - case FIELD_DROPDOWN: - if ($field_value == $field_data['field_novalue'] && $field_data['field_required']) - { - return 'FIELD_REQUIRED'; - } - break; - - case FIELD_STRING: - case FIELD_TEXT: - if (empty($field_value) && !$field_data['field_required']) - { - return false; - } - else if (empty($field_value) && $field_data['field_required']) - { - return 'FIELD_REQUIRED'; - } - - if ($field_data['field_minlen'] && utf8_strlen($field_value) < $field_data['field_minlen']) - { - return 'FIELD_TOO_SHORT'; - } - else if ($field_data['field_maxlen'] && utf8_strlen($field_value) > $field_data['field_maxlen']) - { - return 'FIELD_TOO_LONG'; - } - - if (!empty($field_data['field_validation']) && $field_data['field_validation'] != '.*') - { - $field_validate = ($field_type == FIELD_STRING) ? $field_value : bbcode_nl2br($field_value); - if (!preg_match('#^' . str_replace('\\\\', '\\', $field_data['field_validation']) . '$#i', $field_validate)) - { - return 'FIELD_INVALID_CHARS'; - } - } - break; - } - - return false; - } - - /** - * Build profile cache, used for display - * @access private - */ - private function build_cache() - { - $this->profile_cache = array(); - - // Display hidden/no_view fields for admin/moderator - $sql = 'SELECT l.*, f.* - FROM ' . PROFILE_LANG_TABLE . ' l, ' . PROFILE_FIELDS_TABLE . ' f - WHERE l.lang_id = ' . phpbb::$user->get_iso_lang_id() . ' - AND f.field_active = 1 ' . - ((!phpbb::$acl->acl_gets('a_', 'm_') && !phpbb::$acl->acl_getf_global('m_')) ? ' AND f.field_hide = 0 ' : '') . ' - AND f.field_no_view = 0 - AND l.field_id = f.field_id - ORDER BY f.field_order'; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $this->profile_cache[$row['field_ident']] = $row; - } - phpbb::$db->sql_freeresult($result); - } - - /** - * Get language entries for options and store them here for later use - */ - private function get_option_lang($field_id, $lang_id, $field_type, $preview) - { - if ($preview) - { - $lang_options = (!is_array($this->vars['lang_options'])) ? explode("\n", $this->vars['lang_options']) : $this->vars['lang_options']; - - // @todo: ref optimize - foreach ($lang_options as $num => $var) - { - $this->options_lang[$field_id][$lang_id][($num + 1)] = $var; - } - } - else - { - $sql = 'SELECT option_id, lang_value - FROM ' . PROFILE_FIELDS_LANG_TABLE . " - WHERE field_id = $field_id - AND lang_id = $lang_id - AND field_type = $field_type - ORDER BY option_id"; - $result = phpbb::$db->sql_query($sql); - - // @todo: ref optimize - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $this->options_lang[$field_id][$lang_id][($row['option_id'] + 1)] = $row['lang_value']; - } - phpbb::$db->sql_freeresult($result); - } - } - - /** - * Submit profile field - * @access public - */ - public function submit_cp_field($mode, $lang_id, &$cp_data, &$cp_error) - { - $sql_where = ''; - switch ($mode) - { - case 'register': - // If the field is required we show it on the registration page and do not show hidden fields - $sql_where .= ' AND (f.field_show_on_reg = 1 OR f.field_required = 1) AND f.field_hide = 0'; - break; - - case 'profile': - // Show hidden fields to moderators/admins - if (!phpbb::$acl->acl_gets('a_', 'm_') && !phpbb::$acl->acl_getf_global('m_')) - { - $sql_where .= ' AND f.field_hide = 0'; - } - break; - - default: - trigger_error('Wrong profile mode specified', E_USER_ERROR); - break; - } - - $sql = 'SELECT l.*, f.* - FROM ' . PROFILE_LANG_TABLE . ' l, ' . PROFILE_FIELDS_TABLE . " f - WHERE l.lang_id = $lang_id - AND f.field_active = 1 - $sql_where - AND l.field_id = f.field_id - ORDER BY f.field_order"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $cp_data['pf_' . $row['field_ident']] = $this->get_profile_field($row); - $check_value = $cp_data['pf_' . $row['field_ident']]; - - if (($cp_result = $this->validate_profile_field($row['field_type'], $check_value, $row)) !== false) - { - // If not and only showing common error messages, use this one - $error = ''; - switch ($cp_result) - { - case 'FIELD_INVALID_DATE': - case 'FIELD_REQUIRED': - $error = sprintf(phpbb::$user->lang[$cp_result], $row['lang_name']); - break; - - case 'FIELD_TOO_SHORT': - case 'FIELD_TOO_SMALL': - $error = sprintf(phpbb::$user->lang[$cp_result], $row['lang_name'], $row['field_minlen']); - break; - - case 'FIELD_TOO_LONG': - case 'FIELD_TOO_LARGE': - $error = sprintf(phpbb::$user->lang[$cp_result], $row['lang_name'], $row['field_maxlen']); - break; - - case 'FIELD_INVALID_CHARS': - switch ($row['field_validation']) - { - case '[0-9]+': - $error = sprintf(phpbb::$user->lang[$cp_result . '_NUMBERS_ONLY'], $row['lang_name']); - break; - - case '[\w]+': - $error = sprintf(phpbb::$user->lang[$cp_result . '_ALPHA_ONLY'], $row['lang_name']); - break; - - case '[\w_\+\. \-\[\]]+': - $error = sprintf(phpbb::$user->lang[$cp_result . '_SPACERS_ONLY'], $row['lang_name']); - break; - } - break; - } - - if ($error != '') - { - $cp_error[] = $error; - } - } - } - phpbb::$db->sql_freeresult($result); - } - - /** - * Assign fields to template, used for viewprofile, viewtopic and memberlist (if load setting is enabled) - * This is directly connected to the user -> mode == grab is to grab the user specific fields, mode == show is for assigning the row to the template - * @access public - */ - public function generate_profile_fields_template($mode, $user_id = 0, $profile_row = false) - { - if ($mode == 'grab') - { - if (!is_array($user_id)) - { - $user_id = array($user_id); - } - - if (!sizeof($this->profile_cache)) - { - $this->build_cache(); - } - - if (!sizeof($user_id)) - { - return array(); - } - - $sql = 'SELECT * - FROM ' . PROFILE_FIELDS_DATA_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('user_id', array_map('intval', $user_id)); - $result = phpbb::$db->sql_query($sql); - - $field_data = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $field_data[$row['user_id']] = $row; - } - phpbb::$db->sql_freeresult($result); - - $user_fields = array(); - - // Go through the fields in correct order - foreach (array_keys($this->profile_cache) as $used_ident) - { - foreach ($field_data as $user_id => $row) - { - $user_fields[$user_id][$used_ident]['value'] = $row['pf_' . $used_ident]; - $user_fields[$user_id][$used_ident]['data'] = $this->profile_cache[$used_ident]; - } - } - - return $user_fields; - } - else if ($mode == 'show') - { - // $profile_row == $user_fields[$row['user_id']]; - $tpl_fields = array(); - $tpl_fields['row'] = $tpl_fields['blockrow'] = array(); - - foreach ($profile_row as $ident => $ident_ary) - { - $value = $this->get_profile_value($ident_ary); - - if ($value === NULL) - { - continue; - } - - $tpl_fields['row'] += array( - 'PROFILE_' . strtoupper($ident) . '_VALUE' => $value, - 'PROFILE_' . strtoupper($ident) . '_TYPE' => $ident_ary['data']['field_type'], - 'PROFILE_' . strtoupper($ident) . '_NAME' => $ident_ary['data']['lang_name'], - 'PROFILE_' . strtoupper($ident) . '_EXPLAIN'=> $ident_ary['data']['lang_explain'], - - 'S_PROFILE_' . strtoupper($ident) => true - ); - - $tpl_fields['blockrow'][] = array( - 'PROFILE_FIELD_VALUE' => $value, - 'PROFILE_FIELD_TYPE' => $ident_ary['data']['field_type'], - 'PROFILE_FIELD_NAME' => $ident_ary['data']['lang_name'], - 'PROFILE_FIELD_EXPLAIN' => $ident_ary['data']['lang_explain'], - - 'S_PROFILE_' . strtoupper($ident) => true - ); - } - - return $tpl_fields; - } - else - { - trigger_error('Wrong mode for custom profile', E_USER_ERROR); - } - } - - /** - * Get Profile Value for display - */ - private function get_profile_value($ident_ary) - { - $value = $ident_ary['value']; - $field_type = $ident_ary['data']['field_type']; - - switch (self::$profile_types[$field_type]) - { - case 'int': - if ($value == '') - { - return NULL; - } - return (int) $value; - break; - - case 'string': - case 'text': - if (!$value) - { - return NULL; - } - - $value = make_clickable($value); - $value = censor_text($value); - $value = bbcode_nl2br($value); - return $value; - break; - - // case 'datetime': - case 'date': - $date = explode('-', $value); - $day = (isset($date[0])) ? (int) $date[0] : 0; - $month = (isset($date[1])) ? (int) $date[1] : 0; - $year = (isset($date[2])) ? (int) $date[2] : 0; - - if (!$day && !$month && !$year) - { - return NULL; - } - else if ($day && $month && $year) - { - // d/m/y 00:00 GMT isn't necessarily on the same d/m/y in the user's timezone, so add the timezone seconds - return phpbb::$user->format_date(gmmktime(0, 0, 0, $month, $day, $year) + phpbb::$user->timezone + phpbb::$user->dst, phpbb::$user->lang['DATE_FORMAT'], true); - } - - return $value; - break; - - case 'dropdown': - $field_id = $ident_ary['data']['field_id']; - $lang_id = $ident_ary['data']['lang_id']; - if (!isset($this->options_lang[$field_id][$lang_id])) - { - $this->get_option_lang($field_id, $lang_id, FIELD_DROPDOWN, false); - } - - if ($value == $ident_ary['data']['field_novalue']) - { - return NULL; - } - - $value = (int) $value; - - // User not having a value assigned - if (!isset($this->options_lang[$field_id][$lang_id][$value])) - { - return NULL; - } - - return $this->options_lang[$field_id][$lang_id][$value]; - break; - - case 'bool': - $field_id = $ident_ary['data']['field_id']; - $lang_id = $ident_ary['data']['lang_id']; - if (!isset($this->options_lang[$field_id][$lang_id])) - { - $this->get_option_lang($field_id, $lang_id, FIELD_BOOL, false); - } - - if ($ident_ary['data']['field_length'] == 1) - { - return (isset($this->options_lang[$field_id][$lang_id][(int) $value])) ? $this->options_lang[$field_id][$lang_id][(int) $value] : NULL; - } - else if (!$value) - { - return NULL; - } - else - { - return $this->options_lang[$field_id][$lang_id][(int) ($value) + 1]; - } - break; - - default: - trigger_error('Unknown profile type', E_USER_ERROR); - break; - } - } - - /** - * Get field value for registration/profile - * @access private - */ - private function get_var($field_validation, &$profile_row, $default_value, $preview) - { - $profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident']; - $user_ident = $profile_row['field_ident']; - // checkbox - only testing for isset - if ($profile_row['field_type'] == FIELD_BOOL && $profile_row['field_length'] == 2) - { - $value = (phpbb_request::is_set($profile_row['field_ident'])) ? true : ((!isset(phpbb::$user->profile_fields[$user_ident]) || $preview) ? $default_value : phpbb::$user->profile_fields[$user_ident]); - } - else if ($profile_row['field_type'] == FIELD_INT) - { - if (phpbb_request::is_set($profile_row['field_ident'])) - { - $value = (request_var($profile_row['field_ident'], '') === '') ? null : request_var($profile_row['field_ident'], $default_value); - } - else - { - if (!$preview && isset(phpbb::$user->profile_fields[$user_ident]) && is_null(phpbb::$user->profile_fields[$user_ident])) - { - $value = null; - } - else if (!isset(phpbb::$user->profile_fields[$user_ident]) || $preview) - { - $value = $default_value; - } - else - { - $value = phpbb::$user->profile_fields[$user_ident]; - } - } - - return (is_null($value)) ? '' : (int) $value; - } - else - { - $value = (phpbb_request::is_set($profile_row['field_ident'])) ? request_var($profile_row['field_ident'], $default_value, true) : ((!isset(phpbb::$user->profile_fields[$user_ident]) || $preview) ? $default_value : phpbb::$user->profile_fields[$user_ident]); - - if (gettype($value) == 'string') - { - $value = utf8_normalize_nfc($value); - } - } - - switch ($field_validation) - { - case 'int': - return (int) $value; - break; - } - - return $value; - } - - /** - * Process int-type - * @access private - */ - private function generate_int($profile_row, $preview = false) - { - $profile_row['field_value'] = $this->get_var('int', $profile_row, $profile_row['field_default_value'], $preview); - phpbb::$template->assign_block_vars(self::$profile_types[$profile_row['field_type']], array_change_key_case($profile_row, CASE_UPPER)); - } - - /** - * Process date-type - * @access private - */ - private function generate_date($profile_row, $preview = false) - { - $profile_row['field_ident'] = (isset($profile_row['var_name'])) ? $profile_row['var_name'] : 'pf_' . $profile_row['field_ident']; - $user_ident = $profile_row['field_ident']; - - $now = getdate(); - - if (!phpbb_request::is_set($profile_row['field_ident'] . '_day')) - { - if ($profile_row['field_default_value'] == 'now') - { - $profile_row['field_default_value'] = sprintf('%2d-%2d-%4d', $now['mday'], $now['mon'], $now['year']); - } - list($day, $month, $year) = explode('-', ((!isset(phpbb::$user->profile_fields[$user_ident]) || $preview) ? $profile_row['field_default_value'] : phpbb::$user->profile_fields[$user_ident])); - } - else - { - if ($preview && $profile_row['field_default_value'] == 'now') - { - $profile_row['field_default_value'] = sprintf('%2d-%2d-%4d', $now['mday'], $now['mon'], $now['year']); - list($day, $month, $year) = explode('-', ((!isset(phpbb::$user->profile_fields[$user_ident]) || $preview) ? $profile_row['field_default_value'] : phpbb::$user->profile_fields[$user_ident])); - } - else - { - $day = request_var($profile_row['field_ident'] . '_day', 0); - $month = request_var($profile_row['field_ident'] . '_month', 0); - $year = request_var($profile_row['field_ident'] . '_year', 0); - } - } - - $profile_row['s_day_options'] = '<option value="0"' . ((!$day) ? ' selected="selected"' : '') . '>--</option>'; - for ($i = 1; $i < 32; $i++) - { - $profile_row['s_day_options'] .= '<option value="' . $i . '"' . (($i == $day) ? ' selected="selected"' : '') . ">$i</option>"; - } - - $profile_row['s_month_options'] = '<option value="0"' . ((!$month) ? ' selected="selected"' : '') . '>--</option>'; - for ($i = 1; $i < 13; $i++) - { - $profile_row['s_month_options'] .= '<option value="' . $i . '"' . (($i == $month) ? ' selected="selected"' : '') . ">$i</option>"; - } - - $profile_row['s_year_options'] = '<option value="0"' . ((!$year) ? ' selected="selected"' : '') . '>--</option>'; - for ($i = $now['year'] - 100; $i <= $now['year'] + 100; $i++) - { - $profile_row['s_year_options'] .= '<option value="' . $i . '"' . (($i == $year) ? ' selected="selected"' : '') . ">$i</option>"; - } - unset($now); - - $profile_row['field_value'] = 0; - phpbb::$template->assign_block_vars(self::$profile_types[$profile_row['field_type']], array_change_key_case($profile_row, CASE_UPPER)); - } - - /** - * Process bool-type - * @access private - */ - private function generate_bool($profile_row, $preview = false) - { - $value = $this->get_var('int', $profile_row, $profile_row['field_default_value'], $preview); - - $profile_row['field_value'] = $value; - phpbb::$template->assign_block_vars(self::$profile_types[$profile_row['field_type']], array_change_key_case($profile_row, CASE_UPPER)); - - if ($profile_row['field_length'] == 1) - { - if (!isset($this->options_lang[$profile_row['field_id']][$profile_row['lang_id']]) || !sizeof($this->options_lang[$profile_row['field_id']][$profile_row['lang_id']])) - { - $this->get_option_lang($profile_row['field_id'], $profile_row['lang_id'], FIELD_BOOL, $preview); - } - - foreach ($this->options_lang[$profile_row['field_id']][$profile_row['lang_id']] as $option_id => $option_value) - { - phpbb::$template->assign_block_vars('bool.options', array( - 'OPTION_ID' => $option_id, - 'CHECKED' => ($value == $option_id) ? ' checked="checked"' : '', - 'VALUE' => $option_value, - )); - } - } - } - - /** - * Process string-type - * @access private - */ - private function generate_string($profile_row, $preview = false) - { - $profile_row['field_value'] = $this->get_var('string', $profile_row, $profile_row['lang_default_value'], $preview); - phpbb::$template->assign_block_vars(self::$profile_types[$profile_row['field_type']], array_change_key_case($profile_row, CASE_UPPER)); - } - - /** - * Process text-type - * @access private - */ - private function generate_text($profile_row, $preview = false) - { - $field_length = explode('|', $profile_row['field_length']); - $profile_row['field_rows'] = $field_length[0]; - $profile_row['field_cols'] = $field_length[1]; - - $profile_row['field_value'] = $this->get_var('string', $profile_row, $profile_row['lang_default_value'], $preview); - phpbb::$template->assign_block_vars(self::$profile_types[$profile_row['field_type']], array_change_key_case($profile_row, CASE_UPPER)); - } - - /** - * Process dropdown-type - * @access private - */ - private function generate_dropdown($profile_row, $preview = false) - { - $value = $this->get_var('int', $profile_row, $profile_row['field_default_value'], $preview); - - if (!isset($this->options_lang[$profile_row['field_id']]) || !isset($this->options_lang[$profile_row['field_id']][$profile_row['lang_id']]) || !sizeof($this->options_lang[$profile_row['field_id']][$profile_row['lang_id']])) - { - $this->get_option_lang($profile_row['field_id'], $profile_row['lang_id'], FIELD_DROPDOWN, $preview); - } - - $profile_row['field_value'] = $value; - phpbb::$template->assign_block_vars(self::$profile_types[$profile_row['field_type']], array_change_key_case($profile_row, CASE_UPPER)); - - foreach ($this->options_lang[$profile_row['field_id']][$profile_row['lang_id']] as $option_id => $option_value) - { - phpbb::$template->assign_block_vars('dropdown.options', array( - 'OPTION_ID' => $option_id, - 'SELECTED' => ($value == $option_id) ? ' selected="selected"' : '', - 'VALUE' => $option_value, - )); - } - } - - /** - * Return Templated value/field. Possible values for $mode are: - * change == user is able to set/enter profile values; preview == just show the value - * @access private - */ - private function process_field_row($mode, $profile_row) - { - $preview = ($mode == 'preview') ? true : false; - - // set template filename - phpbb::$template->set_filenames(array( - 'cp_body' => 'custom_profile_fields.html', - )); - - // empty previously filled blockvars - foreach (self::$profile_types as $field_case => $field_type) - { - phpbb::$template->destroy_block_vars($field_type); - } - - // Assign template variables - $type_func = 'generate_' . self::$profile_types[$profile_row['field_type']]; - $this->$type_func($profile_row, $preview); - - // Return templated data - return phpbb::$template->assign_display('cp_body'); - } - - /** - * Build Array for user insertion into custom profile fields table - */ - public static function build_insert_sql_array($cp_data) - { - $sql_not_in = array(); - foreach ($cp_data as $key => $null) - { - $sql_not_in[] = (strncmp($key, 'pf_', 3) === 0) ? substr($key, 3) : $key; - } - - $sql = 'SELECT f.field_type, f.field_ident, f.field_default_value, l.lang_default_value - FROM ' . PROFILE_LANG_TABLE . ' l, ' . PROFILE_FIELDS_TABLE . ' f - WHERE l.lang_id = ' . phpbb::$user->get_iso_lang_id() . ' - ' . ((sizeof($sql_not_in)) ? ' AND ' . phpbb::$db->sql_in_set('f.field_ident', $sql_not_in, true) : '') . ' - AND l.field_id = f.field_id'; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($row['field_default_value'] == 'now' && $row['field_type'] == FIELD_DATE) - { - $now = getdate(); - $row['field_default_value'] = sprintf('%2d-%2d-%4d', $now['mday'], $now['mon'], $now['year']); - } - - $cp_data['pf_' . $row['field_ident']] = (in_array($row['field_type'], array(FIELD_TEXT, FIELD_STRING))) ? $row['lang_default_value'] : $row['field_default_value']; - } - phpbb::$db->sql_freeresult($result); - - return $cp_data; - } - - /** - * Get profile field value on submit - * @access private - */ - private function get_profile_field($profile_row) - { - $var_name = 'pf_' . $profile_row['field_ident']; - - switch ($profile_row['field_type']) - { - case FIELD_DATE: - - if (!phpbb_request::is_set($var_name . '_day')) - { - if ($profile_row['field_default_value'] == 'now') - { - $now = getdate(); - $profile_row['field_default_value'] = sprintf('%2d-%2d-%4d', $now['mday'], $now['mon'], $now['year']); - } - list($day, $month, $year) = explode('-', $profile_row['field_default_value']); - } - else - { - $day = request_var($var_name . '_day', 0); - $month = request_var($var_name . '_month', 0); - $year = request_var($var_name . '_year', 0); - } - - $var = sprintf('%2d-%2d-%4d', $day, $month, $year); - break; - - case FIELD_BOOL: - // Checkbox - if ($profile_row['field_length'] == 2) - { - $var = phpbb_request::is_set($var_name) ? 1 : 0; - } - else - { - $var = request_var($var_name, (int) $profile_row['field_default_value']); - } - break; - - case FIELD_STRING: - case FIELD_TEXT: - $var = utf8_normalize_nfc(request_var($var_name, (string) $profile_row['field_default_value'], true)); - break; - - case FIELD_INT: - if (phpbb_request::is_set($var_name) && request_var($var_name, '') === '') - { - $var = NULL; - } - else - { - $var = request_var($var_name, (int) $profile_row['field_default_value']); - } - break; - - case FIELD_DROPDOWN: - $var = request_var($var_name, (int) $profile_row['field_default_value']); - break; - - default: - $var = request_var($var_name, $profile_row['field_default_value']); - break; - } - - return $var; - } -} - -/** -* Custom Profile Fields ACP -* @package phpBB3 -*/ -class custom_profile_admin extends custom_profile -{ - public $vars = array(); - - /** - * Return possible validation options - */ - public function validate_options() - { - $validate_ary = array('CHARS_ANY' => '.*', 'NUMBERS_ONLY' => '[0-9]+', 'ALPHA_ONLY' => '[\w]+', 'ALPHA_SPACERS' => '[\w_\+\. \-\[\]]+'); - - $validate_options = ''; - foreach ($validate_ary as $lang => $value) - { - $selected = ($this->vars['field_validation'] == $value) ? ' selected="selected"' : ''; - $validate_options .= '<option value="' . $value . '"' . $selected . '>' . phpbb::$user->lang[$lang] . '</option>'; - } - - return $validate_options; - } - - /** - * Get string options for second step in ACP - */ - public function get_string_options() - { - $options = array( - 0 => array('TITLE' => phpbb::$user->lang['FIELD_LENGTH'], 'FIELD' => '<input type="text" name="field_length" size="5" value="' . $this->vars['field_length'] . '" />'), - 1 => array('TITLE' => phpbb::$user->lang['MIN_FIELD_CHARS'], 'FIELD' => '<input type="text" name="field_minlen" size="5" value="' . $this->vars['field_minlen'] . '" />'), - 2 => array('TITLE' => phpbb::$user->lang['MAX_FIELD_CHARS'], 'FIELD' => '<input type="text" name="field_maxlen" size="5" value="' . $this->vars['field_maxlen'] . '" />'), - 3 => array('TITLE' => phpbb::$user->lang['FIELD_VALIDATION'], 'FIELD' => '<select name="field_validation">' . $this->validate_options() . '</select>') - ); - - return $options; - } - - /** - * Get text options for second step in ACP - */ - public function get_text_options() - { - $options = array( - 0 => array('TITLE' => phpbb::$user->lang['FIELD_LENGTH'], 'FIELD' => '<input name="rows" size="5" value="' . $this->vars['rows'] . '" /> ' . phpbb::$user->lang['ROWS'] . '</dd><dd><input name="columns" size="5" value="' . $this->vars['columns'] . '" /> ' . phpbb::$user->lang['COLUMNS'] . ' <input type="hidden" name="field_length" value="' . $this->vars['field_length'] . '" />'), - 1 => array('TITLE' => phpbb::$user->lang['MIN_FIELD_CHARS'], 'FIELD' => '<input type="text" name="field_minlen" size="10" value="' . $this->vars['field_minlen'] . '" />'), - 2 => array('TITLE' => phpbb::$user->lang['MAX_FIELD_CHARS'], 'FIELD' => '<input type="text" name="field_maxlen" size="10" value="' . $this->vars['field_maxlen'] . '" />'), - 3 => array('TITLE' => phpbb::$user->lang['FIELD_VALIDATION'], 'FIELD' => '<select name="field_validation">' . $this->validate_options() . '</select>') - ); - - return $options; - } - - /** - * Get int options for second step in ACP - */ - public function get_int_options() - { - $options = array( - 0 => array('TITLE' => phpbb::$user->lang['FIELD_LENGTH'], 'FIELD' => '<input type="text" name="field_length" size="5" value="' . $this->vars['field_length'] . '" />'), - 1 => array('TITLE' => phpbb::$user->lang['MIN_FIELD_NUMBER'], 'FIELD' => '<input type="text" name="field_minlen" size="5" value="' . $this->vars['field_minlen'] . '" />'), - 2 => array('TITLE' => phpbb::$user->lang['MAX_FIELD_NUMBER'], 'FIELD' => '<input type="text" name="field_maxlen" size="5" value="' . $this->vars['field_maxlen'] . '" />'), - 3 => array('TITLE' => phpbb::$user->lang['DEFAULT_VALUE'], 'FIELD' => '<input type="post" name="field_default_value" value="' . $this->vars['field_default_value'] . '" />') - ); - - return $options; - } - - /** - * Get bool options for second step in ACP - */ - public function get_bool_options() - { - global $lang_defs; - - $default_lang_id = $lang_defs['iso'][phpbb::$config['default_lang']]; - - $profile_row = array( - 'var_name' => 'field_default_value', - 'field_id' => 1, - 'lang_name' => $this->vars['lang_name'], - 'lang_explain' => $this->vars['lang_explain'], - 'lang_id' => $default_lang_id, - 'field_default_value' => $this->vars['field_default_value'], - 'field_ident' => 'field_default_value', - 'field_type' => FIELD_BOOL, - 'field_length' => $this->vars['field_length'], - 'lang_options' => $this->vars['lang_options'] - ); - - $options = array( - 0 => array('TITLE' => phpbb::$user->lang['FIELD_TYPE'], 'EXPLAIN' => phpbb::$user->lang['BOOL_TYPE_EXPLAIN'], 'FIELD' => '<label><input type="radio" class="radio" name="field_length" value="1"' . (($this->vars['field_length'] == 1) ? ' checked="checked"' : '') . ' onchange="document.getElementById(\'add_profile_field\').submit();" /> ' . phpbb::$user->lang['RADIO_BUTTONS'] . '</label><label><input type="radio" class="radio" name="field_length" value="2"' . (($this->vars['field_length'] == 2) ? ' checked="checked"' : '') . ' onchange="document.getElementById(\'add_profile_field\').submit();" /> ' . phpbb::$user->lang['CHECKBOX'] . '</label>'), - 1 => array('TITLE' => phpbb::$user->lang['DEFAULT_VALUE'], 'FIELD' => $this->process_field_row('preview', $profile_row)) - ); - - return $options; - } - - /** - * Get dropdown options for second step in ACP - */ - public function get_dropdown_options() - { - global $lang_defs; - - $default_lang_id = $lang_defs['iso'][phpbb::$config['default_lang']]; - - $profile_row[0] = array( - 'var_name' => 'field_default_value', - 'field_id' => 1, - 'lang_name' => $this->vars['lang_name'], - 'lang_explain' => $this->vars['lang_explain'], - 'lang_id' => $default_lang_id, - 'field_default_value' => $this->vars['field_default_value'], - 'field_ident' => 'field_default_value', - 'field_type' => FIELD_DROPDOWN, - 'lang_options' => $this->vars['lang_options'] - ); - - $profile_row[1] = $profile_row[0]; - $profile_row[1]['var_name'] = 'field_novalue'; - $profile_row[1]['field_ident'] = 'field_novalue'; - $profile_row[1]['field_default_value'] = $this->vars['field_novalue']; - - $options = array( - 0 => array('TITLE' => phpbb::$user->lang['DEFAULT_VALUE'], 'FIELD' => $this->process_field_row('preview', $profile_row[0])), - 1 => array('TITLE' => phpbb::$user->lang['NO_VALUE_OPTION'], 'EXPLAIN' => phpbb::$user->lang['NO_VALUE_OPTION_EXPLAIN'], 'FIELD' => $this->process_field_row('preview', $profile_row[1])) - ); - - return $options; - } - - /** - * Get date options for second step in ACP - */ - public function get_date_options() - { - global $lang_defs; - - $default_lang_id = $lang_defs['iso'][phpbb::$config['default_lang']]; - - $profile_row = array( - 'var_name' => 'field_default_value', - 'lang_name' => $this->vars['lang_name'], - 'lang_explain' => $this->vars['lang_explain'], - 'lang_id' => $default_lang_id, - 'field_default_value' => $this->vars['field_default_value'], - 'field_ident' => 'field_default_value', - 'field_type' => FIELD_DATE, - 'field_length' => $this->vars['field_length'] - ); - - $always_now = request_var('always_now', -1); - if ($always_now == -1) - { - $s_checked = ($this->vars['field_default_value'] == 'now') ? true : false; - } - else - { - $s_checked = ($always_now) ? true : false; - } - - $options = array( - 0 => array('TITLE' => phpbb::$user->lang['DEFAULT_VALUE'], 'FIELD' => $this->process_field_row('preview', $profile_row)), - 1 => array('TITLE' => phpbb::$user->lang['ALWAYS_TODAY'], 'FIELD' => '<label><input type="radio" class="radio" name="always_now" value="1"' . (($s_checked) ? ' checked="checked"' : '') . ' onchange="document.getElementById(\'add_profile_field\').submit();" /> ' . phpbb::$user->lang['YES'] . '</label><label><input type="radio" class="radio" name="always_now" value="0"' . ((!$s_checked) ? ' checked="checked"' : '') . ' onchange="document.getElementById(\'add_profile_field\').submit();" /> ' . phpbb::$user->lang['NO'] . '</label>'), - ); - - return $options; - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/functions_transfer.php b/phpBB/includes/functions_transfer.php deleted file mode 100644 index 351f9517c5..0000000000 --- a/phpBB/includes/functions_transfer.php +++ /dev/null @@ -1,1010 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -require_once PHPBB_ROOT_PATH . 'includes/libraries/sftp/sftp.' . PHP_EXT; - -/** -* Transfer class, wrapper for ftp/sftp/ssh -* @package phpBB3 -*/ -class transfer -{ - var $connection; - var $host; - var $port; - var $username; - var $password; - var $timeout; - var $root_path; - var $tmp_path; - var $file_perms; - var $dir_perms; - - /** - * Constructor - init some basic values - */ - function __construct() - { - $this->file_perms = 0644; - $this->dir_perms = 0777; - - // We use the store directory as temporary path to circumvent open basedir restrictions - $this->tmp_path = PHPBB_ROOT_PATH . 'store/'; - } - - /** - * Write file to location - */ - public function write_file($destination_file = '', $contents = '') - { - $destination_file = $this->root_path . str_replace(PHPBB_ROOT_PATH, '', $destination_file); - - // need to create a temp file and then move that temp file. - // ftp functions can only move files around and can't create. - // This means that the users will need to have access to write - // temporary files or have write access on a folder within phpBB - // like the cache folder. If the user can't do either, then - // he/she needs to use the fsock ftp method - $temp_name = tempnam($this->tmp_path, 'transfer_'); - @unlink($temp_name); - - $fp = @fopen($temp_name, 'w'); - - if (!$fp) - { - trigger_error('Unable to create temporary file ' . $temp_name, E_USER_ERROR); - } - - @fwrite($fp, $contents); - @fclose($fp); - - $result = $this->overwrite_file($temp_name, $destination_file); - - // remove temporary file now - @unlink($temp_name); - - return $result; - } - - /** - * Moving file into location. If the destination file already exists it gets overwritten - */ - public function overwrite_file($source_file, $destination_file) - { - /** - * @todo generally think about overwriting files in another way, by creating a temporary file and then renaming it - * @todo check for the destination file existance too - */ - $this->_delete($destination_file); - $result = $this->_put($source_file, $destination_file); - $this->_chmod($destination_file, $this->file_perms); - - return $result; - } - - /** - * Create directory structure - */ - public function make_dir($dir) - { - $dir = str_replace(PHPBB_ROOT_PATH, '', $dir); - $dir = explode('/', $dir); - $dirs = ''; - - for ($i = 0, $total = sizeof($dir); $i < $total; $i++) - { - $result = true; - - if (strpos($dir[$i], '.') === 0) - { - continue; - } - $cur_dir = $dir[$i] . '/'; - - if (!file_exists(PHPBB_ROOT_PATH . $dirs . $cur_dir)) - { - // create the directory - $result = $this->_mkdir($dir[$i]); - $this->_chmod($dir[$i], $this->dir_perms); - } - - $this->_chdir($this->root_path . $dirs . $dir[$i]); - $dirs .= $cur_dir; - } - - $this->_chdir($this->root_path); - - /** - * @todo stack result into array to make sure every path creation has been taken care of - */ - return $result; - } - - /** - * Copy file from source location to destination location - */ - public function copy_file($from_loc, $to_loc) - { - $from_loc = ((strpos($from_loc, PHPBB_ROOT_PATH) !== 0) ? PHPBB_ROOT_PATH : '') . $from_loc; - $to_loc = $this->root_path . str_replace(PHPBB_ROOT_PATH, '', $to_loc); - - if (!file_exists($from_loc)) - { - return false; - } - - $result = $this->overwrite_file($from_loc, $to_loc); - - return $result; - } - - /** - * Remove file - */ - public function delete_file($file) - { - $file = $this->root_path . str_replace(PHPBB_ROOT_PATH, '', $file); - - return $this->_delete($file); - } - - /** - * Remove directory - * @todo remove child directories? - */ - public function remove_dir($dir) - { - $dir = $this->root_path . str_replace(PHPBB_ROOT_PATH, '', $dir); - - return $this->_rmdir($dir); - } - - /** - * Rename a file or folder - */ - public function rename($old_handle, $new_handle) - { - $old_handle = $this->root_path . str_replace(PHPBB_ROOT_PATH, '', $old_handle); - - return $this->_rename($old_handle, $new_handle); - } - - /** - * Check if a specified file exist... - */ - public function file_exists($directory, $filename) - { - $directory = $this->root_path . str_replace(PHPBB_ROOT_PATH, '', $directory); - - $this->_chdir($directory); - $result = $this->_ls(''); - - if ($result !== false && is_array($result)) - { - return (in_array($filename, $result)) ? true : false; - } - - return false; - } - - /** - * Open session - */ - public function open_session() - { - return $this->_init(); - } - - /** - * Close current session - */ - public function close_session() - { - return $this->_close(); - } - - /** - * Determine methods able to be used - */ - public static function methods() - { - $methods = array(); - $disabled_functions = explode(',', @ini_get('disable_functions')); - - if (@extension_loaded('ftp')) - { - $methods[] = 'ftp'; - } - - if (!in_array('fsockopen', $disabled_functions)) - { - $methods[] = 'ftp_fsock'; - $methods[] = 'sftp'; - } - - return $methods; - } -} - -/** -* FTP transfer class -* @package phpBB3 -*/ -class ftp extends transfer -{ - /** - * Standard parameters for FTP session - */ - function __construct($host, $username, $password, $root_path, $port = 21, $timeout = 10) - { - $this->host = $host; - $this->port = $port; - $this->username = $username; - $this->password = $password; - $this->timeout = $timeout; - - // Make sure $this->root_path is layed out the same way as the phpbb::$user->page['root_script_path'] value (/ at the end) - $this->root_path = str_replace('\\', '/', $this->root_path); - - if (!empty($root_path)) - { - $this->root_path = (($root_path[0] != '/' ) ? '/' : '') . $root_path . ((substr($root_path, -1, 1) == '/') ? '' : '/'); - } - - // Init some needed values - parent::__construct(); - - return; - } - - /** - * Requests data - */ - public static function data() - { - $root_path = phpbb::$url->realpath(PHPBB_ROOT_PATH); - return array( - 'host' => 'localhost', - 'username' => preg_match('#^/home/([^/]+)#', $root_path, $matches) ? $matches[1] : 'anonymous', - 'password' => '', - 'root_path' => phpbb::$user->page['root_script_path'], - 'port' => 21, - 'timeout' => 10 - ); - } - - /** - * Init FTP Session - * @access private - */ - protected function _init() - { - // connect to the server - $this->connection = @ftp_connect($this->host, $this->port, $this->timeout); - - if (!$this->connection) - { - return 'ERR_CONNECTING_SERVER'; - } - - // attempt to turn pasv mode on - @ftp_pasv($this->connection, true); - - // login to the server - if (!@ftp_login($this->connection, $this->username, $this->password)) - { - return 'ERR_UNABLE_TO_LOGIN'; - } - - // change to the root directory - if (!$this->_chdir($this->root_path)) - { - return 'ERR_CHANGING_DIRECTORY'; - } - - return true; - } - - /** - * Create Directory (MKDIR) - * @access private - */ - protected function _mkdir($dir) - { - return @ftp_mkdir($this->connection, $dir); - } - - /** - * Remove directory (RMDIR) - * @access private - */ - protected function _rmdir($dir) - { - return @ftp_rmdir($this->connection, $dir); - } - - /** - * Rename file - * @access private - */ - protected function _rename($old_handle, $new_handle) - { - return @ftp_rename($this->connection, $old_handle, $new_handle); - } - - /** - * Change current working directory (CHDIR) - * @access private - */ - protected function _chdir($dir = '') - { - if ($dir && $dir !== '/') - { - if (substr($dir, -1, 1) == '/') - { - $dir = substr($dir, 0, -1); - } - } - - return @ftp_chdir($this->connection, $dir); - } - - /** - * change file permissions (CHMOD) - * @access private - */ - protected function _chmod($file, $perms) - { - if (function_exists('ftp_chmod')) - { - $err = @ftp_chmod($this->connection, $perms, $file); - } - else - { - // Unfortunatly CHMOD is not expecting an octal value... - // We need to transform the integer (which was an octal) to an octal representation (to get the int) and then pass as is. ;) - $chmod_cmd = 'CHMOD ' . base_convert($perms, 10, 8) . ' ' . $file; - $err = $this->_site($chmod_cmd); - } - - return $err; - } - - /** - * Upload file to location (PUT) - * @access private - */ - protected function _put($from_file, $to_file) - { - // get the file extension - $file_extension = strtolower(substr(strrchr($to_file, '.'), 1)); - - // We only use the BINARY file mode to cicumvent rewrite actions from ftp server (mostly linefeeds being replaced) - $mode = FTP_BINARY; - - $to_dir = dirname($to_file); - $to_file = basename($to_file); - $this->_chdir($to_dir); - - $result = @ftp_put($this->connection, $to_file, $from_file, $mode); - $this->_chdir($this->root_path); - - return $result; - } - - /** - * Delete file (DELETE) - * @access private - */ - protected function _delete($file) - { - return @ftp_delete($this->connection, $file); - } - - /** - * Close ftp session (CLOSE) - * @access private - */ - protected function _close() - { - if (!$this->connection) - { - return false; - } - - return @ftp_quit($this->connection); - } - - /** - * Return current working directory (CWD) - * At the moment not used by parent class - * @access private - */ - protected function _cwd() - { - return @ftp_pwd($this->connection); - } - - /** - * Return list of files in a given directory (LS) - * @access private - */ - protected function _ls($dir = './') - { - $list = @ftp_nlist($this->connection, $dir); - - // Remove path if prepended - foreach ($list as $key => $item) - { - // Use same separator for item and dir - $item = str_replace('\\', '/', $item); - $dir = str_replace('\\', '/', $dir); - - if (!empty($dir) && strpos($item, $dir) === 0) - { - $item = substr($item, strlen($dir)); - } - - $list[$key] = $item; - } - - return $list; - } - - /** - * FTP SITE command (ftp-only function) - * @access private - */ - private function _site($command) - { - return @ftp_site($this->connection, $command); - } -} - -/** -* FTP fsock transfer class -* -* @author wGEric -* @package phpBB3 -*/ -class ftp_fsock extends transfer -{ - var $data_connection; - - /** - * Standard parameters for FTP session - */ - function __construct($host, $username, $password, $root_path, $port = 21, $timeout = 10) - { - $this->host = $host; - $this->port = $port; - $this->username = $username; - $this->password = $password; - $this->timeout = $timeout; - - // Make sure $this->root_path is layed out the same way as the phpbb::$user->page['root_script_path'] value (/ at the end) - $this->root_path = str_replace('\\', '/', $this->root_path); - - if (!empty($root_path)) - { - $this->root_path = (($root_path[0] != '/' ) ? '/' : '') . $root_path . ((substr($root_path, -1, 1) == '/') ? '' : '/'); - } - - // Init some needed values - parent::__construct(); - - return; - } - - /** - * Requests data - */ - public static function data() - { - $root_path = phpbb::$url->realpath(PHPBB_ROOT_PATH); - return array( - 'host' => 'localhost', - 'username' => preg_match('#^/home/([^/]+)#', $root_path, $matches) ? $matches[1] : 'anonymous', - 'password' => '', - 'root_path' => phpbb::$user->page['root_script_path'], - 'port' => 21, - 'timeout' => 10 - ); - } - - /** - * Init FTP Session - * @access private - */ - protected function _init() - { - $errno = 0; - $errstr = ''; - - // connect to the server - $this->connection = @fsockopen($this->host, $this->port, $errno, $errstr, $this->timeout); - - if (!$this->connection || !$this->_check_command()) - { - return 'ERR_CONNECTING_SERVER'; - } - - @stream_set_timeout($this->connection, $this->timeout); - - // login - if (!$this->_send_command('USER', $this->username)) - { - return 'ERR_UNABLE_TO_LOGIN'; - } - - if (!$this->_send_command('PASS', $this->password)) - { - return 'ERR_UNABLE_TO_LOGIN'; - } - - // change to the root directory - if (!$this->_chdir($this->root_path)) - { - return 'ERR_CHANGING_DIRECTORY'; - } - - return true; - } - - /** - * Create Directory (MKDIR) - * @access private - */ - protected function _mkdir($dir) - { - return $this->_send_command('MKD', $dir); - } - - /** - * Remove directory (RMDIR) - * @access private - */ - protected function _rmdir($dir) - { - return $this->_send_command('RMD', $dir); - } - - /** - * Rename File - * @access private - */ - protected function _rename($old_handle, $new_handle) - { - $this->_send_command('RNFR', $old_handle); - return $this->_send_command('RNTO', $new_handle); - } - - /** - * Change current working directory (CHDIR) - * @access private - */ - protected function _chdir($dir = '') - { - if ($dir && $dir !== '/') - { - if (substr($dir, -1, 1) == '/') - { - $dir = substr($dir, 0, -1); - } - } - - return $this->_send_command('CWD', $dir); - } - - /** - * change file permissions (CHMOD) - * @access private - */ - protected function _chmod($file, $perms) - { - // Unfortunatly CHMOD is not expecting an octal value... - // We need to transform the integer (which was an octal) to an octal representation (to get the int) and then pass as is. ;) - return $this->_send_command('SITE CHMOD', base_convert($perms, 10, 8) . ' ' . $file); - } - - /** - * Upload file to location (PUT) - * @access private - */ - protected function _put($from_file, $to_file) - { - // We only use the BINARY file mode to cicumvent rewrite actions from ftp server (mostly linefeeds being replaced) - // 'I' == BINARY - // 'A' == ASCII - if (!$this->_send_command('TYPE', 'I')) - { - return false; - } - - // open the connection to send file over - if (!$this->_open_data_connection()) - { - return false; - } - - $this->_send_command('STOR', $to_file, false); - - // send the file - $fp = @fopen($from_file, 'rb'); - while (!@feof($fp)) - { - @fwrite($this->data_connection, @fread($fp, 4096)); - } - @fclose($fp); - - // close connection - $this->_close_data_connection(); - - return $this->_check_command(); - } - - /** - * Delete file (DELETE) - * @access private - */ - protected function _delete($file) - { - return $this->_send_command('DELE', $file); - } - - /** - * Close ftp session (CLOSE) - * @access private - */ - protected function _close() - { - if (!$this->connection) - { - return false; - } - - return $this->_send_command('QUIT'); - } - - /** - * Return current working directory (CWD) - * At the moment not used by parent class - * @access private - */ - protected function _cwd() - { - $this->_send_command('PWD', '', false); - return preg_replace('#^[0-9]{3} "(.+)" .+\r\n#', '\\1', $this->_check_command(true)); - } - - /** - * Return list of files in a given directory (LS) - * @access private - */ - protected function _ls($dir = './') - { - if (!$this->_open_data_connection()) - { - return false; - } - - $this->_send_command('NLST', $dir); - - $list = array(); - while (!@feof($this->data_connection)) - { - $list[] = preg_replace('#[\r\n]#', '', @fgets($this->data_connection, 512)); - } - $this->_close_data_connection(); - - // Clear buffer - $this->_check_command(); - - // Remove path if prepended - foreach ($list as $key => $item) - { - // Use same separator for item and dir - $item = str_replace('\\', '/', $item); - $dir = str_replace('\\', '/', $dir); - - if (strpos($item, $dir) === 0) - { - $item = substr($item, strlen($dir)); - } - - $list[$key] = $item; - } - - return $list; - } - - /** - * Send a command to server (FTP fsock only function) - * @access private - */ - private function _send_command($command, $args = '', $check = true) - { - if (!empty($args)) - { - $command = "$command $args"; - } - - fwrite($this->connection, $command . "\r\n"); - - if ($check === true && !$this->_check_command()) - { - return false; - } - - return true; - } - - /** - * Opens a connection to send data (FTP fosck only function) - * @access private - */ - private function _open_data_connection() - { - $this->_send_command('PASV', '', false); - - if (!$ip_port = $this->_check_command(true)) - { - return false; - } - - // open the connection to start sending the file - if (!preg_match('#[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]{1,3},[0-9]+,[0-9]+#', $ip_port, $temp)) - { - // bad ip and port - return false; - } - - $temp = explode(',', $temp[0]); - $server_ip = $temp[0] . '.' . $temp[1] . '.' . $temp[2] . '.' . $temp[3]; - $server_port = $temp[4] * 256 + $temp[5]; - $errno = 0; - $errstr = ''; - - if (!$this->data_connection = @fsockopen($server_ip, $server_port, $errno, $errstr, $this->timeout)) - { - return false; - } - @stream_set_timeout($this->data_connection, $this->timeout); - - return true; - } - - /** - * Closes a connection used to send data - * @access private - */ - private function _close_data_connection() - { - return @fclose($this->data_connection); - } - - /** - * Check to make sure command was successful (FTP fsock only function) - * @access private - */ - private function _check_command($return = false) - { - $response = ''; - - do - { - $result = @fgets($this->connection, 512); - $response .= $result; - } - while (substr($response, 3, 1) != ' '); - - if (!preg_match('#^[123]#', $response)) - { - return false; - } - - return ($return) ? $response : true; - } -} - -/** -* SFTP transfer class -* @package phpBB3 -*/ -class sftp extends transfer -{ - var $current_path; - - /** - * Standard parameters for SFTP session - */ - function __construct($host, $username, $password, $root_path, $port = 22, $timeout = 10) - { - $this->host = $host; - $this->port = $port; - $this->username = $username; - $this->password = $password; - $this->timeout = $timeout; - - // Make sure $this->root_path is layed out the same way as the phpbb::$user->page['root_script_path'] value (/ at the end) - $this->root_path = str_replace('\\', '/', $this->root_path); - - if (!empty($root_path)) - { - $this->root_path = (($root_path[0] != '/' ) ? '/' : '') . $root_path . ((substr($root_path, -1, 1) == '/') ? '' : '/'); - } - - // Init some needed values - parent::__construct(); - - return; - } - - /** - * Requests data - */ - public static function data() - { - $root_path = phpbb::$url->realpath(PHPBB_ROOT_PATH); - return array( - 'host' => 'localhost', - 'username' => preg_match('#^/home/([^/]+)#', $root_path, $matches) ? $matches[1] : 'anonymous', - 'password' => '', - 'root_path' => $root_path, - 'port' => 22, - 'timeout' => 10 - ); - } - /** - * Init SFTP Session - * @access private - */ - protected function _init() - { - // connect to the server - $this->connection = new ssh2_sftp($this->host, $this->port, $this->timeout); - - if (!$this->connection->login($this->username, $this->password)) - { - return 'ERR_CONNECTING_SERVER'; - } - - // change to the root directory - if (!$this->_chdir($this->root_path)) - { - return 'ERR_CHANGING_DIRECTORY'; - } - - return true; - } - - /** - * Create Directory (MKDIR) - * @access private - */ - protected function _mkdir($dir) - { - return $this->connection->mkdir($dir); - } - - /** - * Remove directory (RMDIR) - * @access private - */ - protected function _rmdir($dir) - { - return $this->connection->rmdir($dir); - } - - /** - * Rename File - * @access private - */ - protected function _rename($old_handle, $new_handle) - { - return $this->connection->rename($old_handle, $new_handle); - } - - /** - * Change current working directory (CHDIR) - * @access private - */ - protected function _chdir($dir = '') - { - return $this->connection->chdir($dir); - } - - /** - * change file permissions (CHMOD) - * @access private - */ - protected function _chmod($file, $perms) - { - return $this->connection->chmod($file, $perms); - } - - /** - * Upload file to location (PUT) - * @access private - */ - protected function _put($from_file, $to_file) - { - return $this->connection->put($to_file, $from_file, NET_SFTP_LOCAL_FILE); - } - - /** - * Delete file (DELETE) - * @access private - */ - protected function _delete($file) - { - return $this->connection->delete($file); - } - - /** - * Close ftp session (CLOSE) - * @access private - */ - protected function _close() - { - if (!$this->connection) - { - return false; - } - - return $this->connection->disconnect(); - } - - /** - * Return current working directory (CWD) - * At the moment not used by parent class - * @access private - */ - protected function _cwd() - { - return $this->connection->pwd(); - } - - /** - * Return list of files in a given directory (LS) - * @access private - */ - protected function _ls($dir = './') - { - $list = $this->connection->nlist($dir); - - // Remove path if prepended - foreach ($list as $key => $item) - { - // Use same separator for item and dir - $item = str_replace('\\', '/', $item); - $dir = str_replace('\\', '/', $dir); - - if (strpos($item, $dir) === 0) - { - $item = substr($item, strlen($dir)); - } - - $list[$key] = $item; - } - - return $list; - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/functions_upload.php b/phpBB/includes/functions_upload.php deleted file mode 100644 index 363bfdd768..0000000000 --- a/phpBB/includes/functions_upload.php +++ /dev/null @@ -1,977 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Responsible for holding all file relevant information, as well as doing file-specific operations. -* The {@link fileupload fileupload class} can be used to upload several files, each of them being this object to operate further on. -* @package phpBB3 -*/ -class filespec -{ - var $filename = ''; - var $realname = ''; - var $uploadname = ''; - var $mimetype = ''; - var $extension = ''; - var $filesize = 0; - var $width = 0; - var $height = 0; - var $image_info = array(); - - var $destination_file = ''; - var $destination_path = ''; - - var $file_moved = false; - var $init_error = false; - var $local = false; - - var $error = array(); - - var $upload = ''; - - /** - * File Class - * @access private - */ - function __construct($upload_ary, $upload_namespace) - { - if (!isset($upload_ary)) - { - $this->init_error = true; - return; - } - - $this->filename = $upload_ary['tmp_name']; - $this->filesize = $upload_ary['size']; - $name = trim(htmlspecialchars(basename($upload_ary['name']))); - $this->realname = $this->uploadname = (STRIP) ? stripslashes($name) : $name; - $this->mimetype = $upload_ary['type']; - - // Opera adds the name to the mime type - $this->mimetype = (strpos($this->mimetype, '; name') !== false) ? str_replace(strstr($this->mimetype, '; name'), '', $this->mimetype) : $this->mimetype; - - if (!$this->mimetype) - { - $this->mimetype = 'application/octetstream'; - } - - $this->extension = strtolower($this->get_extension($this->realname)); - - // Try to get real filesize from temporary folder (not always working) ;) - $this->filesize = (@filesize($this->filename)) ? @filesize($this->filename) : $this->filesize; - - $this->width = $this->height = 0; - $this->file_moved = false; - - $this->local = (isset($upload_ary['local_mode'])) ? true : false; - $this->upload = $upload_namespace; - } - - /** - * Cleans destination filename - * - * @param real|unique|unique_ext $mode real creates a realname, filtering some characters, lowering every character. Unique creates an unique filename - * @param string $prefix Prefix applied to filename - * @access public - */ - function clean_filename($mode = 'unique', $prefix = '', $user_id = '') - { - if ($this->init_error) - { - return; - } - - switch ($mode) - { - case 'real': - // Remove every extension from filename (to not let the mime bug being exposed) - if (strpos($this->realname, '.') !== false) - { - $this->realname = substr($this->realname, 0, strpos($this->realname, '.')); - } - - // Replace any chars which may cause us problems with _ - $bad_chars = array("'", "\\", ' ', '/', ':', '*', '?', '"', '<', '>', '|'); - - $this->realname = rawurlencode(str_replace($bad_chars, '_', strtolower($this->realname))); - $this->realname = preg_replace("/%(\w{2})/", '_', $this->realname); - - $this->realname = $prefix . $this->realname . '.' . $this->extension; - break; - - case 'unique': - $this->realname = $prefix . md5(unique_id()); - break; - - case 'avatar': - $this->extension = strtolower($this->extension); - $this->realname = $prefix . $user_id . '.' . $this->extension; - - break; - - case 'unique_ext': - default: - $this->realname = $prefix . md5(unique_id()) . '.' . $this->extension; - break; - } - } - - /** - * Get property from file object - */ - function get($property) - { - if ($this->init_error || !isset($this->$property)) - { - return false; - } - - return $this->$property; - } - - /** - * Check if file is an image (mimetype) - * - * @return true if it is an image, false if not - */ - function is_image() - { - return (strpos($this->mimetype, 'image/') !== false) ? true : false; - } - - /** - * Check if the file got correctly uploaded - * - * @return true if it is a valid upload, false if not - */ - function is_uploaded() - { - if (!$this->local && !is_uploaded_file($this->filename)) - { - return false; - } - - if ($this->local && !file_exists($this->filename)) - { - return false; - } - - return true; - } - - /** - * Remove file - */ - function remove() - { - if ($this->file_moved) - { - @unlink($this->destination_file); - } - } - - /** - * Get file extension - */ - function get_extension($filename) - { - if (strpos($filename, '.') === false) - { - return ''; - } - - $filename = explode('.', $filename); - return array_pop($filename); - } - - /** - * Get mimetype. Utilize mime_content_type if the function exist. - * Not used at the moment... - */ - function get_mimetype($filename) - { - $mimetype = ''; - - if (function_exists('mime_content_type')) - { - $mimetype = mime_content_type($filename); - } - - // Some browsers choke on a mimetype of application/octet-stream - if (!$mimetype || $mimetype == 'application/octet-stream') - { - $mimetype = 'application/octetstream'; - } - - return $mimetype; - } - - /** - * Get filesize - */ - function get_filesize($filename) - { - return @filesize($filename); - } - - - /** - * Check the first 256 bytes for forbidden content - */ - function check_content($disallowed_content) - { - if (empty($disallowed_content)) - { - return true; - } - - $fp = @fopen($this->filename, 'rb'); - - if ($fp !== false) - { - $ie_mime_relevant = fread($fp, 256); - fclose($fp); - foreach ($disallowed_content as $forbidden) - { - if (stripos($ie_mime_relevant, '<' . $forbidden) !== false) - { - return false; - } - } - } - return true; - } - - /** - * Move file to destination folder - * The phpbb_root_path variable will be applied to the destination path - * - * @param string $destination_path Destination path, for example phpbb::$config['avatar_path'] - * @param bool $overwrite If set to true, an already existing file will be overwritten - * @param string $chmod Permission mask for chmodding the file after a successful move. The mode entered here is the octal permission mask. - * - * @access public - */ - function move_file($destination, $overwrite = false, $skip_image_check = false, $chmod = false) - { - if (sizeof($this->error)) - { - return false; - } - - $chmod = ($chmod === false) ? phpbb::CHMOD_READ | phpbb::CHMOD_WRITE : $chmod; - - // We need to trust the admin in specifying valid upload directories and an attacker not being able to overwrite it... - $this->destination_path = PHPBB_ROOT_PATH . $destination; - - // Check if the destination path exist... - if (!file_exists($this->destination_path)) - { - @unlink($this->filename); - return false; - } - - $upload_mode = (@ini_get('open_basedir') || @ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == 'on') ? 'move' : 'copy'; - $upload_mode = ($this->local) ? 'local' : $upload_mode; - $this->destination_file = $this->destination_path . '/' . basename($this->realname); - - // Check if the file already exist, else there is something wrong... - if (file_exists($this->destination_file) && !$overwrite) - { - @unlink($this->filename); - } - else - { - if (file_exists($this->destination_file)) - { - @unlink($this->destination_file); - } - - switch ($upload_mode) - { - case 'copy': - - if (!@copy($this->filename, $this->destination_file)) - { - if (!@move_uploaded_file($this->filename, $this->destination_file)) - { - $this->error[] = sprintf(phpbb::$user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file); - return false; - } - } - - @unlink($this->filename); - - break; - - case 'move': - - if (!@move_uploaded_file($this->filename, $this->destination_file)) - { - if (!@copy($this->filename, $this->destination_file)) - { - $this->error[] = sprintf(phpbb::$user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file); - return false; - } - } - - @unlink($this->filename); - - break; - - case 'local': - - if (!@copy($this->filename, $this->destination_file)) - { - $this->error[] = sprintf(phpbb::$user->lang[$this->upload->error_prefix . 'GENERAL_UPLOAD_ERROR'], $this->destination_file); - return false; - } - @unlink($this->filename); - - break; - } - - phpbb::$system->chmod($this->destination_file, $chmod); - } - - // Try to get real filesize from destination folder - $this->filesize = (@filesize($this->destination_file)) ? @filesize($this->destination_file) : $this->filesize; - - if ($this->is_image() && !$skip_image_check) - { - $this->width = $this->height = 0; - - if (($this->image_info = @getimagesize($this->destination_file)) !== false) - { - $this->width = $this->image_info[0]; - $this->height = $this->image_info[1]; - - if (!empty($this->image_info['mime'])) - { - $this->mimetype = $this->image_info['mime']; - } - - // Check image type - $types = $this->upload->image_types(); - - if (!isset($types[$this->image_info[2]]) || !in_array($this->extension, $types[$this->image_info[2]])) - { - if (!isset($types[$this->image_info[2]])) - { - $this->error[] = sprintf(phpbb::$user->lang['IMAGE_FILETYPE_INVALID'], $this->image_info[2], $this->mimetype); - } - else - { - $this->error[] = sprintf(phpbb::$user->lang['IMAGE_FILETYPE_MISMATCH'], $types[$this->image_info[2]][0], $this->extension); - } - } - - // Make sure the dimensions match a valid image - if (empty($this->width) || empty($this->height)) - { - $this->error[] = phpbb::$user->lang['ATTACHED_IMAGE_NOT_IMAGE']; - } - } - else - { - $this->error[] = phpbb::$user->lang['UNABLE_GET_IMAGE_SIZE']; - } - } - - $this->file_moved = true; - $this->additional_checks(); - unset($this->upload); - - return true; - } - - /** - * Performing additional checks - */ - function additional_checks() - { - if (!$this->file_moved) - { - return false; - } - - // Filesize is too big or it's 0 if it was larger than the maxsize in the upload form - if ($this->upload->max_filesize && ($this->get('filesize') > $this->upload->max_filesize || $this->filesize == 0)) - { - $size_lang = ($this->upload->max_filesize >= 1048576) ? phpbb::$user->lang['MIB'] : (($this->upload->max_filesize >= 1024) ? phpbb::$user->lang['KIB'] : phpbb::$user->lang['BYTES'] ); - $max_filesize = get_formatted_filesize($this->upload->max_filesize, false); - - $this->error[] = sprintf(phpbb::$user->lang[$this->upload->error_prefix . 'WRONG_FILESIZE'], $max_filesize, $size_lang); - - return false; - } - - if (!$this->upload->valid_dimensions($this)) - { - $this->error[] = sprintf(phpbb::$user->lang[$this->upload->error_prefix . 'WRONG_SIZE'], $this->upload->min_width, $this->upload->min_height, $this->upload->max_width, $this->upload->max_height, $this->width, $this->height); - - return false; - } - - return true; - } -} - -/** -* Class for assigning error messages before a real filespec class can be assigned -* -* @package phpBB3 -*/ -class fileerror extends filespec -{ - function fileerror($error_msg) - { - $this->error[] = $error_msg; - } -} - -/** -* File upload class -* Init class (all parameters optional and able to be set/overwritten separately) - scope is global and valid for all uploads -* -* @package phpBB3 -*/ -class fileupload -{ - var $allowed_extensions = array(); - var $disallowed_content = array(); - var $max_filesize = 0; - var $min_width = 0; - var $min_height = 0; - var $max_width = 0; - var $max_height = 0; - var $error_prefix = ''; - - /** - * Init file upload class. - * - * @param string $error_prefix Used error messages will get prefixed by this string - * @param array $allowed_extensions Array of allowed extensions, for example array('jpg', 'jpeg', 'gif', 'png') - * @param int $max_filesize Maximum filesize - * @param int $min_width Minimum image width (only checked for images) - * @param int $min_height Minimum image height (only checked for images) - * @param int $max_width Maximum image width (only checked for images) - * @param int $max_height Maximum image height (only checked for images) - * - */ - function __construct($error_prefix = '', $allowed_extensions = false, $max_filesize = false, $min_width = false, $min_height = false, $max_width = false, $max_height = false, $disallowed_content = false) - { - $this->set_allowed_extensions($allowed_extensions); - $this->set_max_filesize($max_filesize); - $this->set_allowed_dimensions($min_width, $min_height, $max_width, $max_height); - $this->set_error_prefix($error_prefix); - $this->set_disallowed_content($disallowed_content); - } - - /** - * Reset vars - */ - function reset_vars() - { - $this->max_filesize = 0; - $this->min_width = $this->min_height = $this->max_width = $this->max_height = 0; - $this->error_prefix = ''; - $this->allowed_extensions = array(); - $this->disallowed_content = array(); - } - - /** - * Set allowed extensions - */ - function set_allowed_extensions($allowed_extensions) - { - if ($allowed_extensions !== false && is_array($allowed_extensions)) - { - $this->allowed_extensions = $allowed_extensions; - } - } - - /** - * Set allowed dimensions - */ - function set_allowed_dimensions($min_width, $min_height, $max_width, $max_height) - { - $this->min_width = (int) $min_width; - $this->min_height = (int) $min_height; - $this->max_width = (int) $max_width; - $this->max_height = (int) $max_height; - } - - /** - * Set maximum allowed filesize - */ - function set_max_filesize($max_filesize) - { - if ($max_filesize !== false && (int) $max_filesize) - { - $this->max_filesize = (int) $max_filesize; - } - } - - /** - * Set disallowed strings - */ - function set_disallowed_content($disallowed_content) - { - if ($disallowed_content !== false && is_array($disallowed_content)) - { - $this->disallowed_content = $disallowed_content; - } - } - - /** - * Set error prefix - */ - function set_error_prefix($error_prefix) - { - $this->error_prefix = $error_prefix; - } - - /** - * Form upload method - * Upload file from users harddisk - * - * @param string $form_name Form name assigned to the file input field (if it is an array, the key has to be specified) - * @return object $file Object "filespec" is returned, all further operations can be done with this object - * @access public - */ - function form_upload($form_name) - { - unset($_FILES[$form_name]['local_mode']); - $file = new filespec($_FILES[$form_name], $this); - - if ($file->init_error) - { - $file->error[] = ''; - return $file; - } - - // Error array filled? - if (isset($_FILES[$form_name]['error'])) - { - $error = $this->assign_internal_error($_FILES[$form_name]['error']); - - if ($error !== false) - { - $file->error[] = $error; - return $file; - } - } - - // Check if empty file got uploaded (not catched by is_uploaded_file) - if (isset($_FILES[$form_name]['size']) && $_FILES[$form_name]['size'] == 0) - { - $file->error[] = phpbb::$user->lang[$this->error_prefix . 'EMPTY_FILEUPLOAD']; - return $file; - } - - // PHP Upload filesize exceeded - if ($file->get('filename') == 'none') - { - $max_filesize = @ini_get('upload_max_filesize'); - $unit = 'MB'; - - if (!empty($max_filesize)) - { - $unit = strtolower(substr($max_filesize, -1, 1)); - $max_filesize = (int) $max_filesize; - - $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB'); - } - - $file->error[] = (empty($max_filesize)) ? phpbb::$user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : phpbb::$user->lang($this->error_prefix . 'PHP_SIZE_OVERRUN', $max_filesize, phpbb::$user->lang[$unit]); - return $file; - } - - // Not correctly uploaded - if (!$file->is_uploaded()) - { - $file->error[] = phpbb::$user->lang[$this->error_prefix . 'NOT_UPLOADED']; - return $file; - } - - $this->common_checks($file); - - return $file; - } - - /** - * Move file from another location to phpBB - */ - function local_upload($source_file, $filedata = false) - { - $form_name = 'local'; - - $_FILES[$form_name]['local_mode'] = true; - $_FILES[$form_name]['tmp_name'] = $source_file; - - if ($filedata === false) - { - $_FILES[$form_name]['name'] = basename($source_file); - $_FILES[$form_name]['size'] = 0; - $mimetype = ''; - - if (function_exists('mime_content_type')) - { - $mimetype = mime_content_type($source_file); - } - - // Some browsers choke on a mimetype of application/octet-stream - if (!$mimetype || $mimetype == 'application/octet-stream') - { - $mimetype = 'application/octetstream'; - } - - $_FILES[$form_name]['type'] = $mimetype; - } - else - { - $_FILES[$form_name]['name'] = $filedata['realname']; - $_FILES[$form_name]['size'] = $filedata['size']; - $_FILES[$form_name]['type'] = $filedata['type']; - } - - $file = new filespec($_FILES[$form_name], $this); - - if ($file->init_error) - { - $file->error[] = ''; - return $file; - } - - if (isset($_FILES[$form_name]['error'])) - { - $error = $this->assign_internal_error($_FILES[$form_name]['error']); - - if ($error !== false) - { - $file->error[] = $error; - return $file; - } - } - - // PHP Upload filesize exceeded - if ($file->get('filename') == 'none') - { - $max_filesize = @ini_get('upload_max_filesize'); - $unit = 'MB'; - - if (!empty($max_filesize)) - { - $unit = strtolower(substr($max_filesize, -1, 1)); - $max_filesize = (int) $max_filesize; - - $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB'); - } - - $file->error[] = (empty($max_filesize)) ? phpbb::$user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : phpbb::$user->lang($this->error_prefix . 'PHP_SIZE_OVERRUN', $max_filesize, phpbb::$user->lang[$unit]); - return $file; - } - - // Not correctly uploaded - if (!$file->is_uploaded()) - { - $file->error[] = phpbb::$user->lang[$this->error_prefix . 'NOT_UPLOADED']; - return $file; - } - - $this->common_checks($file); - - return $file; - } - - /** - * Remote upload method - * Uploads file from given url - * - * @param string $upload_url URL pointing to file to upload, for example http://www.foobar.com/example.gif - * @return object $file Object "filespec" is returned, all further operations can be done with this object - * @access public - */ - function remote_upload($upload_url) - { - $upload_ary = array(); - $upload_ary['local_mode'] = true; - - if (!preg_match('#^(https?://).*?\.(' . implode('|', $this->allowed_extensions) . ')$#i', $upload_url, $match)) - { - $file = new fileerror(phpbb::$user->lang[$this->error_prefix . 'URL_INVALID']); - return $file; - } - - if (empty($match[2])) - { - $file = new fileerror(phpbb::$user->lang[$this->error_prefix . 'URL_INVALID']); - return $file; - } - - $url = parse_url($upload_url); - - $host = $url['host']; - $path = $url['path']; - $port = (!empty($url['port'])) ? (int) $url['port'] : 80; - - $upload_ary['type'] = 'application/octet-stream'; - - $url['path'] = explode('.', $url['path']); - $ext = array_pop($url['path']); - - $url['path'] = implode('', $url['path']); - $upload_ary['name'] = basename($url['path']) . (($ext) ? '.' . $ext : ''); - $filename = $url['path']; - $filesize = 0; - - $errno = 0; - $errstr = ''; - - if (!($fsock = @fsockopen($host, $port, $errno, $errstr))) - { - $file = new fileerror(phpbb::$user->lang[$this->error_prefix . 'NOT_UPLOADED']); - return $file; - } - - // Make sure $path not beginning with / - if (strpos($path, '/') === 0) - { - $path = substr($path, 1); - } - - fputs($fsock, 'GET /' . $path . " HTTP/1.1\r\n"); - fputs($fsock, "HOST: " . $host . "\r\n"); - fputs($fsock, "Connection: close\r\n\r\n"); - - $get_info = false; - $data = ''; - while (!@feof($fsock)) - { - if ($get_info) - { - $data .= @fread($fsock, 1024); - } - else - { - $line = @fgets($fsock, 1024); - - if ($line == "\r\n") - { - $get_info = true; - } - else - { - if (stripos($line, 'content-type: ') !== false) - { - $upload_ary['type'] = rtrim(str_replace('content-type: ', '', strtolower($line))); - } - else if (stripos($line, '404 not found') !== false) - { - $file = new fileerror(phpbb::$user->lang[$this->error_prefix . 'URL_NOT_FOUND']); - return $file; - } - } - } - } - @fclose($fsock); - - if (empty($data)) - { - $file = new fileerror(phpbb::$user->lang[$this->error_prefix . 'EMPTY_REMOTE_DATA']); - return $file; - } - - $tmp_path = (!@ini_get('safe_mode') || strtolower(@ini_get('safe_mode')) == 'off') ? false : PHPBB_ROOT_PATH . 'cache'; - $filename = tempnam($tmp_path, unique_id() . '-'); - - if (!($fp = @fopen($filename, 'wb'))) - { - $file = new fileerror(phpbb::$user->lang[$this->error_prefix . 'NOT_UPLOADED']); - return $file; - } - - $upload_ary['size'] = fwrite($fp, $data); - fclose($fp); - unset($data); - - $upload_ary['tmp_name'] = $filename; - - $file = new filespec($upload_ary, $this); - $this->common_checks($file); - - return $file; - } - - /** - * Assign internal error - * @access private - */ - function assign_internal_error($errorcode) - { - switch ($errorcode) - { - case 1: - $max_filesize = @ini_get('upload_max_filesize'); - $unit = 'MB'; - - if (!empty($max_filesize)) - { - $unit = strtolower(substr($max_filesize, -1, 1)); - $max_filesize = (int) $max_filesize; - - $unit = ($unit == 'k') ? 'KB' : (($unit == 'g') ? 'GB' : 'MB'); - } - - $error = (empty($max_filesize)) ? phpbb::$user->lang[$this->error_prefix . 'PHP_SIZE_NA'] : phpbb::$user->lang($this->error_prefix . 'PHP_SIZE_OVERRUN', $max_filesize, phpbb::$user->lang[$unit]); - break; - - case 2: - $size_lang = ($this->max_filesize >= 1048576) ? phpbb::$user->lang['MIB'] : (($this->max_filesize >= 1024) ? phpbb::$user->lang['KIB'] : phpbb::$user->lang['BYTES']); - $max_filesize = get_formatted_filesize($this->max_filesize, false); - - $error = sprintf(phpbb::$user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize, $size_lang); - break; - - case 3: - $error = phpbb::$user->lang[$this->error_prefix . 'PARTIAL_UPLOAD']; - break; - - case 4: - $error = phpbb::$user->lang[$this->error_prefix . 'NOT_UPLOADED']; - break; - - case 6: - $error = 'Temporary folder could not be found. Please check your PHP installation.'; - break; - - default: - $error = false; - break; - } - - return $error; - } - - /** - * Perform common checks - */ - function common_checks(&$file) - { - // Filesize is too big or it's 0 if it was larger than the maxsize in the upload form - if ($this->max_filesize && ($file->get('filesize') > $this->max_filesize || $file->get('filesize') == 0)) - { - $size_lang = ($this->max_filesize >= 1048576) ? phpbb::$user->lang['MIB'] : (($this->max_filesize >= 1024) ? phpbb::$user->lang['KIB'] : phpbb::$user->lang['BYTES']); - $max_filesize = get_formatted_filesize($this->max_filesize, false); - - $file->error[] = sprintf(phpbb::$user->lang[$this->error_prefix . 'WRONG_FILESIZE'], $max_filesize, $size_lang); - } - - // check Filename - if (preg_match("#[\\/:*?\"<>|]#i", $file->get('realname'))) - { - $file->error[] = sprintf(phpbb::$user->lang[$this->error_prefix . 'INVALID_FILENAME'], $file->get('realname')); - } - - // Invalid Extension - if (!$this->valid_extension($file)) - { - $file->error[] = sprintf(phpbb::$user->lang[$this->error_prefix . 'DISALLOWED_EXTENSION'], $file->get('extension')); - } - - // MIME Sniffing - if (!$this->valid_content($file)) - { - $file->error[] = sprintf(phpbb::$user->lang[$this->error_prefix . 'DISALLOWED_CONTENT']); - } - } - - /** - * Check for allowed extension - */ - function valid_extension(&$file) - { - return (in_array($file->get('extension'), $this->allowed_extensions)) ? true : false; - } - - /** - * Check for allowed dimension - */ - function valid_dimensions(&$file) - { - if (!$this->max_width && !$this->max_height && !$this->min_width && !$this->min_height) - { - return true; - } - - if (($file->get('width') > $this->max_width && $this->max_width) || - ($file->get('height') > $this->max_height && $this->max_height) || - ($file->get('width') < $this->min_width && $this->min_width) || - ($file->get('height') < $this->min_height && $this->min_height)) - { - return false; - } - - return true; - } - - /** - * Check if form upload is valid - */ - function is_valid($form_name) - { - return (isset($_FILES[$form_name]) && $_FILES[$form_name]['name'] != 'none') ? true : false; - } - - - /** - * Check for allowed extension - */ - function valid_content(&$file) - { - return ($file->check_content($this->disallowed_content)); - } - - /** - * Return image type/extension mapping - */ - function image_types() - { - return array( - 1 => array('gif'), - 2 => array('jpg', 'jpeg'), - 3 => array('png'), - 4 => array('swf'), - 5 => array('psd'), - 6 => array('bmp'), - 7 => array('tif', 'tiff'), - 8 => array('tif', 'tiff'), - 9 => array('jpg', 'jpeg'), - 10 => array('jpg', 'jpeg'), - 11 => array('jpg', 'jpeg'), - 12 => array('jpg', 'jpeg'), - 13 => array('swc'), - 14 => array('iff'), - 15 => array('wbmp'), - 16 => array('xbm'), - ); - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/functions_user.php b/phpBB/includes/functions_user.php deleted file mode 100644 index 5c22cfb4ef..0000000000 --- a/phpBB/includes/functions_user.php +++ /dev/null @@ -1,3247 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Obtain user_ids from usernames or vice versa. Returns false on -* success else the error string -* -* @param array &$user_id_ary The user ids to check or empty if usernames used -* @param array &$username_ary The usernames to check or empty if user ids used -* @param mixed $user_type Array of user types to check, false if not restricting by user type -*/ -function user_get_id_name(&$user_id_ary, &$username_ary, $user_type = false) -{ - // Are both arrays already filled? Yep, return else - // are neither array filled? - if ($user_id_ary && $username_ary) - { - return false; - } - else if (!$user_id_ary && !$username_ary) - { - return 'NO_USERS'; - } - - $which_ary = ($user_id_ary) ? 'user_id_ary' : 'username_ary'; - - if ($$which_ary && !is_array($$which_ary)) - { - $$which_ary = array($$which_ary); - } - - $sql_in = ($which_ary == 'user_id_ary') ? array_map('intval', $$which_ary) : array_map('utf8_clean_string', $$which_ary); - unset($$which_ary); - - $user_id_ary = $username_ary = array(); - - // Grab the user id/username records - $sql_where = ($which_ary == 'user_id_ary') ? 'user_id' : 'username_clean'; - $sql = 'SELECT user_id, username - FROM ' . USERS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set($sql_where, $sql_in); - - if ($user_type !== false && !empty($user_type)) - { - $sql .= ' AND ' . phpbb::$db->sql_in_set('user_type', $user_type); - } - - $result = phpbb::$db->sql_query($sql); - - if (!($row = phpbb::$db->sql_fetchrow($result))) - { - phpbb::$db->sql_freeresult($result); - return 'NO_USERS'; - } - - do - { - $username_ary[$row['user_id']] = $row['username']; - $user_id_ary[] = $row['user_id']; - } - while ($row = phpbb::$db->sql_fetchrow($result)); - phpbb::$db->sql_freeresult($result); - - return false; -} - -/** -* Get latest registered username and update database to reflect it -*/ -function update_last_username() -{ - // Get latest username - $sql = 'SELECT user_id, username, user_colour - FROM ' . USERS_TABLE . ' - WHERE user_type IN (' . phpbb::USER_NORMAL . ', ' . phpbb::USER_FOUNDER . ') - ORDER BY user_id DESC'; - $result = phpbb::$db->sql_query_limit($sql, 1); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ($row) - { - set_config('newest_user_id', $row['user_id'], true); - set_config('newest_username', $row['username'], true); - set_config('newest_user_colour', $row['user_colour'], true); - } -} - -/** -* Updates a username across all relevant tables/fields -* -* @param string $old_name the old/current username -* @param string $new_name the new username -*/ -function user_update_name($old_name, $new_name) -{ - $update_ary = array( - FORUMS_TABLE => array('forum_last_poster_name'), - MODERATOR_CACHE_TABLE => array('username'), - POSTS_TABLE => array('post_username'), - TOPICS_TABLE => array('topic_first_poster_name', 'topic_last_poster_name'), - ); - - foreach ($update_ary as $table => $field_ary) - { - foreach ($field_ary as $field) - { - $sql = "UPDATE $table - SET $field = '" . phpbb::$db->sql_escape($new_name) . "' - WHERE $field = '" . phpbb::$db->sql_escape($old_name) . "'"; - phpbb::$db->sql_query($sql); - } - } - - if (phpbb::$config['newest_username'] == $old_name) - { - set_config('newest_username', $new_name, true); - } - - // Because some tables/caches use username-specific data we need to purge this here. - phpbb::$acm->destroy_sql(MODERATOR_CACHE_TABLE); -} - -/** -* Adds a user -* -* @param mixed $user_row An array containing the following keys (and the appropriate values): username, group_id (the group to place the user in), user_email and the user_type(usually 0). Additional entries not overridden by defaults will be forwarded. -* @param string $cp_data custom profile fields, see custom_profile::build_insert_sql_array -* @return the new user's ID. -*/ -function user_add($user_row, $cp_data = false) -{ - if (empty($user_row['username']) || !isset($user_row['group_id']) || !isset($user_row['user_email']) || !isset($user_row['user_type'])) - { - return false; - } - - $username_clean = utf8_clean_string($user_row['username']); - - if (empty($username_clean)) - { - return false; - } - - $sql_ary = array( - 'username' => $user_row['username'], - 'username_clean' => $username_clean, - 'user_password' => (isset($user_row['user_password'])) ? $user_row['user_password'] : '', - 'user_pass_convert' => 0, - 'user_email' => strtolower($user_row['user_email']), - 'user_email_hash' => hexdec(crc32(strtolower($user_row['user_email'])) . strlen($user_row['user_email'])), - 'group_id' => $user_row['group_id'], - 'user_type' => $user_row['user_type'], - ); - - // These are the additional vars able to be specified - $additional_vars = array( - 'user_permissions' => '', - 'user_timezone' => phpbb::$config['board_timezone'], - 'user_dateformat' => phpbb::$config['default_dateformat'], - 'user_lang' => phpbb::$config['default_lang'], - 'user_style' => phpbb::$config['default_style'], - 'user_actkey' => '', - 'user_ip' => '', - 'user_regdate' => time(), - 'user_passchg' => time(), - 'user_options' => 895, - - 'user_inactive_reason' => 0, - 'user_inactive_time' => 0, - 'user_lastmark' => time(), - 'user_lastvisit' => 0, - 'user_lastpost_time' => 0, - 'user_lastpage' => '', - 'user_posts' => 0, - 'user_dst' => (int) phpbb::$config['board_dst'], - 'user_colour' => '', - 'user_occ' => '', - 'user_interests' => '', - 'user_avatar' => '', - 'user_avatar_type' => 0, - 'user_avatar_width' => 0, - 'user_avatar_height' => 0, - 'user_new_privmsg' => 0, - 'user_unread_privmsg' => 0, - 'user_last_privmsg' => 0, - 'user_message_rules' => 0, - 'user_full_folder' => PRIVMSGS_NO_BOX, - 'user_emailtime' => 0, - - 'user_notify' => 0, - 'user_notify_pm' => 1, - 'user_notify_type' => NOTIFY_EMAIL, - 'user_allow_pm' => 1, - 'user_allow_viewonline' => 1, - 'user_allow_viewemail' => 1, - 'user_allow_massemail' => 1, - - 'user_sig' => '', - 'user_sig_bbcode_uid' => '', - 'user_sig_bbcode_bitfield' => '', - - 'user_form_salt' => phpbb::$security->unique_id(), - ); - - // Now fill the sql array with not required variables - foreach ($additional_vars as $key => $default_value) - { - $sql_ary[$key] = (isset($user_row[$key])) ? $user_row[$key] : $default_value; - } - - // Any additional variables in $user_row not covered above? - $remaining_vars = array_diff(array_keys($user_row), array_keys($sql_ary)); - - // Now fill our sql array with the remaining vars - if (sizeof($remaining_vars)) - { - foreach ($remaining_vars as $key) - { - $sql_ary[$key] = $user_row[$key]; - } - } - - $sql = 'INSERT INTO ' . USERS_TABLE . ' ' . phpbb::$db->sql_build_array('INSERT', $sql_ary); - phpbb::$db->sql_query($sql); - - $user_id = phpbb::$db->sql_nextid(); - - // Insert Custom Profile Fields - if ($cp_data !== false && sizeof($cp_data)) - { - $cp_data['user_id'] = (int) $user_id; - - if (!class_exists('custom_profile')) - { - include_once PHPBB_ROOT_PATH . 'includes/functions_profile_fields.' . PHP_EXT; - } - - $sql = 'INSERT INTO ' . PROFILE_FIELDS_DATA_TABLE . ' ' . - phpbb::$db->sql_build_array('INSERT', custom_profile::build_insert_sql_array($cp_data)); - phpbb::$db->sql_query($sql); - } - - // Place into appropriate group... - $sql = 'INSERT INTO ' . USER_GROUP_TABLE . ' ' . phpbb::$db->sql_build_array('INSERT', array( - 'user_id' => (int) $user_id, - 'group_id' => (int) $user_row['group_id'], - 'user_pending' => 0) - ); - phpbb::$db->sql_query($sql); - - // Now make it the users default group... - group_set_user_default($user_row['group_id'], array($user_id), false); - - // set the newest user and adjust the user count if the user is a normal user and no activation mail is sent - if ($user_row['user_type'] == phpbb::USER_NORMAL) - { - set_config('newest_user_id', $user_id, true); - set_config('newest_username', $user_row['username'], true); - set_config_count('num_users', 1, true); - - $sql = 'SELECT group_colour - FROM ' . GROUPS_TABLE . ' - WHERE group_id = ' . (int) $user_row['group_id']; - $result = phpbb::$db->sql_query_limit($sql, 1); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - set_config('newest_user_colour', $row['group_colour'], true); - } - - return $user_id; -} - -/** -* Remove User -*/ -function user_delete($mode, $user_id, $post_username = false) -{ - $sql = 'SELECT * - FROM ' . USERS_TABLE . ' - WHERE user_id = ' . $user_id; - $result = phpbb::$db->sql_query($sql); - $user_row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if (!$user_row) - { - return false; - } - - // Before we begin, we will remove the reports the user issued. - $sql = 'SELECT r.post_id, p.topic_id - FROM ' . REPORTS_TABLE . ' r, ' . POSTS_TABLE . ' p - WHERE r.user_id = ' . $user_id . ' - AND p.post_id = r.post_id'; - $result = phpbb::$db->sql_query($sql); - - $report_posts = $report_topics = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $report_posts[] = $row['post_id']; - $report_topics[] = $row['topic_id']; - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($report_posts)) - { - $report_posts = array_unique($report_posts); - $report_topics = array_unique($report_topics); - - // Get a list of topics that still contain reported posts - $sql = 'SELECT DISTINCT topic_id - FROM ' . POSTS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('topic_id', $report_topics) . ' - AND post_reported = 1 - AND ' . phpbb::$db->sql_in_set('post_id', $report_posts, true); - $result = phpbb::$db->sql_query($sql); - - $keep_report_topics = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $keep_report_topics[] = $row['topic_id']; - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($keep_report_topics)) - { - $report_topics = array_diff($report_topics, $keep_report_topics); - } - unset($keep_report_topics); - - // Now set the flags back - $sql = 'UPDATE ' . POSTS_TABLE . ' - SET post_reported = 0 - WHERE ' . phpbb::$db->sql_in_set('post_id', $report_posts); - phpbb::$db->sql_query($sql); - - if (sizeof($report_topics)) - { - $sql = 'UPDATE ' . TOPICS_TABLE . ' - SET topic_reported = 0 - WHERE ' . phpbb::$db->sql_in_set('topic_id', $report_topics); - phpbb::$db->sql_query($sql); - } - } - - // Remove reports - phpbb::$db->sql_query('DELETE FROM ' . REPORTS_TABLE . ' WHERE user_id = ' . $user_id); - - if ($user_row['user_avatar'] && $user_row['user_avatar_type'] == AVATAR_UPLOAD) - { - avatar_delete('user', $user_row); - } - - switch ($mode) - { - case 'retain': - - phpbb::$db->sql_transaction('begin'); - - if ($post_username === false) - { - $post_username = phpbb::$user->lang['GUEST']; - } - - // If the user is inactive and newly registered we assume no posts from this user being there... - if ($user_row['user_type'] == phpbb::USER_INACTIVE && $user_row['user_inactive_reason'] == INACTIVE_REGISTER && !$user_row['user_posts']) - { - } - else - { - $sql = 'UPDATE ' . FORUMS_TABLE . ' - SET forum_last_poster_id = ' . ANONYMOUS . ", forum_last_poster_name = '" . phpbb::$db->sql_escape($post_username) . "', forum_last_poster_colour = '' - WHERE forum_last_poster_id = $user_id"; - phpbb::$db->sql_query($sql); - - $sql = 'UPDATE ' . POSTS_TABLE . ' - SET poster_id = ' . ANONYMOUS . ", post_username = '" . phpbb::$db->sql_escape($post_username) . "' - WHERE poster_id = $user_id"; - phpbb::$db->sql_query($sql); - - $sql = 'UPDATE ' . POSTS_TABLE . ' - SET post_edit_user = ' . ANONYMOUS . " - WHERE post_edit_user = $user_id"; - phpbb::$db->sql_query($sql); - - $sql = 'UPDATE ' . TOPICS_TABLE . ' - SET topic_poster = ' . ANONYMOUS . ", topic_first_poster_name = '" . phpbb::$db->sql_escape($post_username) . "', topic_first_poster_colour = '' - WHERE topic_poster = $user_id"; - phpbb::$db->sql_query($sql); - - $sql = 'UPDATE ' . TOPICS_TABLE . ' - SET topic_last_poster_id = ' . ANONYMOUS . ", topic_last_poster_name = '" . phpbb::$db->sql_escape($post_username) . "', topic_last_poster_colour = '' - WHERE topic_last_poster_id = $user_id"; - phpbb::$db->sql_query($sql); - - // Since we change every post by this author, we need to count this amount towards the anonymous user - - // Update the post count for the anonymous user - if ($user_row['user_posts']) - { - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_posts = user_posts + ' . $user_row['user_posts'] . ' - WHERE user_id = ' . ANONYMOUS; - phpbb::$db->sql_query($sql); - } - } - - phpbb::$db->sql_transaction('commit'); - - break; - - case 'remove': - - if (!function_exists('delete_posts')) - { - include(PHPBB_ROOT_PATH . 'includes/functions_admin.' . PHP_EXT); - } - - $sql = 'SELECT topic_id, COUNT(post_id) AS total_posts - FROM ' . POSTS_TABLE . " - WHERE poster_id = $user_id - GROUP BY topic_id"; - $result = phpbb::$db->sql_query($sql); - - $topic_id_ary = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $topic_id_ary[$row['topic_id']] = $row['total_posts']; - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($topic_id_ary)) - { - $sql = 'SELECT topic_id, topic_replies, topic_replies_real - FROM ' . TOPICS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('topic_id', array_keys($topic_id_ary)); - $result = phpbb::$db->sql_query($sql); - - $del_topic_ary = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if (max($row['topic_replies'], $row['topic_replies_real']) + 1 == $topic_id_ary[$row['topic_id']]) - { - $del_topic_ary[] = $row['topic_id']; - } - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($del_topic_ary)) - { - $sql = 'DELETE FROM ' . TOPICS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('topic_id', $del_topic_ary); - phpbb::$db->sql_query($sql); - } - } - - // Delete posts, attachments, etc. - delete_posts('poster_id', $user_id); - - break; - } - - phpbb::$db->sql_transaction('begin'); - - $table_ary = array(USERS_TABLE, USER_GROUP_TABLE, TOPICS_WATCH_TABLE, FORUMS_WATCH_TABLE, ACL_USERS_TABLE, TOPICS_TRACK_TABLE, TOPICS_POSTED_TABLE, FORUMS_TRACK_TABLE, PROFILE_FIELDS_DATA_TABLE, MODERATOR_CACHE_TABLE, DRAFTS_TABLE, BOOKMARKS_TABLE, SESSIONS_KEYS_TABLE); - - foreach ($table_ary as $table) - { - $sql = "DELETE FROM $table - WHERE user_id = $user_id"; - phpbb::$db->sql_query($sql); - } - - phpbb::$acm->destroy_sql(MODERATOR_CACHE_TABLE); - - // Delete the user_id from the banlist - $sql = 'DELETE FROM ' . BANLIST_TABLE . ' - WHERE ban_userid = ' . $user_id; - phpbb::$db->sql_query($sql); - - // Delete the user_id from the session table - $sql = 'DELETE FROM ' . SESSIONS_TABLE . ' - WHERE session_user_id = ' . $user_id; - phpbb::$db->sql_query($sql); - - // Remove any undelivered mails... - $sql = 'SELECT msg_id, user_id - FROM ' . PRIVMSGS_TO_TABLE . ' - WHERE author_id = ' . $user_id . ' - AND folder_id = ' . PRIVMSGS_NO_BOX; - $result = phpbb::$db->sql_query($sql); - - $undelivered_msg = $undelivered_user = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $undelivered_msg[] = $row['msg_id']; - $undelivered_user[$row['user_id']][] = true; - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($undelivered_msg)) - { - $sql = 'DELETE FROM ' . PRIVMSGS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('msg_id', $undelivered_msg); - phpbb::$db->sql_query($sql); - } - - $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . ' - WHERE author_id = ' . $user_id . ' - AND folder_id = ' . PRIVMSGS_NO_BOX; - phpbb::$db->sql_query($sql); - - // Delete all to-information - $sql = 'DELETE FROM ' . PRIVMSGS_TO_TABLE . ' - WHERE user_id = ' . $user_id; - phpbb::$db->sql_query($sql); - - // Set the remaining author id to anonymous - this way users are still able to read messages from users being removed - $sql = 'UPDATE ' . PRIVMSGS_TO_TABLE . ' - SET author_id = ' . ANONYMOUS . ' - WHERE author_id = ' . $user_id; - phpbb::$db->sql_query($sql); - - $sql = 'UPDATE ' . PRIVMSGS_TABLE . ' - SET author_id = ' . ANONYMOUS . ' - WHERE author_id = ' . $user_id; - phpbb::$db->sql_query($sql); - - foreach ($undelivered_user as $_user_id => $ary) - { - if ($_user_id == $user_id) - { - continue; - } - - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_new_privmsg = user_new_privmsg - ' . sizeof($ary) . ', - user_unread_privmsg = user_unread_privmsg - ' . sizeof($ary) . ' - WHERE user_id = ' . $_user_id; - phpbb::$db->sql_query($sql); - } - - phpbb::$db->sql_transaction('commit'); - - // Reset newest user info if appropriate - if (phpbb::$config['newest_user_id'] == $user_id) - { - update_last_username(); - } - - // Decrement number of users if this user is active - if ($user_row['user_type'] != phpbb::USER_INACTIVE && $user_row['user_type'] != phpbb::USER_IGNORE) - { - set_config_count('num_users', -1, true); - } - - return false; -} - -/** -* Flips user_type from active to inactive and vice versa, handles group membership updates -* -* @param string $mode can be flip for flipping from active/inactive, activate or deactivate -*/ -function user_active_flip($mode, $user_id_ary, $reason = INACTIVE_MANUAL) -{ - $deactivated = $activated = 0; - $sql_statements = array(); - - if (!is_array($user_id_ary)) - { - $user_id_ary = array($user_id_ary); - } - - if (!sizeof($user_id_ary)) - { - return; - } - - $sql = 'SELECT user_id, group_id, user_type, user_inactive_reason - FROM ' . USERS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('user_id', $user_id_ary); - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $sql_ary = array(); - - if ($row['user_type'] == phpbb::USER_IGNORE || $row['user_type'] == phpbb::USER_FOUNDER || - ($mode == 'activate' && $row['user_type'] != phpbb::USER_INACTIVE) || - ($mode == 'deactivate' && $row['user_type'] == phpbb::USER_INACTIVE)) - { - continue; - } - - if ($row['user_type'] == phpbb::USER_INACTIVE) - { - $activated++; - } - else - { - $deactivated++; - - // Remove the users session key... - phpbb::$user->reset_login_keys($row['user_id']); - } - - $sql_ary += array( - 'user_type' => ($row['user_type'] == phpbb::USER_NORMAL) ? phpbb::USER_INACTIVE : phpbb::USER_NORMAL, - 'user_inactive_time' => ($row['user_type'] == phpbb::USER_NORMAL) ? time() : 0, - 'user_inactive_reason' => ($row['user_type'] == phpbb::USER_NORMAL) ? $reason : 0, - ); - - $sql_statements[$row['user_id']] = $sql_ary; - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($sql_statements)) - { - foreach ($sql_statements as $user_id => $sql_ary) - { - $sql = 'UPDATE ' . USERS_TABLE . ' - SET ' . phpbb::$db->sql_build_array('UPDATE', $sql_ary) . ' - WHERE user_id = ' . $user_id; - phpbb::$db->sql_query($sql); - } - - phpbb::$acl->acl_clear_prefetch(array_keys($sql_statements)); - } - - if ($deactivated) - { - set_config_count('num_users', $deactivated * (-1), true); - } - - if ($activated) - { - set_config_count('num_users', $activated, true); - } - - // Update latest username - update_last_username(); -} - -/** -* Add a ban or ban exclusion to the banlist. Bans either a user, an IP or an email address -* -* @param string $mode Type of ban. One of the following: user, ip, email -* @param mixed $ban Banned entity. Either string or array with usernames, ips or email addresses -* @param int $ban_len Ban length in minutes -* @param string $ban_len_other Ban length as a date (YYYY-MM-DD) -* @param boolean $ban_exclude Exclude these entities from banning? -* @param string $ban_reason String describing the reason for this ban -* @return boolean -*/ -function user_ban($mode, $ban, $ban_len, $ban_len_other, $ban_exclude, $ban_reason, $ban_give_reason = '') -{ - // Delete stale bans - $sql = 'DELETE FROM ' . BANLIST_TABLE . ' - WHERE ban_end < ' . time() . ' - AND ban_end <> 0'; - phpbb::$db->sql_query($sql); - - $ban_list = (!is_array($ban)) ? array_unique(explode("\n", $ban)) : $ban; - $ban_list_log = implode(', ', $ban_list); - - $current_time = time(); - - // Set $ban_end to the unix time when the ban should end. 0 is a permanent ban. - if ($ban_len) - { - if ($ban_len != -1 || !$ban_len_other) - { - $ban_end = max($current_time, $current_time + ($ban_len) * 60); - } - else - { - $ban_other = explode('-', $ban_len_other); - if (sizeof($ban_other) == 3 && ((int)$ban_other[0] < 9999) && - (strlen($ban_other[0]) == 4) && (strlen($ban_other[1]) == 2) && (strlen($ban_other[2]) == 2)) - { - $ban_end = max($current_time, gmmktime(0, 0, 0, (int)$ban_other[1], (int)$ban_other[2], (int)$ban_other[0])); - } - else - { - trigger_error('LENGTH_BAN_INVALID'); - } - } - } - else - { - $ban_end = 0; - } - - $founder = $founder_names = array(); - - if (!$ban_exclude) - { - // Create a list of founder... - $sql = 'SELECT user_id, user_email, username_clean - FROM ' . USERS_TABLE . ' - WHERE user_type = ' . phpbb::USER_FOUNDER; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $founder[$row['user_id']] = $row['user_email']; - $founder_names[$row['user_id']] = $row['username_clean']; - } - phpbb::$db->sql_freeresult($result); - } - - $banlist_ary = array(); - - switch ($mode) - { - case 'user': - $type = 'ban_userid'; - - // At the moment we do not support wildcard username banning - - // Select the relevant user_ids. - $sql_usernames = array(); - - foreach ($ban_list as $username) - { - $username = trim($username); - if ($username != '') - { - $clean_name = utf8_clean_string($username); - if ($clean_name == phpbb::$user->data['username_clean']) - { - trigger_error('CANNOT_BAN_YOURSELF', E_USER_WARNING); - } - if (in_array($clean_name, $founder_names)) - { - trigger_error('CANNOT_BAN_FOUNDER', E_USER_WARNING); - } - $sql_usernames[] = $clean_name; - } - } - - // Make sure we have been given someone to ban - if (!sizeof($sql_usernames)) - { - trigger_error('NO_USER_SPECIFIED'); - } - - $sql = 'SELECT user_id - FROM ' . USERS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('username_clean', $sql_usernames); - - // Do not allow banning yourself - if (sizeof($founder)) - { - $sql .= ' AND ' . phpbb::$db->sql_in_set('user_id', array_merge(array_keys($founder), array(phpbb::$user->data['user_id'])), true); - } - else - { - $sql .= ' AND user_id <> ' . phpbb::$user->data['user_id']; - } - - $result = phpbb::$db->sql_query($sql); - - if ($row = phpbb::$db->sql_fetchrow($result)) - { - do - { - $banlist_ary[] = (int) $row['user_id']; - } - while ($row = phpbb::$db->sql_fetchrow($result)); - } - else - { - phpbb::$db->sql_freeresult($result); - trigger_error('NO_USERS'); - } - phpbb::$db->sql_freeresult($result); - break; - - case 'ip': - $type = 'ban_ip'; - - foreach ($ban_list as $ban_item) - { - if (preg_match('#^([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})[ ]*\-[ ]*([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})\.([0-9]{1,3})$#', trim($ban_item), $ip_range_explode)) - { - // This is an IP range - // Don't ask about all this, just don't ask ... ! - $ip_1_counter = $ip_range_explode[1]; - $ip_1_end = $ip_range_explode[5]; - - while ($ip_1_counter <= $ip_1_end) - { - $ip_2_counter = ($ip_1_counter == $ip_range_explode[1]) ? $ip_range_explode[2] : 0; - $ip_2_end = ($ip_1_counter < $ip_1_end) ? 254 : $ip_range_explode[6]; - - if ($ip_2_counter == 0 && $ip_2_end == 254) - { - $ip_2_counter = 256; - $ip_2_fragment = 256; - - $banlist_ary[] = "$ip_1_counter.*"; - } - - while ($ip_2_counter <= $ip_2_end) - { - $ip_3_counter = ($ip_2_counter == $ip_range_explode[2] && $ip_1_counter == $ip_range_explode[1]) ? $ip_range_explode[3] : 0; - $ip_3_end = ($ip_2_counter < $ip_2_end || $ip_1_counter < $ip_1_end) ? 254 : $ip_range_explode[7]; - - if ($ip_3_counter == 0 && $ip_3_end == 254) - { - $ip_3_counter = 256; - $ip_3_fragment = 256; - - $banlist_ary[] = "$ip_1_counter.$ip_2_counter.*"; - } - - while ($ip_3_counter <= $ip_3_end) - { - $ip_4_counter = ($ip_3_counter == $ip_range_explode[3] && $ip_2_counter == $ip_range_explode[2] && $ip_1_counter == $ip_range_explode[1]) ? $ip_range_explode[4] : 0; - $ip_4_end = ($ip_3_counter < $ip_3_end || $ip_2_counter < $ip_2_end) ? 254 : $ip_range_explode[8]; - - if ($ip_4_counter == 0 && $ip_4_end == 254) - { - $ip_4_counter = 256; - $ip_4_fragment = 256; - - $banlist_ary[] = "$ip_1_counter.$ip_2_counter.$ip_3_counter.*"; - } - - while ($ip_4_counter <= $ip_4_end) - { - $banlist_ary[] = "$ip_1_counter.$ip_2_counter.$ip_3_counter.$ip_4_counter"; - $ip_4_counter++; - } - $ip_3_counter++; - } - $ip_2_counter++; - } - $ip_1_counter++; - } - } - else if (preg_match('#^([0-9]{1,3})\.([0-9\*]{1,3})\.([0-9\*]{1,3})\.([0-9\*]{1,3})$#', trim($ban_item)) || preg_match('#^[a-f0-9:]+\*?$#i', trim($ban_item))) - { - // Normal IP address - $banlist_ary[] = trim($ban_item); - } - else if (preg_match('#^\*$#', trim($ban_item))) - { - // Ban all IPs - $banlist_ary[] = '*'; - } - else if (preg_match('#^([\w\-_]\.?){2,}$#is', trim($ban_item))) - { - // hostname - $ip_ary = gethostbynamel(trim($ban_item)); - - if (!empty($ip_ary)) - { - foreach ($ip_ary as $ip) - { - if ($ip) - { - if (strlen($ip) > 40) - { - continue; - } - - $banlist_ary[] = $ip; - } - } - } - } - else - { - trigger_error('NO_IPS_DEFINED'); - } - } - break; - - case 'email': - $type = 'ban_email'; - - foreach ($ban_list as $ban_item) - { - $ban_item = trim($ban_item); - - if (preg_match('#^.*?@*|(([a-z0-9\-]+\.)+([a-z]{2,3}))$#i', $ban_item)) - { - if (strlen($ban_item) > 100) - { - continue; - } - - if (!sizeof($founder) || !in_array($ban_item, $founder)) - { - $banlist_ary[] = $ban_item; - } - } - } - - if (sizeof($ban_list) == 0) - { - trigger_error('NO_EMAILS_DEFINED'); - } - break; - - default: - trigger_error('NO_MODE'); - break; - } - - // Fetch currently set bans of the specified type and exclude state. Prevent duplicate bans. - $sql_where = ($type == 'ban_userid') ? 'ban_userid <> 0' : "$type <> ''"; - - $sql = "SELECT $type - FROM " . BANLIST_TABLE . " - WHERE $sql_where - AND ban_exclude = " . (int) $ban_exclude; - $result = phpbb::$db->sql_query($sql); - - // Reset $sql_where, because we use it later... - $sql_where = ''; - - if ($row = phpbb::$db->sql_fetchrow($result)) - { - $banlist_ary_tmp = array(); - do - { - switch ($mode) - { - case 'user': - $banlist_ary_tmp[] = $row['ban_userid']; - break; - - case 'ip': - $banlist_ary_tmp[] = $row['ban_ip']; - break; - - case 'email': - $banlist_ary_tmp[] = $row['ban_email']; - break; - } - } - while ($row = phpbb::$db->sql_fetchrow($result)); - - $banlist_ary = array_unique(array_diff($banlist_ary, $banlist_ary_tmp)); - unset($banlist_ary_tmp); - } - phpbb::$db->sql_freeresult($result); - - // We have some entities to ban - if (sizeof($banlist_ary)) - { - $sql_ary = array(); - - foreach ($banlist_ary as $ban_entry) - { - $sql_ary[] = array( - $type => $ban_entry, - 'ban_start' => (int) $current_time, - 'ban_end' => (int) $ban_end, - 'ban_exclude' => (int) $ban_exclude, - 'ban_reason' => (string) $ban_reason, - 'ban_give_reason' => (string) $ban_give_reason, - ); - } - - phpbb::$db->sql_multi_insert(BANLIST_TABLE, $sql_ary); - - // If we are banning we want to logout anyone matching the ban - if (!$ban_exclude) - { - switch ($mode) - { - case 'user': - $sql_where = 'WHERE ' . phpbb::$db->sql_in_set('session_user_id', $banlist_ary); - break; - - case 'ip': - $sql_where = 'WHERE ' . phpbb::$db->sql_in_set('session_ip', $banlist_ary); - break; - - case 'email': - $banlist_ary_sql = array(); - - foreach ($banlist_ary as $ban_entry) - { - $banlist_ary_sql[] = (string) str_replace('*', '%', $ban_entry); - } - - $sql = 'SELECT user_id - FROM ' . USERS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('user_email', $banlist_ary_sql); - $result = phpbb::$db->sql_query($sql); - - $sql_in = array(); - - if ($row = phpbb::$db->sql_fetchrow($result)) - { - do - { - $sql_in[] = $row['user_id']; - } - while ($row = phpbb::$db->sql_fetchrow($result)); - - $sql_where = 'WHERE ' . phpbb::$db->sql_in_set('session_user_id', $sql_in); - } - phpbb::$db->sql_freeresult($result); - break; - } - - if (isset($sql_where) && $sql_where) - { - $sql = 'DELETE FROM ' . SESSIONS_TABLE . " - $sql_where"; - phpbb::$db->sql_query($sql); - - if ($mode == 'user') - { - $sql = 'DELETE FROM ' . SESSIONS_KEYS_TABLE . ' ' . ((in_array('*', $banlist_ary)) ? '' : 'WHERE ' . phpbb::$db->sql_in_set('user_id', $banlist_ary)); - phpbb::$db->sql_query($sql); - } - } - } - - // Update log - $log_entry = ($ban_exclude) ? 'LOG_BAN_EXCLUDE_' : 'LOG_BAN_'; - - // Add to moderator and admin log - add_log('admin', $log_entry . strtoupper($mode), $ban_reason, $ban_list_log); - add_log('mod', 0, 0, $log_entry . strtoupper($mode), $ban_reason, $ban_list_log); - - phpbb::$acm->destroy_sql(BANLIST_TABLE); - - return true; - } - - // There was nothing to ban/exclude. But destroying the cache because of the removal of stale bans. - phpbb::$acm->destroy_sql(BANLIST_TABLE); - - return false; -} - -/** -* Unban User -*/ -function user_unban($mode, $ban) -{ - // Delete stale bans - $sql = 'DELETE FROM ' . BANLIST_TABLE . ' - WHERE ban_end < ' . time() . ' - AND ban_end <> 0'; - phpbb::$db->sql_query($sql); - - if (!is_array($ban)) - { - $ban = array($ban); - } - - $unban_sql = array_map('intval', $ban); - - if (sizeof($unban_sql)) - { - // Grab details of bans for logging information later - switch ($mode) - { - case 'user': - $sql = 'SELECT u.username AS unban_info - FROM ' . USERS_TABLE . ' u, ' . BANLIST_TABLE . ' b - WHERE ' . phpbb::$db->sql_in_set('b.ban_id', $unban_sql) . ' - AND u.user_id = b.ban_userid'; - break; - - case 'email': - $sql = 'SELECT ban_email AS unban_info - FROM ' . BANLIST_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('ban_id', $unban_sql); - break; - - case 'ip': - $sql = 'SELECT ban_ip AS unban_info - FROM ' . BANLIST_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('ban_id', $unban_sql); - break; - } - $result = phpbb::$db->sql_query($sql); - - $l_unban_list = ''; - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $l_unban_list .= (($l_unban_list != '') ? ', ' : '') . $row['unban_info']; - } - phpbb::$db->sql_freeresult($result); - - $sql = 'DELETE FROM ' . BANLIST_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('ban_id', $unban_sql); - phpbb::$db->sql_query($sql); - - // Add to moderator and admin log - add_log('admin', 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list); - add_log('mod', 0, 0, 'LOG_UNBAN_' . strtoupper($mode), $l_unban_list); - } - - phpbb::$acm->destroy_sql(BANLIST_TABLE); - - return false; -} - -/** -* Whois facility -* -* @link http://tools.ietf.org/html/rfc3912 RFC3912: WHOIS Protocol Specification -*/ -function user_ipwhois($ip) -{ - $ipwhois = ''; - - // Check IP - // Only supporting IPv4 at the moment... - if (empty($ip) || !preg_match(get_preg_expression('ipv4'), $ip)) - { - return ''; - } - - if (($fsk = @fsockopen('whois.arin.net', 43))) - { - // CRLF as per RFC3912 - fputs($fsk, "$ip\r\n"); - while (!feof($fsk)) - { - $ipwhois .= fgets($fsk, 1024); - } - @fclose($fsk); - } - - $match = array(); - - // Test for referrals from ARIN to other whois databases, roll on rwhois - if (preg_match('#ReferralServer: whois://(.+)#im', $ipwhois, $match)) - { - if (strpos($match[1], ':') !== false) - { - $pos = strrpos($match[1], ':'); - $server = substr($match[1], 0, $pos); - $port = (int) substr($match[1], $pos + 1); - unset($pos); - } - else - { - $server = $match[1]; - $port = 43; - } - - $buffer = ''; - - if (($fsk = @fsockopen($server, $port))) - { - fputs($fsk, "$ip\r\n"); - while (!feof($fsk)) - { - $buffer .= fgets($fsk, 1024); - } - @fclose($fsk); - } - - // Use the result from ARIN if we don't get any result here - $ipwhois = (empty($buffer)) ? $ipwhois : $buffer; - } - - $ipwhois = htmlspecialchars($ipwhois); - - // Magic URL ;) - return trim(make_clickable($ipwhois, false, '')); -} - -/** -* Data validation ... used primarily but not exclusively by ucp modules -* -* "Master" function for validating a range of data types -*/ -function validate_data($data, $val_ary) -{ - $error = array(); - - foreach ($val_ary as $var => $val_seq) - { - if (!is_array($val_seq[0])) - { - $val_seq = array($val_seq); - } - - foreach ($val_seq as $validate) - { - $function = array_shift($validate); - array_unshift($validate, $data[$var]); - - if ($result = call_user_func_array('validate_' . $function, $validate)) - { - // Since errors are checked later for their language file existence, we need to make sure custom errors are not adjusted. - $error[] = (empty(phpbb::$user->lang[$result . '_' . strtoupper($var)])) ? $result : $result . '_' . strtoupper($var); - } - } - } - - return $error; -} - -/** -* Validate String -* -* @return boolean|string Either false if validation succeeded or a string which will be used as the error message (with the variable name appended) -*/ -function validate_string($string, $optional = false, $min = 0, $max = 0) -{ - if (empty($string) && $optional) - { - return false; - } - - if ($min && utf8_strlen(htmlspecialchars_decode($string)) < $min) - { - return 'TOO_SHORT'; - } - else if ($max && utf8_strlen(htmlspecialchars_decode($string)) > $max) - { - return 'TOO_LONG'; - } - - return false; -} - -/** -* Validate Number -* -* @return boolean|string Either false if validation succeeded or a string which will be used as the error message (with the variable name appended) -*/ -function validate_num($num, $optional = false, $min = 0, $max = 1E99) -{ - if (empty($num) && $optional) - { - return false; - } - - if ($num < $min) - { - return 'TOO_SMALL'; - } - else if ($num > $max) - { - return 'TOO_LARGE'; - } - - return false; -} - -/** -* Validate Date -* @param String $string a date in the dd-mm-yyyy format -* @return boolean -*/ -function validate_date($date_string, $optional = false) -{ - $date = explode('-', $date_string); - if ((empty($date) || sizeof($date) != 3) && $optional) - { - return false; - } - else if ($optional) - { - for ($field = 0; $field <= 1; $field++) - { - $date[$field] = (int) $date[$field]; - if (empty($date[$field])) - { - $date[$field] = 1; - } - } - $date[2] = (int) $date[2]; - // assume an arbitrary leap year - if (empty($date[2])) - { - $date[2] = 1980; - } - } - - if (sizeof($date) != 3 || !checkdate($date[1], $date[0], $date[2])) - { - return 'INVALID'; - } - - return false; -} - - -/** -* Validate Match -* -* @return boolean|string Either false if validation succeeded or a string which will be used as the error message (with the variable name appended) -*/ -function validate_match($string, $optional = false, $match = '') -{ - if (empty($string) && $optional) - { - return false; - } - - if (empty($match)) - { - return false; - } - - if (!preg_match($match, $string)) - { - return 'WRONG_DATA'; - } - - return false; -} - -/** -* Check to see if the username has been taken, or if it is disallowed. -* Also checks if it includes the " character, which we don't allow in usernames. -* Used for registering, changing names, and posting anonymously with a username -* -* @param string $username The username to check -* @param string $allowed_username An allowed username, default being phpbb::$user->data['username'] -* -* @return mixed Either false if validation succeeded or a string which will be used as the error message (with the variable name appended) -*/ -function validate_username($username, $allowed_username = false) -{ - $clean_username = utf8_clean_string($username); - $allowed_username = ($allowed_username === false) ? phpbb::$user->data['username_clean'] : utf8_clean_string($allowed_username); - - if ($allowed_username == $clean_username) - { - return false; - } - - // ... fast checks first. - if (strpos($username, '"') !== false || strpos($username, '"') !== false || empty($clean_username)) - { - return 'INVALID_CHARS'; - } - - $mbstring = $pcre = false; - - // generic UTF-8 character types supported - switch (phpbb::$config['allow_name_chars']) - { - case 'USERNAME_CHARS_ANY': - $regex = '.+'; - break; - - case 'USERNAME_ALPHA_ONLY': - $regex = '[A-Za-z0-9]+'; - break; - - case 'USERNAME_ALPHA_SPACERS': - $regex = '[A-Za-z0-9-[\]_+ ]+'; - break; - - case 'USERNAME_LETTER_NUM': - $regex = '[\p{Lu}\p{Ll}\p{N}]+'; - break; - - case 'USERNAME_LETTER_NUM_SPACERS': - $regex = '[-\]_+ [\p{Lu}\p{Ll}\p{N}]+'; - break; - - case 'USERNAME_ASCII': - default: - $regex = '[\x01-\x7F]+'; - break; - } - - if (!preg_match('#^' . $regex . '$#u', $username)) - { - return 'INVALID_CHARS'; - } - - $sql = 'SELECT username - FROM ' . USERS_TABLE . " - WHERE username_clean = '" . phpbb::$db->sql_escape($clean_username) . "'"; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ($row) - { - return 'USERNAME_TAKEN'; - } - - $sql = 'SELECT group_name - FROM ' . GROUPS_TABLE . " - WHERE group_name = '" . phpbb::$db->sql_escape($clean_username) . "'"; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ($row) - { - return 'USERNAME_TAKEN'; - } - - $bad_usernames = phpbb_cache::obtain_disallowed_usernames(); - - foreach ($bad_usernames as $bad_username) - { - if (preg_match('#^' . $bad_username . '$#', $clean_username)) - { - return 'USERNAME_DISALLOWED'; - } - } - - return false; -} - -/** -* Check to see if the password meets the complexity settings -* -* @return boolean|string Either false if validation succeeded or a string which will be used as the error message (with the variable name appended) -*/ -function validate_password($password) -{ - if (!$password) - { - return false; - } - - // generic UTF-8 character types supported - $upp = '\p{Lu}'; - $low = '\p{Ll}'; - $let = '\p{L}'; - $num = '\p{N}'; - $sym = '[^\p{Lu}\p{Ll}\p{N}]'; - - $chars = array(); - - switch (phpbb::$config['pass_complex']) - { - case 'PASS_TYPE_CASE': - $chars[] = $low; - $chars[] = $upp; - break; - - case 'PASS_TYPE_ALPHA': - $chars[] = $let; - $chars[] = $num; - break; - - case 'PASS_TYPE_SYMBOL': - $chars[] = $low; - $chars[] = $upp; - $chars[] = $num; - $chars[] = $sym; - break; - } - - if ($pcre) - { - foreach ($chars as $char) - { - if (!preg_match('#' . $char . '#u', $password)) - { - return 'INVALID_CHARS'; - } - } - } - else if ($mbstring) - { - foreach ($chars as $char) - { - if (mb_ereg($char, $password) === false) - { - return 'INVALID_CHARS'; - } - } - } - - return false; -} - -/** -* Check to see if email address is banned or already present in the DB -* -* @param string $email The email to check -* @param string $allowed_email An allowed email, default being phpbb::$user->data['user_email'] -* -* @return mixed Either false if validation succeeded or a string which will be used as the error message (with the variable name appended) -*/ -function validate_email($email, $allowed_email = false) -{ - $email = strtolower($email); - $allowed_email = ($allowed_email === false) ? strtolower(phpbb::$user->data['user_email']) : strtolower($allowed_email); - - if ($allowed_email == $email) - { - return false; - } - - if (!preg_match('/^' . get_preg_expression('email') . '$/i', $email)) - { - return 'EMAIL_INVALID'; - } - - // Check MX record. - // The idea for this is from reading the UseBB blog/announcement. :) - if (phpbb::$config['email_check_mx']) - { - list(, $domain) = explode('@', $email); - - if (phpbb_checkdnsrr($domain, 'A') === false && phpbb_checkdnsrr($domain, 'MX') === false) - { - return 'DOMAIN_NO_MX_RECORD'; - } - } - - if (($ban_reason = phpbb::$user->check_ban(false, false, $email, true)) !== false) - { - return ($ban_reason === true) ? 'EMAIL_BANNED' : $ban_reason; - } - - if (!phpbb::$config['allow_emailreuse']) - { - $sql = 'SELECT user_email_hash - FROM ' . USERS_TABLE . " - WHERE user_email_hash = " . hexdec(crc32($email) . strlen($email)); - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ($row) - { - return 'EMAIL_TAKEN'; - } - } - - return false; -} - -/** -* Validate jabber address -* Taken from the jabber class within flyspray (see author notes) -* -* @author flyspray.org -*/ -function validate_jabber($jid) -{ - if (!$jid) - { - return false; - } - - $seperator_pos = strpos($jid, '@'); - - if ($seperator_pos === false) - { - return 'WRONG_DATA'; - } - - $username = substr($jid, 0, $seperator_pos); - $realm = substr($jid, $seperator_pos + 1); - - if (strlen($username) == 0 || strlen($realm) < 3) - { - return 'WRONG_DATA'; - } - - $arr = explode('.', $realm); - - if (sizeof($arr) == 0) - { - return 'WRONG_DATA'; - } - - foreach ($arr as $part) - { - if (substr($part, 0, 1) == '-' || substr($part, -1, 1) == '-') - { - return 'WRONG_DATA'; - } - - if (!preg_match("@^[a-zA-Z0-9-.]+$@", $part)) - { - return 'WRONG_DATA'; - } - } - - $boundary = array(array(0, 127), array(192, 223), array(224, 239), array(240, 247), array(248, 251), array(252, 253)); - - // Prohibited Characters RFC3454 + RFC3920 - $prohibited = array( - // Table C.1.1 - array(0x0020, 0x0020), // SPACE - // Table C.1.2 - array(0x00A0, 0x00A0), // NO-BREAK SPACE - array(0x1680, 0x1680), // OGHAM SPACE MARK - array(0x2000, 0x2001), // EN QUAD - array(0x2001, 0x2001), // EM QUAD - array(0x2002, 0x2002), // EN SPACE - array(0x2003, 0x2003), // EM SPACE - array(0x2004, 0x2004), // THREE-PER-EM SPACE - array(0x2005, 0x2005), // FOUR-PER-EM SPACE - array(0x2006, 0x2006), // SIX-PER-EM SPACE - array(0x2007, 0x2007), // FIGURE SPACE - array(0x2008, 0x2008), // PUNCTUATION SPACE - array(0x2009, 0x2009), // THIN SPACE - array(0x200A, 0x200A), // HAIR SPACE - array(0x200B, 0x200B), // ZERO WIDTH SPACE - array(0x202F, 0x202F), // NARROW NO-BREAK SPACE - array(0x205F, 0x205F), // MEDIUM MATHEMATICAL SPACE - array(0x3000, 0x3000), // IDEOGRAPHIC SPACE - // Table C.2.1 - array(0x0000, 0x001F), // [CONTROL CHARACTERS] - array(0x007F, 0x007F), // DELETE - // Table C.2.2 - array(0x0080, 0x009F), // [CONTROL CHARACTERS] - array(0x06DD, 0x06DD), // ARABIC END OF AYAH - array(0x070F, 0x070F), // SYRIAC ABBREVIATION MARK - array(0x180E, 0x180E), // MONGOLIAN VOWEL SEPARATOR - array(0x200C, 0x200C), // ZERO WIDTH NON-JOINER - array(0x200D, 0x200D), // ZERO WIDTH JOINER - array(0x2028, 0x2028), // LINE SEPARATOR - array(0x2029, 0x2029), // PARAGRAPH SEPARATOR - array(0x2060, 0x2060), // WORD JOINER - array(0x2061, 0x2061), // FUNCTION APPLICATION - array(0x2062, 0x2062), // INVISIBLE TIMES - array(0x2063, 0x2063), // INVISIBLE SEPARATOR - array(0x206A, 0x206F), // [CONTROL CHARACTERS] - array(0xFEFF, 0xFEFF), // ZERO WIDTH NO-BREAK SPACE - array(0xFFF9, 0xFFFC), // [CONTROL CHARACTERS] - array(0x1D173, 0x1D17A), // [MUSICAL CONTROL CHARACTERS] - // Table C.3 - array(0xE000, 0xF8FF), // [PRIVATE USE, PLANE 0] - array(0xF0000, 0xFFFFD), // [PRIVATE USE, PLANE 15] - array(0x100000, 0x10FFFD), // [PRIVATE USE, PLANE 16] - // Table C.4 - array(0xFDD0, 0xFDEF), // [NONCHARACTER CODE POINTS] - array(0xFFFE, 0xFFFF), // [NONCHARACTER CODE POINTS] - array(0x1FFFE, 0x1FFFF), // [NONCHARACTER CODE POINTS] - array(0x2FFFE, 0x2FFFF), // [NONCHARACTER CODE POINTS] - array(0x3FFFE, 0x3FFFF), // [NONCHARACTER CODE POINTS] - array(0x4FFFE, 0x4FFFF), // [NONCHARACTER CODE POINTS] - array(0x5FFFE, 0x5FFFF), // [NONCHARACTER CODE POINTS] - array(0x6FFFE, 0x6FFFF), // [NONCHARACTER CODE POINTS] - array(0x7FFFE, 0x7FFFF), // [NONCHARACTER CODE POINTS] - array(0x8FFFE, 0x8FFFF), // [NONCHARACTER CODE POINTS] - array(0x9FFFE, 0x9FFFF), // [NONCHARACTER CODE POINTS] - array(0xAFFFE, 0xAFFFF), // [NONCHARACTER CODE POINTS] - array(0xBFFFE, 0xBFFFF), // [NONCHARACTER CODE POINTS] - array(0xCFFFE, 0xCFFFF), // [NONCHARACTER CODE POINTS] - array(0xDFFFE, 0xDFFFF), // [NONCHARACTER CODE POINTS] - array(0xEFFFE, 0xEFFFF), // [NONCHARACTER CODE POINTS] - array(0xFFFFE, 0xFFFFF), // [NONCHARACTER CODE POINTS] - array(0x10FFFE, 0x10FFFF), // [NONCHARACTER CODE POINTS] - // Table C.5 - array(0xD800, 0xDFFF), // [SURROGATE CODES] - // Table C.6 - array(0xFFF9, 0xFFF9), // INTERLINEAR ANNOTATION ANCHOR - array(0xFFFA, 0xFFFA), // INTERLINEAR ANNOTATION SEPARATOR - array(0xFFFB, 0xFFFB), // INTERLINEAR ANNOTATION TERMINATOR - array(0xFFFC, 0xFFFC), // OBJECT REPLACEMENT CHARACTER - array(0xFFFD, 0xFFFD), // REPLACEMENT CHARACTER - // Table C.7 - array(0x2FF0, 0x2FFB), // [IDEOGRAPHIC DESCRIPTION CHARACTERS] - // Table C.8 - array(0x0340, 0x0340), // COMBINING GRAVE TONE MARK - array(0x0341, 0x0341), // COMBINING ACUTE TONE MARK - array(0x200E, 0x200E), // LEFT-TO-RIGHT MARK - array(0x200F, 0x200F), // RIGHT-TO-LEFT MARK - array(0x202A, 0x202A), // LEFT-TO-RIGHT EMBEDDING - array(0x202B, 0x202B), // RIGHT-TO-LEFT EMBEDDING - array(0x202C, 0x202C), // POP DIRECTIONAL FORMATTING - array(0x202D, 0x202D), // LEFT-TO-RIGHT OVERRIDE - array(0x202E, 0x202E), // RIGHT-TO-LEFT OVERRIDE - array(0x206A, 0x206A), // INHIBIT SYMMETRIC SWAPPING - array(0x206B, 0x206B), // ACTIVATE SYMMETRIC SWAPPING - array(0x206C, 0x206C), // INHIBIT ARABIC FORM SHAPING - array(0x206D, 0x206D), // ACTIVATE ARABIC FORM SHAPING - array(0x206E, 0x206E), // NATIONAL DIGIT SHAPES - array(0x206F, 0x206F), // NOMINAL DIGIT SHAPES - // Table C.9 - array(0xE0001, 0xE0001), // LANGUAGE TAG - array(0xE0020, 0xE007F), // [TAGGING CHARACTERS] - // RFC3920 - array(0x22, 0x22), // " - array(0x26, 0x26), // & - array(0x27, 0x27), // ' - array(0x2F, 0x2F), // / - array(0x3A, 0x3A), // : - array(0x3C, 0x3C), // < - array(0x3E, 0x3E), // > - array(0x40, 0x40) // @ - ); - - $pos = 0; - $result = true; - - // @todo: rewrite this! - while ($pos < strlen($username)) - { - $len = $uni = 0; - for ($i = 0; $i <= 5; $i++) - { - if (ord($username[$pos]) >= $boundary[$i][0] && ord($username[$pos]) <= $boundary[$i][1]) - { - $len = $i + 1; - $uni = (ord($username[$pos]) - $boundary[$i][0]) * pow(2, $i * 6); - - for ($k = 1; $k < $len; $k++) - { - $uni += (ord($username[$pos + $k]) - 128) * pow(2, ($i - $k) * 6); - } - - break; - } - } - - if ($len == 0) - { - return 'WRONG_DATA'; - } - - foreach ($prohibited as $pval) - { - if ($uni >= $pval[0] && $uni <= $pval[1]) - { - $result = false; - break 2; - } - } - - $pos = $pos + $len; - } - - if (!$result) - { - return 'WRONG_DATA'; - } - - return false; -} - -/** -* Remove avatar -*/ -function avatar_delete($mode, $row, $clean_db = false) -{ - // Check if the users avatar is actually *not* a group avatar - if ($mode == 'user') - { - if (strpos($row['user_avatar'], 'g') === 0 || (((int)$row['user_avatar'] !== 0) && ((int)$row['user_avatar'] !== (int)$row['user_id']))) - { - return false; - } - } - - if ($clean_db) - { - avatar_remove_db($row[$mode . '_avatar']); - } - $filename = get_avatar_filename($row[$mode . '_avatar']); - if (file_exists(PHPBB_ROOT_PATH . phpbb::$config['avatar_path'] . '/' . $filename)) - { - @unlink(PHPBB_ROOT_PATH . phpbb::$config['avatar_path'] . '/' . $filename); - return true; - } - - return false; -} - -/** -* Remote avatar linkage -*/ -function avatar_remote($data, &$error) -{ - if (!preg_match('#^(http|https|ftp)://#i', $data['remotelink'])) - { - $data['remotelink'] = 'http://' . $data['remotelink']; - } - if (!preg_match('#^(http|https|ftp)://(?:(.*?\.)*?[a-z0-9\-]+?\.[a-z]{2,4}|(?:\d{1,3}\.){3,5}\d{1,3}):?([0-9]*?).*?\.(gif|jpg|jpeg|png)$#i', $data['remotelink'])) - { - $error[] = phpbb::$user->lang['AVATAR_URL_INVALID']; - return false; - } - - // Make sure getimagesize works... - if (($image_data = @getimagesize($data['remotelink'])) === false && (empty($data['width']) || empty($data['height']))) - { - $error[] = phpbb::$user->lang['UNABLE_GET_IMAGE_SIZE']; - return false; - } - - if (!empty($image_data) && ($image_data[0] < 2 || $image_data[1] < 2)) - { - $error[] = phpbb::$user->lang['AVATAR_NO_SIZE']; - return false; - } - - $width = ($data['width'] && $data['height']) ? $data['width'] : $image_data[0]; - $height = ($data['width'] && $data['height']) ? $data['height'] : $image_data[1]; - - if ($width < 2 || $height < 2) - { - $error[] = phpbb::$user->lang['AVATAR_NO_SIZE']; - return false; - } - - // Check image type - include_once(PHPBB_ROOT_PATH . 'includes/functions_upload.' . PHP_EXT); - $types = fileupload::image_types(); - $extension = strtolower(filespec::get_extension($data['remotelink'])); - - if (!empty($image_data) && (!isset($types[$image_data[2]]) || !in_array($extension, $types[$image_data[2]]))) - { - if (!isset($types[$image_data[2]])) - { - $error[] = phpbb::$user->lang['UNABLE_GET_IMAGE_SIZE']; - } - else - { - $error[] = sprintf(phpbb::$user->lang['IMAGE_FILETYPE_MISMATCH'], $types[$image_data[2]][0], $extension); - } - return false; - } - - if (phpbb::$config['avatar_max_width'] || phpbb::$config['avatar_max_height']) - { - if ($width > phpbb::$config['avatar_max_width'] || $height > phpbb::$config['avatar_max_height']) - { - $error[] = sprintf(phpbb::$user->lang['AVATAR_WRONG_SIZE'], phpbb::$config['avatar_min_width'], phpbb::$config['avatar_min_height'], phpbb::$config['avatar_max_width'], phpbb::$config['avatar_max_height'], $width, $height); - return false; - } - } - - if (phpbb::$config['avatar_min_width'] || phpbb::$config['avatar_min_height']) - { - if ($width < phpbb::$config['avatar_min_width'] || $height < phpbb::$config['avatar_min_height']) - { - $error[] = sprintf(phpbb::$user->lang['AVATAR_WRONG_SIZE'], phpbb::$config['avatar_min_width'], phpbb::$config['avatar_min_height'], phpbb::$config['avatar_max_width'], phpbb::$config['avatar_max_height'], $width, $height); - return false; - } - } - - return array(AVATAR_REMOTE, $data['remotelink'], $width, $height); -} - -/** -* Avatar upload using the upload class -*/ -function avatar_upload($data, &$error) -{ - // Init upload class - include_once(PHPBB_ROOT_PATH . 'includes/functions_upload.' . PHP_EXT); - $upload = new fileupload('AVATAR_', array('jpg', 'jpeg', 'gif', 'png'), phpbb::$config['avatar_filesize'], phpbb::$config['avatar_min_width'], phpbb::$config['avatar_min_height'], phpbb::$config['avatar_max_width'], phpbb::$config['avatar_max_height'], explode('|', phpbb::$config['mime_triggers'])); - - if (!empty($_FILES['uploadfile']['name'])) - { - $file = $upload->form_upload('uploadfile'); - } - else - { - $file = $upload->remote_upload($data['uploadurl']); - } - - $prefix = phpbb::$config['avatar_salt'] . '_'; - $file->clean_filename('avatar', $prefix, $data['user_id']); - - $destination = phpbb::$config['avatar_path']; - - // Adjust destination path (no trailing slash) - if (substr($destination, -1, 1) == '/' || substr($destination, -1, 1) == '\\') - { - $destination = substr($destination, 0, -1); - } - - $destination = str_replace(array('../', '..\\', './', '.\\'), '', $destination); - if ($destination && ($destination[0] == '/' || $destination[0] == "\\")) - { - $destination = ''; - } - - // Move file and overwrite any existing image - $file->move_file($destination, true); - - if (sizeof($file->error)) - { - $file->remove(); - $error = array_merge($error, $file->error); - } - - return array(AVATAR_UPLOAD, $data['user_id'] . '_' . time() . '.' . $file->get('extension'), $file->get('width'), $file->get('height')); -} - -/** -* Generates avatar filename from the database entry -*/ -function get_avatar_filename($avatar_entry) -{ - if ($avatar_entry[0] === 'g') - { - $avatar_group = true; - $avatar_entry = substr($avatar_entry, 1); - } - else - { - $avatar_group = false; - } - $ext = substr(strrchr($avatar_entry, '.'), 1); - $avatar_entry = intval($avatar_entry); - return phpbb::$config['avatar_salt'] . '_' . (($avatar_group) ? 'g' : '') . $avatar_entry . '.' . $ext; -} - -/** -* Avatar Gallery -*/ -function avatar_gallery($category, $avatar_select, $items_per_column, $block_var = 'avatar_row') -{ - $avatar_list = array(); - - $path = PHPBB_ROOT_PATH . phpbb::$config['avatar_gallery_path']; - - if (!file_exists($path) || !is_dir($path)) - { - $avatar_list = array(phpbb::$user->lang['NO_AVATAR_CATEGORY'] => array()); - } - else - { - // Collect images - $dp = @opendir($path); - - if (!$dp) - { - return array(phpbb::$user->lang['NO_AVATAR_CATEGORY'] => array()); - } - - while (($file = readdir($dp)) !== false) - { - if ($file[0] != '.' && preg_match('#^[^&"\'<>]+$#i', $file) && is_dir("$path/$file")) - { - $avatar_row_count = $avatar_col_count = 0; - - if ($dp2 = @opendir("$path/$file")) - { - while (($sub_file = readdir($dp2)) !== false) - { - if (preg_match('#^[^&\'"<>]+\.(?:gif|png|jpe?g)$#i', $sub_file)) - { - $avatar_list[$file][$avatar_row_count][$avatar_col_count] = array( - 'file' => "$file/$sub_file", - 'filename' => $sub_file, - 'name' => ucfirst(str_replace('_', ' ', preg_replace('#^(.*)\..*$#', '\1', $sub_file))), - ); - $avatar_col_count++; - if ($avatar_col_count == $items_per_column) - { - $avatar_row_count++; - $avatar_col_count = 0; - } - } - } - closedir($dp2); - } - } - } - closedir($dp); - } - - if (!sizeof($avatar_list)) - { - $avatar_list = array(phpbb::$user->lang['NO_AVATAR_CATEGORY'] => array()); - } - - @ksort($avatar_list); - - $category = (!$category) ? key($avatar_list) : $category; - $avatar_categories = array_keys($avatar_list); - - $s_category_options = ''; - foreach ($avatar_categories as $cat) - { - $s_category_options .= '<option value="' . $cat . '"' . (($cat == $category) ? ' selected="selected"' : '') . '>' . $cat . '</option>'; - } - - phpbb::$template->assign_vars(array( - 'S_AVATARS_ENABLED' => true, - 'S_IN_AVATAR_GALLERY' => true, - 'S_CAT_OPTIONS' => $s_category_options, - )); - - $avatar_list = (isset($avatar_list[$category])) ? $avatar_list[$category] : array(); - - foreach ($avatar_list as $avatar_row_ary) - { - phpbb::$template->assign_block_vars($block_var, array()); - - foreach ($avatar_row_ary as $avatar_col_ary) - { - phpbb::$template->assign_block_vars($block_var . '.avatar_column', array( - 'AVATAR_IMAGE' => PHPBB_ROOT_PATH . phpbb::$config['avatar_gallery_path'] . '/' . $avatar_col_ary['file'], - 'AVATAR_NAME' => $avatar_col_ary['name'], - 'AVATAR_FILE' => $avatar_col_ary['filename'], - )); - - phpbb::$template->assign_block_vars($block_var . '.avatar_option_column', array( - 'AVATAR_IMAGE' => PHPBB_ROOT_PATH . phpbb::$config['avatar_gallery_path'] . '/' . $avatar_col_ary['file'], - 'S_OPTIONS_AVATAR' => $avatar_col_ary['filename'], - )); - } - } - - return $avatar_list; -} - - -/** -* Tries to (re-)establish avatar dimensions -*/ -function avatar_get_dimensions($avatar, $avatar_type, &$error, $current_x = 0, $current_y = 0) -{ - switch ($avatar_type) - { - case AVATAR_REMOTE : - break; - - case AVATAR_UPLOAD : - $avatar = PHPBB_ROOT_PATH . phpbb::$config['avatar_path'] . '/' . get_avatar_filename($avatar); - break; - - case AVATAR_GALLERY : - $avatar = PHPBB_ROOT_PATH . phpbb::$config['avatar_gallery_path'] . '/' . $avatar ; - break; - } - - // Make sure getimagesize works... - if (($image_data = @getimagesize($avatar)) === false) - { - $error[] = phpbb::$user->lang['UNABLE_GET_IMAGE_SIZE']; - return false; - } - - if ($image_data[0] < 2 || $image_data[1] < 2) - { - $error[] = phpbb::$user->lang['AVATAR_NO_SIZE']; - return false; - } - - // try to maintain ratio - if (!(empty($current_x) && empty($current_y))) - { - if ($current_x != 0) - { - $image_data[1] = (int) floor(($current_x / $image_data[0]) * $image_data[1]); - $image_data[1] = min(phpbb::$config['avatar_max_height'], $image_data[1]); - $image_data[1] = max(phpbb::$config['avatar_min_height'], $image_data[1]); - } - if ($current_y != 0) - { - $image_data[0] = (int) floor(($current_y / $image_data[1]) * $image_data[0]); - $image_data[0] = min(phpbb::$config['avatar_max_width'], $image_data[1]); - $image_data[0] = max(phpbb::$config['avatar_min_width'], $image_data[1]); - } - } - return array($image_data[0], $image_data[1]); -} - -/** -* Uploading/Changing user avatar -*/ -function avatar_process_user(&$error, $custom_userdata = false) -{ - $data = array( - 'uploadurl' => request_var('uploadurl', ''), - 'remotelink' => request_var('remotelink', ''), - 'width' => request_var('width', 0), - 'height' => request_var('height', 0), - ); - - $error = validate_data($data, array( - 'uploadurl' => array('string', true, 5, 255), - 'remotelink' => array('string', true, 5, 255), - 'width' => array('string', true, 1, 3), - 'height' => array('string', true, 1, 3), - )); - - if (sizeof($error)) - { - return false; - } - - $sql_ary = array(); - - if ($custom_userdata === false) - { - $userdata = &phpbb::$user->data; - } - else - { - $userdata = &$custom_userdata; - } - - $data['user_id'] = $userdata['user_id']; - $change_avatar = ($custom_userdata === false) ? phpbb::$acl->acl_get('u_chgavatar') : true; - $avatar_select = basename(request_var('avatar_select', '')); - - // Can we upload? - $can_upload = (phpbb::$config['allow_avatar_upload'] && file_exists(PHPBB_ROOT_PATH . phpbb::$config['avatar_path']) && @is_writable(PHPBB_ROOT_PATH . phpbb::$config['avatar_path']) && $change_avatar && (@ini_get('file_uploads') || strtolower(@ini_get('file_uploads')) == 'on')) ? true : false; - - if ((!empty($_FILES['uploadfile']['name']) || $data['uploadurl']) && $can_upload) - { - list($sql_ary['user_avatar_type'], $sql_ary['user_avatar'], $sql_ary['user_avatar_width'], $sql_ary['user_avatar_height']) = avatar_upload($data, $error); - } - else if ($data['remotelink'] && $change_avatar && phpbb::$config['allow_avatar_remote']) - { - list($sql_ary['user_avatar_type'], $sql_ary['user_avatar'], $sql_ary['user_avatar_width'], $sql_ary['user_avatar_height']) = avatar_remote($data, $error); - } - else if ($avatar_select && $change_avatar && phpbb::$config['allow_avatar_local']) - { - $category = basename(request_var('category', '')); - - $sql_ary['user_avatar_type'] = AVATAR_GALLERY; - $sql_ary['user_avatar'] = $avatar_select; - - // check avatar gallery - if (!is_dir(PHPBB_ROOT_PATH . phpbb::$config['avatar_gallery_path'] . '/' . $category)) - { - $sql_ary['user_avatar'] = ''; - $sql_ary['user_avatar_type'] = $sql_ary['user_avatar_width'] = $sql_ary['user_avatar_height'] = 0; - } - else - { - list($sql_ary['user_avatar_width'], $sql_ary['user_avatar_height']) = getimagesize(PHPBB_ROOT_PATH . phpbb::$config['avatar_gallery_path'] . '/' . $category . '/' . $sql_ary['user_avatar']); - $sql_ary['user_avatar'] = $category . '/' . $sql_ary['user_avatar']; - } - } - else if (phpbb_request::is_set_post('delete') && $change_avatar) - { - $sql_ary['user_avatar'] = ''; - $sql_ary['user_avatar_type'] = $sql_ary['user_avatar_width'] = $sql_ary['user_avatar_height'] = 0; - } - else if (!empty($userdata['user_avatar'])) - { - // Only update the dimensions - - if (empty($data['width']) || empty($data['height'])) - { - if ($dims = avatar_get_dimensions($userdata['user_avatar'], $userdata['user_avatar_type'], $error, $data['width'], $data['height'])) - { - list($guessed_x, $guessed_y) = $dims; - if (empty($data['width'])) - { - $data['width'] = $guessed_x; - } - if (empty($data['height'])) - { - $data['height'] = $guessed_y; - } - } - } - if ((phpbb::$config['avatar_max_width'] || phpbb::$config['avatar_max_height']) && - (($data['width'] != $userdata['user_avatar_width']) || $data['height'] != $userdata['user_avatar_height'])) - { - if ($data['width'] > phpbb::$config['avatar_max_width'] || $data['height'] > phpbb::$config['avatar_max_height']) - { - $error[] = sprintf(phpbb::$user->lang['AVATAR_WRONG_SIZE'], phpbb::$config['avatar_min_width'], phpbb::$config['avatar_min_height'], phpbb::$config['avatar_max_width'], phpbb::$config['avatar_max_height'], $data['width'], $data['height']); - } - } - - if (!sizeof($error)) - { - if (phpbb::$config['avatar_min_width'] || phpbb::$config['avatar_min_height']) - { - if ($data['width'] < phpbb::$config['avatar_min_width'] || $data['height'] < phpbb::$config['avatar_min_height']) - { - $error[] = sprintf(phpbb::$user->lang['AVATAR_WRONG_SIZE'], phpbb::$config['avatar_min_width'], phpbb::$config['avatar_min_height'], phpbb::$config['avatar_max_width'], phpbb::$config['avatar_max_height'], $data['width'], $data['height']); - } - } - } - - if (!sizeof($error)) - { - $sql_ary['user_avatar_width'] = $data['width']; - $sql_ary['user_avatar_height'] = $data['height']; - } - } - - if (!sizeof($error)) - { - // Do we actually have any data to update? - if (sizeof($sql_ary)) - { - $ext_new = $ext_old = ''; - if (isset($sql_ary['user_avatar'])) - { - $userdata = ($custom_userdata === false) ? phpbb::$user->data : $custom_userdata; - $ext_new = (empty($sql_ary['user_avatar'])) ? '' : substr(strrchr($sql_ary['user_avatar'], '.'), 1); - $ext_old = (empty($userdata['user_avatar'])) ? '' : substr(strrchr($userdata['user_avatar'], '.'), 1); - - if ($userdata['user_avatar_type'] == AVATAR_UPLOAD) - { - // Delete old avatar if present - if ((!empty($userdata['user_avatar']) && empty($sql_ary['user_avatar'])) - || ( !empty($userdata['user_avatar']) && !empty($sql_ary['user_avatar']) && $ext_new !== $ext_old)) - { - avatar_delete('user', $userdata); - } - } - } - - $sql = 'UPDATE ' . USERS_TABLE . ' - SET ' . phpbb::$db->sql_build_array('UPDATE', $sql_ary) . ' - WHERE user_id = ' . (($custom_userdata === false) ? phpbb::$user->data['user_id'] : $custom_userdata['user_id']); - phpbb::$db->sql_query($sql); - - } - } - - return (sizeof($error)) ? false : true; -} - -// -// Usergroup functions -// - -/** -* Add or edit a group. If we're editing a group we only update user -* parameters such as rank, etc. if they are changed -*/ -function group_create(&$group_id, $type, $name, $desc, $group_attributes, $allow_desc_bbcode = false, $allow_desc_urls = false, $allow_desc_smilies = false) -{ - global $file_upload; - - $error = array(); - $attribute_ary = array( - 'group_colour' => 'string', - 'group_rank' => 'int', - 'group_avatar' => 'string', - 'group_avatar_type' => 'int', - 'group_avatar_width' => 'int', - 'group_avatar_height' => 'int', - - 'group_receive_pm' => 'int', - 'group_legend' => 'int', - 'group_message_limit' => 'int', - 'group_max_recipients' => 'int', - - 'group_founder_manage' => 'int', - ); - - // Those are group-only attributes - $group_only_ary = array('group_receive_pm', 'group_legend', 'group_message_limit', 'group_max_recipients', 'group_founder_manage'); - - // Check data. Limit group name length. - if (!utf8_strlen($name) || utf8_strlen($name) > 60) - { - $error[] = (!utf8_strlen($name)) ? phpbb::$user->lang['GROUP_ERR_USERNAME'] : phpbb::$user->lang['GROUP_ERR_USER_LONG']; - } - - $err = group_validate_groupname($group_id, $name); - if (!empty($err)) - { - $error[] = phpbb::$user->lang[$err]; - } - - if (!in_array($type, array(GROUP_OPEN, GROUP_CLOSED, GROUP_HIDDEN, GROUP_SPECIAL, GROUP_FREE))) - { - $error[] = phpbb::$user->lang['GROUP_ERR_TYPE']; - } - - if (!sizeof($error)) - { - $user_ary = array(); - $sql_ary = array( - 'group_name' => (string) $name, - 'group_name_clean' => (string) utf8_clean_string($name), - 'group_desc' => (string) $desc, - 'group_desc_uid' => '', - 'group_desc_bitfield' => '', - 'group_type' => (int) $type, - ); - - // Parse description - if ($desc) - { - generate_text_for_storage($sql_ary['group_desc'], $sql_ary['group_desc_uid'], $sql_ary['group_desc_bitfield'], $sql_ary['group_desc_options'], $allow_desc_bbcode, $allow_desc_urls, $allow_desc_smilies); - } - - if (sizeof($group_attributes)) - { - foreach ($attribute_ary as $attribute => $_type) - { - if (isset($group_attributes[$attribute])) - { - settype($group_attributes[$attribute], $_type); - $sql_ary[$attribute] = $group_attributes[$attribute]; - } - } - } - - // Setting the log message before we set the group id (if group gets added) - $log = ($group_id) ? 'LOG_GROUP_UPDATED' : 'LOG_GROUP_CREATED'; - - $query = ''; - - if ($group_id) - { - $sql = 'SELECT user_id - FROM ' . USERS_TABLE . ' - WHERE group_id = ' . $group_id; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $user_ary[] = $row['user_id']; - } - phpbb::$db->sql_freeresult($result); - - if (isset($sql_ary['group_avatar']) && !$sql_ary['group_avatar']) - { - remove_default_avatar($group_id, $user_ary); - } - if (isset($sql_ary['group_rank']) && !$sql_ary['group_rank']) - { - remove_default_rank($group_id, $user_ary); - } - - $sql = 'UPDATE ' . GROUPS_TABLE . ' - SET ' . phpbb::$db->sql_build_array('UPDATE', $sql_ary) . " - WHERE group_id = $group_id"; - phpbb::$db->sql_query($sql); - - // Since we may update the name too, we need to do this on other tables too... - $sql = 'UPDATE ' . MODERATOR_CACHE_TABLE . " - SET group_name = '" . phpbb::$db->sql_escape($sql_ary['group_name']) . "' - WHERE group_id = $group_id"; - phpbb::$db->sql_query($sql); - } - else - { - $sql = 'INSERT INTO ' . GROUPS_TABLE . ' ' . phpbb::$db->sql_build_array('INSERT', $sql_ary); - phpbb::$db->sql_query($sql); - } - - if (!$group_id) - { - $group_id = phpbb::$db->sql_nextid(); - if (isset($sql_ary['group_avatar_type']) && $sql_ary['group_avatar_type'] == AVATAR_UPLOAD) - { - group_correct_avatar($group_id, $sql_ary['group_avatar']); - } - } - - // Set user attributes - $sql_ary = array(); - if (sizeof($group_attributes)) - { - foreach ($attribute_ary as $attribute => $_type) - { - if (isset($group_attributes[$attribute]) && !in_array($attribute, $group_only_ary)) - { - // If we are about to set an avatar, we will not overwrite user avatars if no group avatar is set... - if (strpos($attribute, 'group_avatar') === 0 && !$group_attributes[$attribute]) - { - continue; - } - - $sql_ary[$attribute] = $group_attributes[$attribute]; - } - } - } - - if (sizeof($sql_ary) && sizeof($user_ary)) - { - group_set_user_default($group_id, $user_ary, $sql_ary); - } - - $name = ($type == GROUP_SPECIAL) ? phpbb::$user->lang['G_' . $name] : $name; - add_log('admin', $log, $name); - - group_update_listings($group_id); - } - - return (sizeof($error)) ? $error : false; -} - - -/** -* Changes a group avatar's filename to conform to the naming scheme -*/ -function group_correct_avatar($group_id, $old_entry) -{ - $group_id = (int)$group_id; - $ext = substr(strrchr($old_entry, '.'), 1); - $old_filename = get_avatar_filename($old_entry); - $new_filename = phpbb::$config['avatar_salt'] . "_g$group_id.$ext"; - $new_entry = 'g' . $group_id . '_' . substr(time(), -5) . ".$ext"; - - $avatar_path = PHPBB_ROOT_PATH . phpbb::$config['avatar_path']; - if (@rename($avatar_path . '/'. $old_filename, $avatar_path . '/' . $new_filename)) - { - $sql = 'UPDATE ' . GROUPS_TABLE . ' - SET group_avatar = \'' . phpbb::$db->sql_escape($new_entry) . "' - WHERE group_id = $group_id"; - phpbb::$db->sql_query($sql); - } -} - - -/** -* Remove avatar also for users not having the group as default -*/ -function avatar_remove_db($avatar_name) -{ - $sql = 'UPDATE ' . USERS_TABLE . " - SET user_avatar = '', - user_avatar_type = 0 - WHERE user_avatar = '" . phpbb::$db->sql_escape($avatar_name) . '\''; - phpbb::$db->sql_query($sql); -} - - -/** -* Group Delete -*/ -function group_delete($group_id, $group_name = false) -{ - if (!$group_name) - { - $group_name = get_group_name($group_id); - } - - $start = 0; - - do - { - $user_id_ary = $username_ary = array(); - - // Batch query for group members, call group_user_del - $sql = 'SELECT u.user_id, u.username - FROM ' . USER_GROUP_TABLE . ' ug, ' . USERS_TABLE . " u - WHERE ug.group_id = $group_id - AND u.user_id = ug.user_id"; - $result = phpbb::$db->sql_query_limit($sql, 200, $start); - - if ($row = phpbb::$db->sql_fetchrow($result)) - { - do - { - $user_id_ary[] = $row['user_id']; - $username_ary[] = $row['username']; - - $start++; - } - while ($row = phpbb::$db->sql_fetchrow($result)); - - group_user_del($group_id, $user_id_ary, $username_ary, $group_name); - } - else - { - $start = 0; - } - phpbb::$db->sql_freeresult($result); - } - while ($start); - - // Delete group - $sql = 'DELETE FROM ' . GROUPS_TABLE . " - WHERE group_id = $group_id"; - phpbb::$db->sql_query($sql); - - // Delete auth entries from the groups table - $sql = 'DELETE FROM ' . ACL_GROUPS_TABLE . " - WHERE group_id = $group_id"; - phpbb::$db->sql_query($sql); - - // Re-cache moderators - if (!function_exists('cache_moderators')) - { - include(PHPBB_ROOT_PATH . 'includes/functions_admin.' . PHP_EXT); - } - - cache_moderators(); - - add_log('admin', 'LOG_GROUP_DELETE', $group_name); - - // Return false - no error - return false; -} - -/** -* Add user(s) to group -* -* @return mixed false if no errors occurred, else the user lang string for the relevant error, for example 'NO_USER' -*/ -function group_user_add($group_id, $user_id_ary = false, $username_ary = false, $group_name = false, $default = false, $leader = 0, $pending = 0, $group_attributes = false) -{ - // We need both username and user_id info - $result = user_get_id_name($user_id_ary, $username_ary); - - if (!sizeof($user_id_ary) || $result !== false) - { - return 'NO_USER'; - } - - // Remove users who are already members of this group - $sql = 'SELECT user_id, group_leader - FROM ' . USER_GROUP_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('user_id', $user_id_ary) . " - AND group_id = $group_id"; - $result = phpbb::$db->sql_query($sql); - - $add_id_ary = $update_id_ary = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $add_id_ary[] = (int) $row['user_id']; - - if ($leader && !$row['group_leader']) - { - $update_id_ary[] = (int) $row['user_id']; - } - } - phpbb::$db->sql_freeresult($result); - - // Do all the users exist in this group? - $add_id_ary = array_diff($user_id_ary, $add_id_ary); - - // If we have no users - if (!sizeof($add_id_ary) && !sizeof($update_id_ary)) - { - return 'GROUP_USERS_EXIST'; - } - - phpbb::$db->sql_transaction('begin'); - - // Insert the new users - if (sizeof($add_id_ary)) - { - $sql_ary = array(); - - foreach ($add_id_ary as $user_id) - { - $sql_ary[] = array( - 'user_id' => (int) $user_id, - 'group_id' => (int) $group_id, - 'group_leader' => (int) $leader, - 'user_pending' => (int) $pending, - ); - } - - phpbb::$db->sql_multi_insert(USER_GROUP_TABLE, $sql_ary); - } - - if (sizeof($update_id_ary)) - { - $sql = 'UPDATE ' . USER_GROUP_TABLE . ' - SET group_leader = 1 - WHERE ' . phpbb::$db->sql_in_set('user_id', $update_id_ary) . " - AND group_id = $group_id"; - phpbb::$db->sql_query($sql); - } - - if ($default) - { - group_set_user_default($group_id, $user_id_ary, $group_attributes); - } - - phpbb::$db->sql_transaction('commit'); - - // Clear permissions cache of relevant users - phpbb::$acl->acl_clear_prefetch($user_id_ary); - - if (!$group_name) - { - $group_name = get_group_name($group_id); - } - - $log = ($leader) ? 'LOG_MODS_ADDED' : 'LOG_USERS_ADDED'; - - add_log('admin', $log, $group_name, implode(', ', $username_ary)); - - group_update_listings($group_id); - - // Return false - no error - return false; -} - -/** -* Remove a user/s from a given group. When we remove users we update their -* default group_id. We do this by examining which "special" groups they belong -* to. The selection is made based on a reasonable priority system -* -* @return false if no errors occurred, else the user lang string for the relevant error, for example 'NO_USER' -*/ -function group_user_del($group_id, $user_id_ary = false, $username_ary = false, $group_name = false) -{ - if (phpbb::$config['coppa_enable']) - { - $group_order = array('ADMINISTRATORS', 'GLOBAL_MODERATORS', 'REGISTERED_COPPA', 'REGISTERED', 'BOTS', 'GUESTS'); - } - else - { - $group_order = array('ADMINISTRATORS', 'GLOBAL_MODERATORS', 'REGISTERED', 'BOTS', 'GUESTS'); - } - - // We need both username and user_id info - $result = user_get_id_name($user_id_ary, $username_ary); - - if (!sizeof($user_id_ary) || $result !== false) - { - return 'NO_USER'; - } - - $clean_group_order = array_map('utf8_clean_string', $group_order); - - $sql = 'SELECT * - FROM ' . GROUPS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('group_name_clean', $clean_group_order); - $result = phpbb::$db->sql_query($sql); - - $group_order_id = $special_group_data = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $group_order_id[$row['group_name']] = $row['group_id']; - - $special_group_data[$row['group_id']] = array( - 'group_colour' => $row['group_colour'], - 'group_rank' => $row['group_rank'], - ); - - // Only set the group avatar if one is defined... - if ($row['group_avatar']) - { - $special_group_data[$row['group_id']] = array_merge($special_group_data[$row['group_id']], array( - 'group_avatar' => $row['group_avatar'], - 'group_avatar_type' => $row['group_avatar_type'], - 'group_avatar_width' => $row['group_avatar_width'], - 'group_avatar_height' => $row['group_avatar_height']) - ); - } - } - phpbb::$db->sql_freeresult($result); - - // Get users default groups - we only need to reset default group membership if the group from which the user gets removed is set as default - $sql = 'SELECT user_id, group_id - FROM ' . USERS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('user_id', $user_id_ary); - $result = phpbb::$db->sql_query($sql); - - $default_groups = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $default_groups[$row['user_id']] = $row['group_id']; - } - phpbb::$db->sql_freeresult($result); - - // What special group memberships exist for these users? - $sql = 'SELECT g.group_id, g.group_name_clean, ug.user_id - FROM ' . USER_GROUP_TABLE . ' ug, ' . GROUPS_TABLE . ' g - WHERE ' . phpbb::$db->sql_in_set('ug.user_id', $user_id_ary) . " - AND g.group_id = ug.group_id - AND g.group_id <> $group_id - AND g.group_type = " . GROUP_SPECIAL . ' - ORDER BY ug.user_id, g.group_id'; - $result = phpbb::$db->sql_query($sql); - - $temp_ary = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($default_groups[$row['user_id']] == $group_id && (!isset($temp_ary[$row['user_id']]) || $group_order_id[$row['group_name']] < $temp_ary[$row['user_id']])) - { - $temp_ary[$row['user_id']] = $row['group_id']; - } - } - phpbb::$db->sql_freeresult($result); - - // sql_where_ary holds the new default groups and their users - $sql_where_ary = array(); - foreach ($temp_ary as $uid => $gid) - { - $sql_where_ary[$gid][] = $uid; - } - unset($temp_ary); - - foreach ($special_group_data as $gid => $default_data_ary) - { - if (isset($sql_where_ary[$gid]) && sizeof($sql_where_ary[$gid])) - { - remove_default_rank($gid, $sql_where_ary[$gid]); - remove_default_avatar($group_id, $sql_where_ary[$gid]); - group_set_user_default($gid, $sql_where_ary[$gid], $default_data_ary); - } - } - unset($special_group_data); - - $sql = 'DELETE FROM ' . USER_GROUP_TABLE . " - WHERE group_id = $group_id - AND " . phpbb::$db->sql_in_set('user_id', $user_id_ary); - phpbb::$db->sql_query($sql); - - // Clear permissions cache of relevant users - phpbb::$acl->acl_clear_prefetch($user_id_ary); - - if (!$group_name) - { - $group_name = get_group_name($group_id); - } - - $log = 'LOG_GROUP_REMOVE'; - - add_log('admin', $log, $group_name, implode(', ', $username_ary)); - - group_update_listings($group_id); - - // Return false - no error - return false; -} - - -/** -* Removes the group avatar of the default group from the users in user_ids who have that group as default. -*/ -function remove_default_avatar($group_id, $user_ids) -{ - if (!is_array($user_ids)) - { - $user_ids = array($user_ids); - } - if (empty($user_ids)) - { - return false; - } - - $user_ids = array_map('intval', $user_ids); - - $sql = 'SELECT * - FROM ' . GROUPS_TABLE . ' - WHERE group_id = ' . (int)$group_id; - $result = phpbb::$db->sql_query($sql); - if (!$row = phpbb::$db->sql_fetchrow($result)) - { - phpbb::$db->sql_freeresult($result); - return false; - } - phpbb::$db->sql_freeresult($result); - - $sql = 'UPDATE ' . USERS_TABLE . " - SET user_avatar = '', - user_avatar_type = 0, - user_avatar_width = 0, - user_avatar_height = 0 - WHERE group_id = " . (int) $group_id . " - AND user_avatar = '" . phpbb::$db->sql_escape($row['group_avatar']) . "' - AND " . phpbb::$db->sql_in_set('user_id', $user_ids); - - phpbb::$db->sql_query($sql); -} - -/** -* Removes the group rank of the default group from the users in user_ids who have that group as default. -*/ -function remove_default_rank($group_id, $user_ids) -{ - if (!is_array($user_ids)) - { - $user_ids = array($user_ids); - } - if (empty($user_ids)) - { - return false; - } - - $user_ids = array_map('intval', $user_ids); - - $sql = 'SELECT * - FROM ' . GROUPS_TABLE . ' - WHERE group_id = ' . (int)$group_id; - $result = phpbb::$db->sql_query($sql); - if (!$row = phpbb::$db->sql_fetchrow($result)) - { - phpbb::$db->sql_freeresult($result); - return false; - } - phpbb::$db->sql_freeresult($result); - - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_rank = 0 - WHERE group_id = ' . (int)$group_id . ' - AND user_rank <> 0 - AND user_rank = ' . (int)$row['group_rank'] . ' - AND ' . phpbb::$db->sql_in_set('user_id', $user_ids); - phpbb::$db->sql_query($sql); -} - -/** -* This is used to promote (to leader), demote or set as default a member/s -*/ -function group_user_attributes($action, $group_id, $user_id_ary = false, $username_ary = false, $group_name = false, $group_attributes = false) -{ - // We need both username and user_id info - $result = user_get_id_name($user_id_ary, $username_ary); - - if (!sizeof($user_id_ary) || $result !== false) - { - return 'NO_USERS'; - } - - if (!$group_name) - { - $group_name = get_group_name($group_id); - } - - switch ($action) - { - case 'demote': - case 'promote': - - $sql = 'SELECT user_id FROM ' . USER_GROUP_TABLE . " - WHERE group_id = $group_id - AND user_pending = 1 - AND " . phpbb::$db->sql_in_set('user_id', $user_id_ary); - $result = phpbb::$db->sql_query_limit($sql, 1); - $not_empty = (phpbb::$db->sql_fetchrow($result)); - phpbb::$db->sql_freeresult($result); - if ($not_empty) - { - return 'NO_VALID_USERS'; - } - - $sql = 'UPDATE ' . USER_GROUP_TABLE . ' - SET group_leader = ' . (($action == 'promote') ? 1 : 0) . " - WHERE group_id = $group_id - AND user_pending = 0 - AND " . phpbb::$db->sql_in_set('user_id', $user_id_ary); - phpbb::$db->sql_query($sql); - - $log = ($action == 'promote') ? 'LOG_GROUP_PROMOTED' : 'LOG_GROUP_DEMOTED'; - break; - - case 'approve': - // Make sure we only approve those which are pending ;) - $sql = 'SELECT u.user_id, u.user_email, u.username, u.username_clean, u.user_notify_type, u.user_jabber, u.user_lang - FROM ' . USERS_TABLE . ' u, ' . USER_GROUP_TABLE . ' ug - WHERE ug.group_id = ' . $group_id . ' - AND ug.user_pending = 1 - AND ug.user_id = u.user_id - AND ' . phpbb::$db->sql_in_set('ug.user_id', $user_id_ary); - $result = phpbb::$db->sql_query($sql); - - $user_id_ary = $email_users = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $user_id_ary[] = $row['user_id']; - $email_users[] = $row; - } - phpbb::$db->sql_freeresult($result); - - if (!sizeof($user_id_ary)) - { - return false; - } - - $sql = 'UPDATE ' . USER_GROUP_TABLE . " - SET user_pending = 0 - WHERE group_id = $group_id - AND " . phpbb::$db->sql_in_set('user_id', $user_id_ary); - phpbb::$db->sql_query($sql); - - // Send approved email to users... - include_once(PHPBB_ROOT_PATH . 'includes/functions_messenger.' . PHP_EXT); - $messenger = new messenger(); - - foreach ($email_users as $row) - { - $messenger->template('group_approved', $row['user_lang']); - - $messenger->to($row['user_email'], $row['username']); - $messenger->im($row['user_jabber'], $row['username']); - - $messenger->assign_vars(array( - 'USERNAME' => htmlspecialchars_decode($row['username']), - 'GROUP_NAME' => htmlspecialchars_decode($group_name), - 'U_GROUP' => generate_board_url() . '/ucp.' . PHP_EXT . '?i=groups&mode=membership', - )); - - $messenger->send($row['user_notify_type']); - } - - $messenger->save_queue(); - - $log = 'LOG_USERS_APPROVED'; - break; - - case 'default': - $sql = 'SELECT user_id, group_id FROM ' . USERS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('user_id', $user_id_ary, false, true); - $result = phpbb::$db->sql_query($sql); - - $groups = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if (!isset($groups[$row['group_id']])) - { - $groups[$row['group_id']] = array(); - } - $groups[$row['group_id']][] = $row['user_id']; - } - phpbb::$db->sql_freeresult($result); - - foreach ($groups as $gid => $uids) - { - remove_default_rank($gid, $uids); - remove_default_avatar($gid, $uids); - } - group_set_user_default($group_id, $user_id_ary, $group_attributes); - $log = 'LOG_GROUP_DEFAULTS'; - break; - } - - // Clear permissions cache of relevant users - phpbb::$acl->acl_clear_prefetch($user_id_ary); - - add_log('admin', $log, $group_name, implode(', ', $username_ary)); - - group_update_listings($group_id); - - return false; -} - -/** -* A small version of validate_username to check for a group name's existence. To be called directly. -*/ -function group_validate_groupname($group_id, $group_name) -{ - $group_name = utf8_clean_string($group_name); - - if (!empty($group_id)) - { - $sql = 'SELECT group_name_clean - FROM ' . GROUPS_TABLE . ' - WHERE group_id = ' . (int) $group_id; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if (!$row) - { - return false; - } - - $allowed_groupname = utf8_clean_string($row['group_name']); - - if ($allowed_groupname == $group_name) - { - return false; - } - } - - $sql = 'SELECT group_name - FROM ' . GROUPS_TABLE . " - WHERE group_name_clean = '" . phpbb::$db->sql_escape(utf8_clean_string($group_name)) . "'"; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ($row) - { - return 'GROUP_NAME_TAKEN'; - } - - return false; -} - -/** -* Set users default group -* -* @access private -*/ -function group_set_user_default($group_id, $user_id_ary, $group_attributes = false, $update_listing = false) -{ - if (empty($user_id_ary)) - { - return; - } - - $attribute_ary = array( - 'group_colour' => 'string', - 'group_rank' => 'int', - 'group_avatar' => 'string', - 'group_avatar_type' => 'int', - 'group_avatar_width' => 'int', - 'group_avatar_height' => 'int', - ); - - $sql_ary = array( - 'group_id' => $group_id - ); - - // Were group attributes passed to the function? If not we need to obtain them - if ($group_attributes === false) - { - $sql = 'SELECT ' . implode(', ', array_keys($attribute_ary)) . ' - FROM ' . GROUPS_TABLE . " - WHERE group_id = $group_id"; - $result = phpbb::$db->sql_query($sql); - $group_attributes = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - } - - foreach ($attribute_ary as $attribute => $type) - { - if (isset($group_attributes[$attribute])) - { - // If we are about to set an avatar or rank, we will not overwrite with empty, unless we are not actually changing the default group - if ((strpos($attribute, 'group_avatar') === 0 || strpos($attribute, 'group_rank') === 0) && !$group_attributes[$attribute]) - { - continue; - } - - settype($group_attributes[$attribute], $type); - $sql_ary[str_replace('group_', 'user_', $attribute)] = $group_attributes[$attribute]; - } - } - - // Before we update the user attributes, we will make a list of those having now the group avatar assigned - if (isset($sql_ary['user_avatar'])) - { - // Ok, get the original avatar data from users having an uploaded one (we need to remove these from the filesystem) - $sql = 'SELECT user_id, group_id, user_avatar - FROM ' . USERS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('user_id', $user_id_ary) . ' - AND user_avatar_type = ' . AVATAR_UPLOAD; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - avatar_delete('user', $row); - } - phpbb::$db->sql_freeresult($result); - } - else - { - unset($sql_ary['user_avatar_type']); - unset($sql_ary['user_avatar_height']); - unset($sql_ary['user_avatar_width']); - } - - $sql = 'UPDATE ' . USERS_TABLE . ' SET ' . phpbb::$db->sql_build_array('UPDATE', $sql_ary) . ' - WHERE ' . phpbb::$db->sql_in_set('user_id', $user_id_ary); - phpbb::$db->sql_query($sql); - - if (isset($sql_ary['user_colour'])) - { - // Update any cached colour information for these users - $sql = 'UPDATE ' . FORUMS_TABLE . " SET forum_last_poster_colour = '" . phpbb::$db->sql_escape($sql_ary['user_colour']) . "' - WHERE " . phpbb::$db->sql_in_set('forum_last_poster_id', $user_id_ary); - phpbb::$db->sql_query($sql); - - $sql = 'UPDATE ' . TOPICS_TABLE . " SET topic_first_poster_colour = '" . phpbb::$db->sql_escape($sql_ary['user_colour']) . "' - WHERE " . phpbb::$db->sql_in_set('topic_poster', $user_id_ary); - phpbb::$db->sql_query($sql); - - $sql = 'UPDATE ' . TOPICS_TABLE . " SET topic_last_poster_colour = '" . phpbb::$db->sql_escape($sql_ary['user_colour']) . "' - WHERE " . phpbb::$db->sql_in_set('topic_last_poster_id', $user_id_ary); - phpbb::$db->sql_query($sql); - - if (in_array(phpbb::$config['newest_user_id'], $user_id_ary)) - { - set_config('newest_user_colour', $sql_ary['user_colour'], true); - } - } - - if ($update_listing) - { - group_update_listings($group_id); - } -} - -/** -* Get group name -*/ -function get_group_name($group_id) -{ - $sql = 'SELECT group_name, group_type - FROM ' . GROUPS_TABLE . ' - WHERE group_id = ' . (int) $group_id; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if (!$row) - { - return ''; - } - - return ($row['group_type'] == GROUP_SPECIAL) ? phpbb::$user->lang['G_' . $row['group_name']] : $row['group_name']; -} - -/** -* Obtain either the members of a specified group, the groups the specified user is subscribed to -* or checking if a specified user is in a specified group. This function does not return pending memberships. -* -* Note: Never use this more than once... first group your users/groups -*/ -function group_memberships($group_id_ary = false, $user_id_ary = false, $return_bool = false) -{ - if (!$group_id_ary && !$user_id_ary) - { - return true; - } - - if ($user_id_ary) - { - $user_id_ary = (!is_array($user_id_ary)) ? array($user_id_ary) : $user_id_ary; - } - - if ($group_id_ary) - { - $group_id_ary = (!is_array($group_id_ary)) ? array($group_id_ary) : $group_id_ary; - } - - $sql = 'SELECT ug.*, u.username, u.username_clean, u.user_email - FROM ' . USER_GROUP_TABLE . ' ug, ' . USERS_TABLE . ' u - WHERE ug.user_id = u.user_id - AND ug.user_pending = 0 AND '; - - if ($group_id_ary) - { - $sql .= ' ' . phpbb::$db->sql_in_set('ug.group_id', $group_id_ary); - } - - if ($user_id_ary) - { - $sql .= ($group_id_ary) ? ' AND ' : ' '; - $sql .= phpbb::$db->sql_in_set('ug.user_id', $user_id_ary); - } - - $result = ($return_bool) ? phpbb::$db->sql_query_limit($sql, 1) : phpbb::$db->sql_query($sql); - - $row = phpbb::$db->sql_fetchrow($result); - - if ($return_bool) - { - phpbb::$db->sql_freeresult($result); - return ($row) ? true : false; - } - - if (!$row) - { - return false; - } - - $return = array(); - - do - { - $return[] = $row; - } - while ($row = phpbb::$db->sql_fetchrow($result)); - - phpbb::$db->sql_freeresult($result); - - return $return; -} - -/** -* Re-cache moderators and foes if group has a_ or m_ permissions -*/ -function group_update_listings($group_id) -{ - $hold_ary = phpbb::$acl->acl_group_raw_data($group_id, array('a_', 'm_')); - - if (!sizeof($hold_ary)) - { - return; - } - - $mod_permissions = $admin_permissions = false; - - foreach ($hold_ary as $g_id => $forum_ary) - { - foreach ($forum_ary as $forum_id => $auth_ary) - { - foreach ($auth_ary as $auth_option => $setting) - { - if ($mod_permissions && $admin_permissions) - { - break 3; - } - - if ($setting != phpbb::ACL_YES) - { - continue; - } - - if ($auth_option == 'm_') - { - $mod_permissions = true; - } - - if ($auth_option == 'a_') - { - $admin_permissions = true; - } - } - } - } - - if ($mod_permissions) - { - if (!function_exists('cache_moderators')) - { - include(PHPBB_ROOT_PATH . 'includes/functions_admin.' . PHP_EXT); - } - cache_moderators(); - } - - if ($mod_permissions || $admin_permissions) - { - if (!function_exists('update_foes')) - { - include(PHPBB_ROOT_PATH . 'includes/functions_admin.' . PHP_EXT); - } - update_foes(array($group_id)); - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/libraries/diff/diff.php b/phpBB/includes/libraries/diff/diff.php deleted file mode 100644 index c5249ee3c1..0000000000 --- a/phpBB/includes/libraries/diff/diff.php +++ /dev/null @@ -1,823 +0,0 @@ -<?php -/** -* -* @package diff -* @version $Id$ -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Code from pear.php.net, Text_Diff-1.1.0 package -* http://pear.php.net/package/Text_Diff/ -* -* Modified by phpBB Group to meet our coding standards -* and being able to integrate into phpBB -* -* General API for generating and formatting diffs - the differences between -* two sequences of strings. -* -* Copyright 2004 Geoffrey T. Dairiki <dairiki@dairiki.org> -* Copyright 2004-2008 The Horde Project (http://www.horde.org/) -* -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -*/ -class diff -{ - /** - * Array of changes. - * @var array - */ - var $_edits; - - /** - * Computes diffs between sequences of strings. - * - * @param array $from_lines An array of strings. Typically these are lines from a file. - * @param array $to_lines An array of strings. - */ - function __construct(&$from_content, &$to_content, $preserve_cr = true) - { - $diff_engine = new diff_engine(); - $this->_edits = $diff_engine->diff($from_content, $to_content, $preserve_cr); - } - - /** - * Returns the array of differences. - */ - function get_diff() - { - return $this->_edits; - } - - /** - * returns the number of new (added) lines in a given diff. - * - * @since Text_Diff 1.1.0 - * - * @return integer The number of new lines - */ - function count_added_lines() - { - $count = 0; - - foreach ($this->_edits as $edit) - { - if (is_a($edit, 'diff_op_add') || is_a($edit, 'diff_op_change')) - { - $count += $edit->nfinal(); - } - } - return $count; - } - - /** - * Returns the number of deleted (removed) lines in a given diff. - * - * @since Text_Diff 1.1.0 - * - * @return integer The number of deleted lines - */ - function count_deleted_lines() - { - $count = 0; - - foreach ($this->_edits as $edit) - { - if (is_a($edit, 'diff_op_delete') || is_a($edit, 'diff_op_change')) - { - $count += $edit->norig(); - } - } - return $count; - } - - /** - * Computes a reversed diff. - * - * Example: - * <code> - * $diff = new diff($lines1, $lines2); - * $rev = $diff->reverse(); - * </code> - * - * @return diff A Diff object representing the inverse of the original diff. - * Note that we purposely don't return a reference here, since - * this essentially is a clone() method. - */ - function reverse() - { - if (version_compare(zend_version(), '2', '>')) - { - $rev = clone($this); - } - else - { - $rev = $this; - } - - $rev->_edits = array(); - - foreach ($this->_edits as $edit) - { - $rev->_edits[] = $edit->reverse(); - } - - return $rev; - } - - /** - * Checks for an empty diff. - * - * @return boolean True if two sequences were identical. - */ - function is_empty() - { - foreach ($this->_edits as $edit) - { - if (!is_a($edit, 'diff_op_copy')) - { - return false; - } - } - return true; - } - - /** - * Computes the length of the Longest Common Subsequence (LCS). - * - * This is mostly for diagnostic purposes. - * - * @return integer The length of the LCS. - */ - function lcs() - { - $lcs = 0; - - foreach ($this->_edits as $edit) - { - if (is_a($edit, 'diff_op_copy')) - { - $lcs += sizeof($edit->orig); - } - } - return $lcs; - } - - /** - * Gets the original set of lines. - * - * This reconstructs the $from_lines parameter passed to the constructor. - * - * @return array The original sequence of strings. - */ - function get_original() - { - $lines = array(); - - foreach ($this->_edits as $edit) - { - if ($edit->orig) - { - array_splice($lines, sizeof($lines), 0, $edit->orig); - } - } - return $lines; - } - - /** - * Gets the final set of lines. - * - * This reconstructs the $to_lines parameter passed to the constructor. - * - * @return array The sequence of strings. - */ - function get_final() - { - $lines = array(); - - foreach ($this->_edits as $edit) - { - if ($edit->final) - { - array_splice($lines, sizeof($lines), 0, $edit->final); - } - } - return $lines; - } - - /** - * Removes trailing newlines from a line of text. This is meant to be used with array_walk(). - * - * @param string &$line The line to trim. - * @param integer $key The index of the line in the array. Not used. - */ - function trim_newlines(&$line, $key) - { - $line = str_replace(array("\n", "\r"), '', $line); - } - - /** - * Checks a diff for validity. - * - * This is here only for debugging purposes. - */ - function _check($from_lines, $to_lines) - { - if (serialize($from_lines) != serialize($this->get_original())) - { - trigger_error("[diff] Reconstructed original doesn't match", E_USER_ERROR); - } - - if (serialize($to_lines) != serialize($this->get_final())) - { - trigger_error("[diff] Reconstructed final doesn't match", E_USER_ERROR); - } - - $rev = $this->reverse(); - - if (serialize($to_lines) != serialize($rev->get_original())) - { - trigger_error("[diff] Reversed original doesn't match", E_USER_ERROR); - } - - if (serialize($from_lines) != serialize($rev->get_final())) - { - trigger_error("[diff] Reversed final doesn't match", E_USER_ERROR); - } - - $prevtype = null; - - foreach ($this->_edits as $edit) - { - if ($prevtype == get_class($edit)) - { - trigger_error("[diff] Edit sequence is non-optimal", E_USER_ERROR); - } - $prevtype = get_class($edit); - } - - return true; - } -} - -/** -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -*/ -class mapped_diff extends diff -{ - /** - * Computes a diff between sequences of strings. - * - * This can be used to compute things like case-insensitve diffs, or diffs - * which ignore changes in white-space. - * - * @param array $from_lines An array of strings. - * @param array $to_lines An array of strings. - * @param array $mapped_from_lines This array should have the same size number of elements as $from_lines. - * The elements in $mapped_from_lines and $mapped_to_lines are what is actually - * compared when computing the diff. - * @param array $mapped_to_lines This array should have the same number of elements as $to_lines. - */ - function mapped_diff(&$from_lines, &$to_lines, &$mapped_from_lines, &$mapped_to_lines) - { - if (sizeof($from_lines) != sizeof($mapped_from_lines) || sizeof($to_lines) != sizeof($mapped_to_lines)) - { - return false; - } - - parent::diff($mapped_from_lines, $mapped_to_lines); - - $xi = $yi = 0; - for ($i = 0; $i < sizeof($this->_edits); $i++) - { - $orig = &$this->_edits[$i]->orig; - if (is_array($orig)) - { - $orig = array_slice($from_lines, $xi, sizeof($orig)); - $xi += sizeof($orig); - } - - $final = &$this->_edits[$i]->final; - if (is_array($final)) - { - $final = array_slice($to_lines, $yi, sizeof($final)); - $yi += sizeof($final); - } - } - } -} - -/** -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -* -* @access private -*/ -class diff_op -{ - var $orig; - var $final; - - function &reverse() - { - trigger_error('[diff] Abstract method', E_USER_ERROR); - } - - function norig() - { - return ($this->orig) ? sizeof($this->orig) : 0; - } - - function nfinal() - { - return ($this->final) ? sizeof($this->final) : 0; - } -} - -/** -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -* -* @access private -*/ -class diff_op_copy extends diff_op -{ - function diff_op_copy($orig, $final = false) - { - if (!is_array($final)) - { - $final = $orig; - } - $this->orig = $orig; - $this->final = $final; - } - - function &reverse() - { - $reverse = new diff_op_copy($this->final, $this->orig); - return $reverse; - } -} - -/** -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -* -* @access private -*/ -class diff_op_delete extends diff_op -{ - function diff_op_delete($lines) - { - $this->orig = $lines; - $this->final = false; - } - - function &reverse() - { - $reverse = new diff_op_add($this->orig); - return $reverse; - } -} - -/** -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -* -* @access private -*/ -class diff_op_add extends diff_op -{ - function diff_op_add($lines) - { - $this->final = $lines; - $this->orig = false; - } - - function &reverse() - { - $reverse = new diff_op_delete($this->final); - return $reverse; - } -} - -/** -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -* -* @access private -*/ -class diff_op_change extends diff_op -{ - function diff_op_change($orig, $final) - { - $this->orig = $orig; - $this->final = $final; - } - - function &reverse() - { - $reverse = new diff_op_change($this->final, $this->orig); - return $reverse; - } -} - - -/** -* A class for computing three way diffs. -* -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -*/ -class diff3 extends diff -{ - /** - * Conflict counter. - * @var integer - */ - var $_conflicting_blocks = 0; - - /** - * Computes diff between 3 sequences of strings. - * - * @param array $orig The original lines to use. - * @param array $final1 The first version to compare to. - * @param array $final2 The second version to compare to. - */ - function diff3(&$orig, &$final1, &$final2) - { - $diff_engine = new diff_engine(); - - $diff_1 = $diff_engine->diff($orig, $final1); - $diff_2 = $diff_engine->diff($orig, $final2); - - unset($engine); - - $this->_edits = $this->_diff3($diff_1, $diff_2); - } - - /** - * Return number of conflicts - */ - function get_num_conflicts() - { - $conflicts = 0; - - foreach ($this->_edits as $edit) - { - if ($edit->is_conflict()) - { - $conflicts++; - } - } - - return $conflicts; - } - - /** - * Get conflicts content for download. This is generally a merged file, but preserving conflicts and adding explanations to it. - * A user could then go through this file, search for the conflicts and changes the code accordingly. - * - * @param string $label1 the cvs file version/label from the original set of lines - * @param string $label2 the cvs file version/label from the new set of lines - * @param string $label_sep the explanation between label1 and label2 - more of a helper for the user - * - * @return mixed the merged output - */ - function get_conflicts_content($label1 = 'CURRENT_FILE', $label2 = 'NEW_FILE', $label_sep = 'DIFF_SEP_EXPLAIN') - { - $label1 = (!empty(phpbb::$user->lang[$label1])) ? phpbb::$user->lang[$label1] : $label1; - $label2 = (!empty(phpbb::$user->lang[$label2])) ? phpbb::$user->lang[$label2] : $label2; - $label_sep = (!empty(phpbb::$user->lang[$label_sep])) ? phpbb::$user->lang[$label_sep] : $label_sep; - - $lines = array(); - - foreach ($this->_edits as $edit) - { - if ($edit->is_conflict()) - { - // Start conflict label - $label_start = array('<<<<<<< ' . $label1); - $label_mid = array('======= ' . $label_sep); - $label_end = array('>>>>>>> ' . $label2); - - $lines = array_merge($lines, $label_start, $edit->final1, $label_mid, $edit->final2, $label_end); - } - else - { - $lines = array_merge($lines, $edit->merged()); - } - } - - return $lines; - } - - /** - * Merge the output and use the new file code for conflicts - */ - function merged_new_output() - { - $lines = array(); - - foreach ($this->_edits as $edit) - { - if ($edit->is_conflict()) - { - $lines = array_merge($lines, $edit->final2); - } - else - { - $lines = array_merge($lines, $edit->merged()); - } - } - - return $lines; - } - - /** - * Merge the output and use the original file code for conflicts - */ - function merged_orig_output() - { - $lines = array(); - - foreach ($this->_edits as $edit) - { - if ($edit->is_conflict()) - { - $lines = array_merge($lines, $edit->final1); - } - else - { - $lines = array_merge($lines, $edit->merged()); - } - } - - return $lines; - } - - /** - * Get conflicting block(s) - */ - function get_conflicts() - { - $conflicts = array(); - - foreach ($this->_edits as $edit) - { - if ($edit->is_conflict()) - { - $conflicts[] = array($edit->final1, $edit->final2); - } - } - - return $conflicts; - } - - /** - * @access private - */ - function _diff3(&$edits1, &$edits2) - { - $edits = array(); - $bb = new diff3_block_builder(); - - $e1 = current($edits1); - $e2 = current($edits2); - - while ($e1 || $e2) - { - if ($e1 && $e2 && is_a($e1, 'diff_op_copy') && is_a($e2, 'diff_op_copy')) - { - // We have copy blocks from both diffs. This is the (only) time we want to emit a diff3 copy block. - // Flush current diff3 diff block, if any. - if ($edit = $bb->finish()) - { - $edits[] = $edit; - } - - $ncopy = min($e1->norig(), $e2->norig()); - $edits[] = new diff3_op_copy(array_slice($e1->orig, 0, $ncopy)); - - if ($e1->norig() > $ncopy) - { - array_splice($e1->orig, 0, $ncopy); - array_splice($e1->final, 0, $ncopy); - } - else - { - $e1 = next($edits1); - } - - if ($e2->norig() > $ncopy) - { - array_splice($e2->orig, 0, $ncopy); - array_splice($e2->final, 0, $ncopy); - } - else - { - $e2 = next($edits2); - } - } - else - { - if ($e1 && $e2) - { - if ($e1->orig && $e2->orig) - { - $norig = min($e1->norig(), $e2->norig()); - $orig = array_splice($e1->orig, 0, $norig); - array_splice($e2->orig, 0, $norig); - $bb->input($orig); - } - else - { - $norig = 0; - } - - if (is_a($e1, 'diff_op_copy')) - { - $bb->out1(array_splice($e1->final, 0, $norig)); - } - - if (is_a($e2, 'diff_op_copy')) - { - $bb->out2(array_splice($e2->final, 0, $norig)); - } - } - - if ($e1 && ! $e1->orig) - { - $bb->out1($e1->final); - $e1 = next($edits1); - } - - if ($e2 && ! $e2->orig) - { - $bb->out2($e2->final); - $e2 = next($edits2); - } - } - } - - if ($edit = $bb->finish()) - { - $edits[] = $edit; - } - - return $edits; - } -} - -/** -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -* -* @access private -*/ -class diff3_op -{ - function __construct($orig = false, $final1 = false, $final2 = false) - { - $this->orig = $orig ? $orig : array(); - $this->final1 = $final1 ? $final1 : array(); - $this->final2 = $final2 ? $final2 : array(); - } - - function merged() - { - if (!isset($this->_merged)) - { - if ($this->final1 === $this->final2) - { - $this->_merged = &$this->final1; - } - else if ($this->final1 === $this->orig) - { - $this->_merged = &$this->final2; - } - else if ($this->final2 === $this->orig) - { - $this->_merged = &$this->final1; - } - else - { - $this->_merged = false; - } - } - - return $this->_merged; - } - - function is_conflict() - { - return ($this->merged() === false) ? true : false; - } -} - -/** -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -* -* @access private -*/ -class diff3_op_copy extends diff3_op -{ - function diff3_op_copy($lines = false) - { - $this->orig = $lines ? $lines : array(); - $this->final1 = &$this->orig; - $this->final2 = &$this->orig; - } - - function merged() - { - return $this->orig; - } - - function is_conflict() - { - return false; - } -} - -/** -* @package diff -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -* -* @access private -*/ -class diff3_block_builder -{ - function __construct() - { - $this->_init(); - } - - function input($lines) - { - if ($lines) - { - $this->_append($this->orig, $lines); - } - } - - function out1($lines) - { - if ($lines) - { - $this->_append($this->final1, $lines); - } - } - - function out2($lines) - { - if ($lines) - { - $this->_append($this->final2, $lines); - } - } - - function is_empty() - { - return !$this->orig && !$this->final1 && !$this->final2; - } - - function finish() - { - if ($this->is_empty()) - { - return false; - } - else - { - $edit = new diff3_op($this->orig, $this->final1, $this->final2); - $this->_init(); - return $edit; - } - } - - function _init() - { - $this->orig = $this->final1 = $this->final2 = array(); - } - - function _append(&$array, $lines) - { - array_splice($array, sizeof($array), 0, $lines); - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/libraries/diff/engine.php b/phpBB/includes/libraries/diff/engine.php deleted file mode 100644 index eb0dcce395..0000000000 --- a/phpBB/includes/libraries/diff/engine.php +++ /dev/null @@ -1,536 +0,0 @@ -<?php -/** -* -* @package diff -* @version $Id$ -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Code from pear.php.net, Text_Diff-1.1.0 package -* http://pear.php.net/package/Text_Diff/ (native engine) -* -* Modified by phpBB Group to meet our coding standards -* and being able to integrate into phpBB -* -* Class used internally by Text_Diff to actually compute the diffs. This -* class is implemented using native PHP code. -* -* The algorithm used here is mostly lifted from the perl module -* Algorithm::Diff (version 1.06) by Ned Konz, which is available at: -* http://www.perl.com/CPAN/authors/id/N/NE/NEDKONZ/Algorithm-Diff-1.06.zip -* -* More ideas are taken from: http://www.ics.uci.edu/~eppstein/161/960229.html -* -* Some ideas (and a bit of code) are taken from analyze.c, of GNU -* diffutils-2.7, which can be found at: -* ftp://gnudist.gnu.org/pub/gnu/diffutils/diffutils-2.7.tar.gz -* -* Some ideas (subdivision by NCHUNKS > 2, and some optimizations) are from -* Geoffrey T. Dairiki <dairiki@dairiki.org>. The original PHP version of this -* code was written by him, and is used/adapted with his permission. -* -* Copyright 2004-2008 The Horde Project (http://www.horde.org/) -* -* @author Geoffrey T. Dairiki <dairiki@dairiki.org> -* @package diff -* -* @access private -*/ -class diff_engine -{ - function diff(&$from_lines, &$to_lines, $preserve_cr = true) - { - // Remove empty lines... - // If preserve_cr is true, we basically only change \r\n and bare \r to \n to get the same carriage returns for both files - // If it is false, we try to only use \n once per line and ommit all empty lines to be able to get a proper data diff - - if (is_array($from_lines)) - { - $from_lines = implode("\n", $from_lines); - } - - if (is_array($to_lines)) - { - $to_lines = implode("\n", $to_lines); - } - - if ($preserve_cr) - { - $from_lines = explode("\n", str_replace("\r", "\n", str_replace("\r\n", "\n", $from_lines))); - $to_lines = explode("\n", str_replace("\r", "\n", str_replace("\r\n", "\n", $to_lines))); - } - else - { - $from_lines = explode("\n", preg_replace('#[\n\r]+#', "\n", $from_lines)); - $to_lines = explode("\n", preg_replace('#[\n\r]+#', "\n", $to_lines)); - } - - $n_from = sizeof($from_lines); - $n_to = sizeof($to_lines); - - $this->xchanged = $this->ychanged = $this->xv = $this->yv = $this->xind = $this->yind = array(); - unset($this->seq, $this->in_seq, $this->lcs); - - // Skip leading common lines. - for ($skip = 0; $skip < $n_from && $skip < $n_to; $skip++) - { - if ($from_lines[$skip] !== $to_lines[$skip]) - { - break; - } - $this->xchanged[$skip] = $this->ychanged[$skip] = false; - } - - // Skip trailing common lines. - $xi = $n_from; - $yi = $n_to; - - for ($endskip = 0; --$xi > $skip && --$yi > $skip; $endskip++) - { - if ($from_lines[$xi] !== $to_lines[$yi]) - { - break; - } - $this->xchanged[$xi] = $this->ychanged[$yi] = false; - } - - // Ignore lines which do not exist in both files. - for ($xi = $skip; $xi < $n_from - $endskip; $xi++) - { - $xhash[$from_lines[$xi]] = 1; - } - - for ($yi = $skip; $yi < $n_to - $endskip; $yi++) - { - $line = $to_lines[$yi]; - - if (($this->ychanged[$yi] = empty($xhash[$line]))) - { - continue; - } - $yhash[$line] = 1; - $this->yv[] = $line; - $this->yind[] = $yi; - } - - for ($xi = $skip; $xi < $n_from - $endskip; $xi++) - { - $line = $from_lines[$xi]; - - if (($this->xchanged[$xi] = empty($yhash[$line]))) - { - continue; - } - $this->xv[] = $line; - $this->xind[] = $xi; - } - - // Find the LCS. - $this->_compareseq(0, sizeof($this->xv), 0, sizeof($this->yv)); - - // Merge edits when possible. - $this->_shift_boundaries($from_lines, $this->xchanged, $this->ychanged); - $this->_shift_boundaries($to_lines, $this->ychanged, $this->xchanged); - - // Compute the edit operations. - $edits = array(); - $xi = $yi = 0; - - while ($xi < $n_from || $yi < $n_to) - { - // Skip matching "snake". - $copy = array(); - - while ($xi < $n_from && $yi < $n_to && !$this->xchanged[$xi] && !$this->ychanged[$yi]) - { - $copy[] = $from_lines[$xi++]; - $yi++; - } - - if ($copy) - { - $edits[] = new diff_op_copy($copy); - } - - // Find deletes & adds. - $delete = array(); - while ($xi < $n_from && $this->xchanged[$xi]) - { - $delete[] = $from_lines[$xi++]; - } - - $add = array(); - while ($yi < $n_to && $this->ychanged[$yi]) - { - $add[] = $to_lines[$yi++]; - } - - if ($delete && $add) - { - $edits[] = new diff_op_change($delete, $add); - } - else if ($delete) - { - $edits[] = new diff_op_delete($delete); - } - else if ($add) - { - $edits[] = new diff_op_add($add); - } - } - - return $edits; - } - - /** - * Divides the Largest Common Subsequence (LCS) of the sequences (XOFF, - * XLIM) and (YOFF, YLIM) into NCHUNKS approximately equally sized segments. - * - * Returns (LCS, PTS). LCS is the length of the LCS. PTS is an array of - * NCHUNKS+1 (X, Y) indexes giving the diving points between sub - * sequences. The first sub-sequence is contained in (X0, X1), (Y0, Y1), - * the second in (X1, X2), (Y1, Y2) and so on. Note that (X0, Y0) == - * (XOFF, YOFF) and (X[NCHUNKS], Y[NCHUNKS]) == (XLIM, YLIM). - * - * This function assumes that the first lines of the specified portions of - * the two files do not match, and likewise that the last lines do not - * match. The caller must trim matching lines from the beginning and end - * of the portions it is going to specify. - */ - function _diag($xoff, $xlim, $yoff, $ylim, $nchunks) - { - $flip = false; - - if ($xlim - $xoff > $ylim - $yoff) - { - // Things seems faster (I'm not sure I understand why) when the shortest sequence is in X. - $flip = true; - list($xoff, $xlim, $yoff, $ylim) = array($yoff, $ylim, $xoff, $xlim); - } - - if ($flip) - { - for ($i = $ylim - 1; $i >= $yoff; $i--) - { - $ymatches[$this->xv[$i]][] = $i; - } - } - else - { - for ($i = $ylim - 1; $i >= $yoff; $i--) - { - $ymatches[$this->yv[$i]][] = $i; - } - } - - $this->lcs = 0; - $this->seq[0]= $yoff - 1; - $this->in_seq = array(); - $ymids[0] = array(); - - $numer = $xlim - $xoff + $nchunks - 1; - $x = $xoff; - - for ($chunk = 0; $chunk < $nchunks; $chunk++) - { - if ($chunk > 0) - { - for ($i = 0; $i <= $this->lcs; $i++) - { - $ymids[$i][$chunk - 1] = $this->seq[$i]; - } - } - - $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $chunk) / $nchunks); - - for (; $x < $x1; $x++) - { - $line = $flip ? $this->yv[$x] : $this->xv[$x]; - if (empty($ymatches[$line])) - { - continue; - } - $matches = $ymatches[$line]; - - reset($matches); - while (list(, $y) = each($matches)) - { - if (empty($this->in_seq[$y])) - { - $k = $this->_lcs_pos($y); - $ymids[$k] = $ymids[$k - 1]; - break; - } - } - - // no reset() here - while (list(, $y) = each($matches)) - { - if ($y > $this->seq[$k - 1]) - { - // Optimization: this is a common case: next match is just replacing previous match. - $this->in_seq[$this->seq[$k]] = false; - $this->seq[$k] = $y; - $this->in_seq[$y] = 1; - } - else if (empty($this->in_seq[$y])) - { - $k = $this->_lcs_pos($y); - $ymids[$k] = $ymids[$k - 1]; - } - } - } - } - - $seps[] = $flip ? array($yoff, $xoff) : array($xoff, $yoff); - $ymid = $ymids[$this->lcs]; - - for ($n = 0; $n < $nchunks - 1; $n++) - { - $x1 = $xoff + (int)(($numer + ($xlim - $xoff) * $n) / $nchunks); - $y1 = $ymid[$n] + 1; - $seps[] = $flip ? array($y1, $x1) : array($x1, $y1); - } - $seps[] = $flip ? array($ylim, $xlim) : array($xlim, $ylim); - - return array($this->lcs, $seps); - } - - function _lcs_pos($ypos) - { - $end = $this->lcs; - - if ($end == 0 || $ypos > $this->seq[$end]) - { - $this->seq[++$this->lcs] = $ypos; - $this->in_seq[$ypos] = 1; - return $this->lcs; - } - - $beg = 1; - while ($beg < $end) - { - $mid = (int)(($beg + $end) / 2); - if ($ypos > $this->seq[$mid]) - { - $beg = $mid + 1; - } - else - { - $end = $mid; - } - } - - $this->in_seq[$this->seq[$end]] = false; - $this->seq[$end] = $ypos; - $this->in_seq[$ypos] = 1; - - return $end; - } - - /** - * Finds LCS of two sequences. - * - * The results are recorded in the vectors $this->{x,y}changed[], by - * storing a 1 in the element for each line that is an insertion or - * deletion (ie. is not in the LCS). - * - * The subsequence of file 0 is (XOFF, XLIM) and likewise for file 1. - * - * Note that XLIM, YLIM are exclusive bounds. All line numbers are - * origin-0 and discarded lines are not counted. - */ - function _compareseq($xoff, $xlim, $yoff, $ylim) - { - // Slide down the bottom initial diagonal. - while ($xoff < $xlim && $yoff < $ylim && $this->xv[$xoff] == $this->yv[$yoff]) - { - ++$xoff; - ++$yoff; - } - - // Slide up the top initial diagonal. - while ($xlim > $xoff && $ylim > $yoff && $this->xv[$xlim - 1] == $this->yv[$ylim - 1]) - { - --$xlim; - --$ylim; - } - - if ($xoff == $xlim || $yoff == $ylim) - { - $lcs = 0; - } - else - { - // This is ad hoc but seems to work well. - // $nchunks = sqrt(min($xlim - $xoff, $ylim - $yoff) / 2.5); - // $nchunks = max(2,min(8,(int)$nchunks)); - $nchunks = min(7, $xlim - $xoff, $ylim - $yoff) + 1; - list($lcs, $seps) = $this->_diag($xoff, $xlim, $yoff, $ylim, $nchunks); - } - - if ($lcs == 0) - { - // X and Y sequences have no common subsequence: mark all changed. - while ($yoff < $ylim) - { - $this->ychanged[$this->yind[$yoff++]] = 1; - } - - while ($xoff < $xlim) - { - $this->xchanged[$this->xind[$xoff++]] = 1; - } - } - else - { - // Use the partitions to split this problem into subproblems. - reset($seps); - $pt1 = $seps[0]; - - while ($pt2 = next($seps)) - { - $this->_compareseq($pt1[0], $pt2[0], $pt1[1], $pt2[1]); - $pt1 = $pt2; - } - } - } - - /** - * Adjusts inserts/deletes of identical lines to join changes as much as possible. - * - * We do something when a run of changed lines include a line at one end - * and has an excluded, identical line at the other. We are free to - * choose which identical line is included. 'compareseq' usually chooses - * the one at the beginning, but usually it is cleaner to consider the - * following identical line to be the "change". - * - * This is extracted verbatim from analyze.c (GNU diffutils-2.7). - */ - function _shift_boundaries($lines, &$changed, $other_changed) - { - $i = 0; - $j = 0; - - $len = sizeof($lines); - $other_len = sizeof($other_changed); - - while (1) - { - // Scan forward to find the beginning of another run of - // changes. Also keep track of the corresponding point in the other file. - // - // Throughout this code, $i and $j are adjusted together so that - // the first $i elements of $changed and the first $j elements of - // $other_changed both contain the same number of zeros (unchanged lines). - // - // Furthermore, $j is always kept so that $j == $other_len or $other_changed[$j] == false. - while ($j < $other_len && $other_changed[$j]) - { - $j++; - } - - while ($i < $len && ! $changed[$i]) - { - $i++; - $j++; - - while ($j < $other_len && $other_changed[$j]) - { - $j++; - } - } - - if ($i == $len) - { - break; - } - - $start = $i; - - // Find the end of this run of changes. - while (++$i < $len && $changed[$i]) - { - continue; - } - - do - { - // Record the length of this run of changes, so that we can later determine whether the run has grown. - $runlength = $i - $start; - - // Move the changed region back, so long as the previous unchanged line matches the last changed one. - // This merges with previous changed regions. - while ($start > 0 && $lines[$start - 1] == $lines[$i - 1]) - { - $changed[--$start] = 1; - $changed[--$i] = false; - - while ($start > 0 && $changed[$start - 1]) - { - $start--; - } - - while ($other_changed[--$j]) - { - continue; - } - } - - // Set CORRESPONDING to the end of the changed run, at the last point where it corresponds to a changed run in the - // other file. CORRESPONDING == LEN means no such point has been found. - $corresponding = $j < $other_len ? $i : $len; - - // Move the changed region forward, so long as the first changed line matches the following unchanged one. - // This merges with following changed regions. - // Do this second, so that if there are no merges, the changed region is moved forward as far as possible. - while ($i < $len && $lines[$start] == $lines[$i]) - { - $changed[$start++] = false; - $changed[$i++] = 1; - - while ($i < $len && $changed[$i]) - { - $i++; - } - - $j++; - if ($j < $other_len && $other_changed[$j]) - { - $corresponding = $i; - while ($j < $other_len && $other_changed[$j]) - { - $j++; - } - } - } - } - while ($runlength != $i - $start); - - // If possible, move the fully-merged run of changes back to a corresponding run in the other file. - while ($corresponding < $i) - { - $changed[--$start] = 1; - $changed[--$i] = 0; - - while ($other_changed[--$j]) - { - continue; - } - } - } - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/libraries/diff/renderer.php b/phpBB/includes/libraries/diff/renderer.php deleted file mode 100644 index 2d3ab88a26..0000000000 --- a/phpBB/includes/libraries/diff/renderer.php +++ /dev/null @@ -1,858 +0,0 @@ -<?php -/** -* -* @package diff -* @version $Id$ -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* Code from pear.php.net, Text_Diff-1.1.0 package -* http://pear.php.net/package/Text_Diff/ -* -* Modified by phpBB Group to meet our coding standards -* and being able to integrate into phpBB -* -* A class to render Diffs in different formats. -* -* This class renders the diff in classic diff format. It is intended that -* this class be customized via inheritance, to obtain fancier outputs. -* -* Copyright 2004-2008 The Horde Project (http://www.horde.org/) -* -* @package diff -*/ -class diff_renderer -{ - /** - * Number of leading context "lines" to preserve. - * - * This should be left at zero for this class, but subclasses may want to - * set this to other values. - */ - var $_leading_context_lines = 0; - - /** - * Number of trailing context "lines" to preserve. - * - * This should be left at zero for this class, but subclasses may want to - * set this to other values. - */ - var $_trailing_context_lines = 0; - - /** - * Constructor. - */ - function __construct($params = array()) - { - foreach ($params as $param => $value) - { - $v = '_' . $param; - if (isset($this->$v)) - { - $this->$v = $value; - } - } - } - - /** - * Get any renderer parameters. - * - * @return array All parameters of this renderer object. - */ - function get_params() - { - $params = array(); - foreach (get_object_vars($this) as $k => $v) - { - if ($k[0] == '_') - { - $params[substr($k, 1)] = $v; - } - } - - return $params; - } - - /** - * Renders a diff. - * - * @param diff &$diff A diff object. - * - * @return string The formatted output. - */ - function render(&$diff) - { - $xi = $yi = 1; - $block = false; - $context = array(); - - // Create a new diff object if it is a 3-way diff - if (is_a($diff, 'diff3')) - { - $diff3 = &$diff; - - $diff_1 = $diff3->get_original(); - $diff_2 = $diff3->merged_output(); - - unset($diff3); - - $diff = new diff($diff_1, $diff_2); - } - - $nlead = $this->_leading_context_lines; - $ntrail = $this->_trailing_context_lines; - - $output = $this->_start_diff(); - $diffs = $diff->get_diff(); - - foreach ($diffs as $i => $edit) - { - // If these are unchanged (copied) lines, and we want to keep leading or trailing context lines, extract them from the copy block. - if (is_a($edit, 'diff_op_copy')) - { - // Do we have any diff blocks yet? - if (is_array($block)) - { - // How many lines to keep as context from the copy block. - $keep = ($i == sizeof($diffs) - 1) ? $ntrail : $nlead + $ntrail; - if (sizeof($edit->orig) <= $keep) - { - // We have less lines in the block than we want for context => keep the whole block. - $block[] = $edit; - } - else - { - if ($ntrail) - { - // Create a new block with as many lines as we need for the trailing context. - $context = array_slice($edit->orig, 0, $ntrail); - $block[] = new diff_op_copy($context); - } - - $output .= $this->_block($x0, $ntrail + $xi - $x0, $y0, $ntrail + $yi - $y0, $block); - $block = false; - } - } - // Keep the copy block as the context for the next block. - $context = $edit->orig; - } - else - { - // Don't we have any diff blocks yet? - if (!is_array($block)) - { - // Extract context lines from the preceding copy block. - $context = array_slice($context, sizeof($context) - $nlead); - $x0 = $xi - sizeof($context); - $y0 = $yi - sizeof($context); - $block = array(); - - if ($context) - { - $block[] = new diff_op_copy($context); - } - } - $block[] = $edit; - } - - $xi += ($edit->orig) ? sizeof($edit->orig) : 0; - $yi += ($edit->final) ? sizeof($edit->final) : 0; - } - - if (is_array($block)) - { - $output .= $this->_block($x0, $xi - $x0, $y0, $yi - $y0, $block); - } - - return $output . $this->_end_diff(); - } - - function _block($xbeg, $xlen, $ybeg, $ylen, &$edits) - { - $output = $this->_start_block($this->_block_header($xbeg, $xlen, $ybeg, $ylen)); - - foreach ($edits as $edit) - { - switch (get_class($edit)) - { - case 'diff_op_copy': - $output .= $this->_context($edit->orig); - break; - - case 'diff_op_add': - $output .= $this->_added($edit->final); - break; - - case 'diff_op_delete': - $output .= $this->_deleted($edit->orig); - break; - - case 'diff_op_change': - $output .= $this->_changed($edit->orig, $edit->final); - break; - } - } - - return $output . $this->_end_block(); - } - - function _start_diff() - { - return ''; - } - - function _end_diff() - { - return ''; - } - - function _block_header($xbeg, $xlen, $ybeg, $ylen) - { - if ($xlen > 1) - { - $xbeg .= ',' . ($xbeg + $xlen - 1); - } - - if ($ylen > 1) - { - $ybeg .= ',' . ($ybeg + $ylen - 1); - } - - // this matches the GNU Diff behaviour - if ($xlen && !$ylen) - { - $ybeg--; - } - else if (!$xlen) - { - $xbeg--; - } - - return $xbeg . ($xlen ? ($ylen ? 'c' : 'd') : 'a') . $ybeg; - } - - function _start_block($header) - { - return $header . "\n"; - } - - function _end_block() - { - return ''; - } - - function _lines($lines, $prefix = ' ') - { - return $prefix . implode("\n$prefix", $lines) . "\n"; - } - - function _context($lines) - { - return $this->_lines($lines, ' '); - } - - function _added($lines) - { - return $this->_lines($lines, '> '); - } - - function _deleted($lines) - { - return $this->_lines($lines, '< '); - } - - function _changed($orig, $final) - { - return $this->_deleted($orig) . "---\n" . $this->_added($final); - } - - /** - * Our function to get the diff - */ - function get_diff_content($diff) - { - return $this->render($diff); - } -} - -/** -* Renders a unified diff -* @package diff -*/ -class diff_renderer_unified extends diff_renderer -{ - var $_leading_context_lines = 4; - var $_trailing_context_lines = 4; - - /** - * Our function to get the diff - */ - function get_diff_content($diff) - { - return nl2br($this->render($diff)); - } - - function _block_header($xbeg, $xlen, $ybeg, $ylen) - { - if ($xlen != 1) - { - $xbeg .= ',' . $xlen; - } - - if ($ylen != 1) - { - $ybeg .= ',' . $ylen; - } - return '<div class="diff"><big class="info">@@ -' . $xbeg . ' +' . $ybeg . ' @@</big></div>'; - } - - function _context($lines) - { - return '<pre class="diff context">' . htmlspecialchars($this->_lines($lines, ' ')) . '<br /></pre>'; - } - - function _added($lines) - { - return '<pre class="diff added">' . htmlspecialchars($this->_lines($lines, '+')) . '<br /></pre>'; - } - - function _deleted($lines) - { - return '<pre class="diff removed">' . htmlspecialchars($this->_lines($lines, '-')) . '<br /></pre>'; - } - - function _changed($orig, $final) - { - return $this->_deleted($orig) . $this->_added($final); - } - - function _start_diff() - { - $start = '<div class="file">'; - - return $start; - } - - function _end_diff() - { - return '</div>'; - } - - function _end_block() - { - return ''; - } -} - -/** -* "Inline" diff renderer. -* -* This class renders diffs in the Wiki-style "inline" format. -* -* @author Ciprian Popovici -* @package diff -*/ -class diff_renderer_inline extends diff_renderer -{ - var $_leading_context_lines = 10000; - var $_trailing_context_lines = 10000; - - // Prefix and suffix for inserted text - var $_ins_prefix = '<span class="ins">'; - var $_ins_suffix = '</span>'; - - // Prefix and suffix for deleted text - var $_del_prefix = '<span class="del">'; - var $_del_suffix = '</span>'; - - var $_block_head = ''; - - // What are we currently splitting on? Used to recurse to show word-level - var $_split_level = 'lines'; - - /** - * Our function to get the diff - */ - function get_diff_content($diff) - { - return '<pre>' . nl2br($this->render($diff)) . '<br /></pre>'; - } - - function _start_diff() - { - return ''; - } - - function _end_diff() - { - return ''; - } - - function _block_header($xbeg, $xlen, $ybeg, $ylen) - { - return $this->_block_head; - } - - function _start_block($header) - { - return $header; - } - - function _lines($lines, $prefix = ' ', $encode = true) - { - if ($encode) - { - array_walk($lines, array(&$this, '_encode')); - } - - if ($this->_split_level == 'words') - { - return implode('', $lines); - } - else - { - return implode("\n", $lines) . "\n"; - } - } - - function _added($lines) - { - array_walk($lines, array(&$this, '_encode')); - $lines[0] = $this->_ins_prefix . $lines[0]; - $lines[sizeof($lines) - 1] .= $this->_ins_suffix; - return $this->_lines($lines, ' ', false); - } - - function _deleted($lines, $words = false) - { - array_walk($lines, array(&$this, '_encode')); - $lines[0] = $this->_del_prefix . $lines[0]; - $lines[sizeof($lines) - 1] .= $this->_del_suffix; - return $this->_lines($lines, ' ', false); - } - - function _changed($orig, $final) - { - // If we've already split on words, don't try to do so again - just display. - if ($this->_split_level == 'words') - { - $prefix = ''; - while ($orig[0] !== false && $final[0] !== false && substr($orig[0], 0, 1) == ' ' && substr($final[0], 0, 1) == ' ') - { - $prefix .= substr($orig[0], 0, 1); - $orig[0] = substr($orig[0], 1); - $final[0] = substr($final[0], 1); - } - - return $prefix . $this->_deleted($orig) . $this->_added($final); - } - - $text1 = implode("\n", $orig); - $text2 = implode("\n", $final); - - // Non-printing newline marker. - $nl = "\0"; - - // We want to split on word boundaries, but we need to preserve whitespace as well. - // Therefore we split on words, but include all blocks of whitespace in the wordlist. - $splitted_text_1 = $this->_split_on_words($text1, $nl); - $splitted_text_2 = $this->_split_on_words($text2, $nl); - - $diff = new diff($splitted_text_1, $splitted_text_2); - unset($splitted_text_1, $splitted_text_2); - - // Get the diff in inline format. - $renderer = new diff_renderer_inline(array_merge($this->get_params(), array('split_level' => 'words'))); - - // Run the diff and get the output. - return str_replace($nl, "\n", $renderer->render($diff)) . "\n"; - } - - function _split_on_words($string, $newline_escape = "\n") - { - // Ignore \0; otherwise the while loop will never finish. - $string = str_replace("\0", '', $string); - - $words = array(); - $length = strlen($string); - $pos = 0; - - $tab_there = true; - while ($pos < $length) - { - // Check for tabs... do not include them - if ($tab_there && substr($string, $pos, 1) === "\t") - { - $words[] = "\t"; - $pos++; - - continue; - } - else - { - $tab_there = false; - } - - // Eat a word with any preceding whitespace. - $spaces = strspn(substr($string, $pos), " \n"); - $nextpos = strcspn(substr($string, $pos + $spaces), " \n"); - $words[] = str_replace("\n", $newline_escape, substr($string, $pos, $spaces + $nextpos)); - $pos += $spaces + $nextpos; - } - - return $words; - } - - function _encode(&$string) - { - $string = htmlspecialchars($string); - } -} - -/** -* "raw" diff renderer. -* This class could be used to output a raw unified patch file -* -* @package diff -*/ -class diff_renderer_raw extends diff_renderer -{ - var $_leading_context_lines = 4; - var $_trailing_context_lines = 4; - - /** - * Our function to get the diff - */ - function get_diff_content($diff) - { - return '<textarea style="height: 290px;" class="full">' . htmlspecialchars($this->render($diff)) . '</textarea>'; - } - - function _block_header($xbeg, $xlen, $ybeg, $ylen) - { - if ($xlen != 1) - { - $xbeg .= ',' . $xlen; - } - - if ($ylen != 1) - { - $ybeg .= ',' . $ylen; - } - return '@@ -' . $xbeg . ' +' . $ybeg . ' @@'; - } - - function _context($lines) - { - return $this->_lines($lines, ' '); - } - - function _added($lines) - { - return $this->_lines($lines, '+'); - } - - function _deleted($lines) - { - return $this->_lines($lines, '-'); - } - - function _changed($orig, $final) - { - return $this->_deleted($orig) . $this->_added($final); - } -} - -/** -* "chora (Horde)" diff renderer - similar style. -* This renderer class is a modified human_readable function from the Horde Framework. -* -* @package diff -*/ -class diff_renderer_side_by_side extends diff_renderer -{ - var $_leading_context_lines = 3; - var $_trailing_context_lines = 3; - - var $lines = array(); - - // Hold the left and right columns of lines for change blocks. - var $cols; - var $state; - - var $data = false; - - /** - * Our function to get the diff - */ - function get_diff_content($diff) - { - $output = ''; - $output .= '<table cellspacing="0" class="hrdiff"> -<caption> - <span class="unmodified"> </span> ' . phpbb::$user->lang['LINE_UNMODIFIED'] . ' - <span class="added"> </span> ' . phpbb::$user->lang['LINE_ADDED'] . ' - <span class="modified"> </span> ' . phpbb::$user->lang['LINE_MODIFIED'] . ' - <span class="removed"> </span> ' . phpbb::$user->lang['LINE_REMOVED'] . ' -</caption> -<tbody> -'; - - $this->render($diff); - - // Is the diff empty? - if (!sizeof($this->lines)) - { - $output .= '<tr><th colspan="2">' . phpbb::$user->lang['NO_VISIBLE_CHANGES'] . '</th></tr>'; - } - else - { - // Iterate through every header block of changes - foreach ($this->lines as $header) - { - $output .= '<tr><th>' . phpbb::$user->lang['LINE'] . ' ' . $header['oldline'] . '</th><th>' . phpbb::$user->lang['LINE'] . ' ' . $header['newline'] . '</th></tr>'; - - // Each header block consists of a number of changes (add, remove, change). - $current_context = ''; - - foreach ($header['contents'] as $change) - { - if (!empty($current_context) && $change['type'] != 'empty') - { - $line = $current_context; - $current_context = ''; - - $output .= '<tr class="unmodified"><td><pre>' . ((strlen($line)) ? $line : ' ') . '<br /></pre></td> - <td><pre>' . ((strlen($line)) ? $line : ' ') . '<br /></pre></td></tr>'; - } - - switch ($change['type']) - { - case 'add': - $line = ''; - - foreach ($change['lines'] as $_line) - { - $line .= htmlspecialchars($_line) . '<br />'; - } - - $output .= '<tr><td class="added_empty"> </td><td class="added"><pre>' . ((strlen($line)) ? $line : ' ') . '<br /></pre></td></tr>'; - break; - - case 'remove': - $line = ''; - - foreach ($change['lines'] as $_line) - { - $line .= htmlspecialchars($_line) . '<br />'; - } - - $output .= '<tr><td class="removed"><pre>' . ((strlen($line)) ? $line : ' ') . '<br /></pre></td><td class="removed_empty"> </td></tr>'; - break; - - case 'empty': - $current_context .= htmlspecialchars($change['line']) . '<br />'; - break; - - case 'change': - // Pop the old/new stacks one by one, until both are empty. - $oldsize = sizeof($change['old']); - $newsize = sizeof($change['new']); - $left = $right = ''; - - for ($row = 0, $row_max = max($oldsize, $newsize); $row < $row_max; ++$row) - { - $left .= isset($change['old'][$row]) ? htmlspecialchars($change['old'][$row]) : ''; - $left .= '<br />'; - $right .= isset($change['new'][$row]) ? htmlspecialchars($change['new'][$row]) : ''; - $right .= '<br />'; - } - - $output .= '<tr>'; - - if (!empty($left)) - { - $output .= '<td class="modified"><pre>' . $left . '<br /></pre></td>'; - } - else if ($row < $oldsize) - { - $output .= '<td class="modified"> </td>'; - } - else - { - $output .= '<td class="unmodified"> </td>'; - } - - if (!empty($right)) - { - $output .= '<td class="modified"><pre>' . $right . '<br /></pre></td>'; - } - else if ($row < $newsize) - { - $output .= '<td class="modified"> </td>'; - } - else - { - $output .= '<td class="unmodified"> </td>'; - } - - $output .= '</tr>'; - break; - } - } - - if (!empty($current_context)) - { - $line = $current_context; - $current_context = ''; - - $output .= '<tr class="unmodified"><td><pre>' . ((strlen($line)) ? $line : ' ') . '<br /></pre></td>'; - $output .= '<td><pre>' . ((strlen($line)) ? $line : ' ') . '<br /></pre></td></tr>'; - } - } - } - - $output .= '</tbody></table>'; - - return $output; - } - - function _start_diff() - { - $this->lines = array(); - - $this->data = false; - $this->cols = array(array(), array()); - $this->state = 'empty'; - - return ''; - } - - function _end_diff() - { - // Just flush any remaining entries in the columns stack. - switch ($this->state) - { - case 'add': - $this->data['contents'][] = array('type' => 'add', 'lines' => $this->cols[0]); - break; - - case 'remove': - // We have some removal lines pending in our stack, so flush them. - $this->data['contents'][] = array('type' => 'remove', 'lines' => $this->cols[0]); - break; - - case 'change': - // We have both remove and addition lines, so this is a change block. - $this->data['contents'][] = array('type' => 'change', 'old' => $this->cols[0], 'new' => $this->cols[1]); - break; - } - - if ($this->data !== false) - { - $this->lines[] = $this->data; - } - - return ''; - } - - function _block_header($xbeg, $xlen, $ybeg, $ylen) - { - // Push any previous header information to the return stack. - if ($this->data !== false) - { - $this->lines[] = $this->data; - } - - $this->data = array('type' => 'header', 'oldline' => $xbeg, 'newline' => $ybeg, 'contents' => array()); - $this->state = 'dump'; - } - - function _added($lines) - { - array_walk($lines, array(&$this, '_perform_add')); - } - - function _perform_add($line) - { - if ($this->state == 'empty') - { - return ''; - } - - // This is just an addition line. - if ($this->state == 'dump' || $this->state == 'add') - { - // Start adding to the addition stack. - $this->cols[0][] = $line; - $this->state = 'add'; - } - else - { - // This is inside a change block, so start accumulating lines. - $this->state = 'change'; - $this->cols[1][] = $line; - } - } - - function _deleted($lines) - { - array_walk($lines, array(&$this, '_perform_delete')); - } - - function _perform_delete($line) - { - // This is a removal line. - $this->state = 'remove'; - $this->cols[0][] = $line; - } - - function _context($lines) - { - array_walk($lines, array(&$this, '_perform_context')); - } - - function _perform_context($line) - { - // An empty block with no action. - switch ($this->state) - { - case 'add': - $this->data['contents'][] = array('type' => 'add', 'lines' => $this->cols[0]); - break; - - case 'remove': - // We have some removal lines pending in our stack, so flush them. - $this->data['contents'][] = array('type' => 'remove', 'lines' => $this->cols[0]); - break; - - case 'change': - // We have both remove and addition lines, so this is a change block. - $this->data['contents'][] = array('type' => 'change', 'old' => $this->cols[0], 'new' => $this->cols[1]); - break; - } - - $this->cols = array(array(), array()); - $this->data['contents'][] = array('type' => 'empty', 'line' => $line); - $this->state = 'dump'; - } - - function _changed($orig, $final) - { - return $this->_deleted($orig) . $this->_added($final); - } - -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/libraries/ezcomponents/loader.php b/phpBB/includes/libraries/ezcomponents/loader.php deleted file mode 100644 index 62aaa7667d..0000000000 --- a/phpBB/includes/libraries/ezcomponents/loader.php +++ /dev/null @@ -1,73 +0,0 @@ -<?php -/** -* -* @package ezcomponents -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* eZ components class loader -* Replaces the autoload mechanism eZ Components normally use -* @package ezcomponents -*/ -class phpbb_ezcomponents_loader -{ - var $loaded; - - /** - * Constructor which makes sure the PHP version requirement is met. - */ - function phpbb_ezcomponents_loader() - { - $this->loaded = array(); - if (version_compare(PHP_VERSION, '5.2.1', '<')) - { - trigger_error('PHP >= 5.2.1 required', E_USER_ERROR); - } - } - - /** - * Loads all classes of a particular component. - * The base component is always loaded first. - * - * @param $component string Lower case component name - */ - function load_component($component) - { - global $phpbb_root_path; - - // don't allow loading the same component twice - if (isset($this->loaded[$component]) && $this->loaded[$component]) - { - return; - } - - // make sure base is always loaded first - if ($component != 'base' && !isset($this->loaded['base'])) - { - $this->load_component('base'); - } - - $ezc_path = $phpbb_root_path . 'includes/ezcomponents/'; - - // retrieve the autoload list - $classes = include($ezc_path . ucfirst($component) . '/' . $component . '_autoload.php'); - - // include all files related to this component - foreach ($classes as $class => $path) - { - include($ezc_path . $path); - } - } -}
\ No newline at end of file diff --git a/phpBB/includes/libraries/sftp/aes.php b/phpBB/includes/libraries/sftp/aes.php deleted file mode 100644 index 612e20830b..0000000000 --- a/phpBB/includes/libraries/sftp/aes.php +++ /dev/null @@ -1,1526 +0,0 @@ -<?php
-/**
-*
-* @package sftp
-* @version $Id$
-* @copyright (c) 2006 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Code from http://phpseclib.sourceforge.net/
-*
-* Modified by phpBB Group to meet our coding standards
-* and being able to integrate into phpBB
-*
-* Pure-PHP implementation of AES
-*
-* Copyright 2007-2009 TerraFrost <terrafrost@php.net>
-* Copyright 2009+ phpBB
-*
-* @package sftp
-* @author TerraFrost <terrafrost@php.net>
-*/
-
-/**#@+
- * @access public
- * @see rijndael::encrypt()
- * @see rijndael::decrypt()
- */
-/**
- * Encrypt / decrypt using the Electronic Code Book mode.
- *
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
- */
-define('CRYPT_RIJNDAEL_MODE_ECB', 1);
-/**
- * Encrypt / decrypt using the Code Book Chaining mode.
- *
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
- */
-define('CRYPT_RIJNDAEL_MODE_CBC', 2);
-/**#@-*/
-
-/**#@+
- * @access private
- * @see rijndael::__construct()
- */
-/**
- * Toggles the internal implementation
- */
-define('CRYPT_RIJNDAEL_MODE_INTERNAL', 1);
-/**
- * Toggles the mcrypt implementation
- */
-define('CRYPT_RIJNDAEL_MODE_MCRYPT', 2);
-/**#@-*/
-
-/**#@+
- * @access public
- * @see aes::encrypt()
- * @see aes::decrypt()
- */
-/**
- * Encrypt / decrypt using the Electronic Code Book mode.
- *
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
- */
-define('CRYPT_AES_MODE_ECB', 1);
-/**
- * Encrypt / decrypt using the Code Book Chaining mode.
- *
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
- */
-define('CRYPT_AES_MODE_CBC', 2);
-/**#@-*/
-
-/**#@+
- * @access private
- * @see aes::__construct()
- */
-/**
- * Toggles the internal implementation
- */
-define('CRYPT_AES_MODE_INTERNAL', 1);
-/**
- * Toggles the mcrypt implementation
- */
-define('CRYPT_AES_MODE_MCRYPT', 2);
-/**#@-*/
-
-/**
- * Pure-PHP implementation of Rijndael.
- *
- * @author Jim Wigginton <terrafrost@php.net>
- * @version 0.1.0
- * @access public
- * @package rijndael
- */
-class rijndael
-{
- /**
- * The Encryption Mode
- *
- * @see rijndael::__construct()
- * @var Integer
- * @access private
- */
- var $mode;
-
- /**
- * The Key
- *
- * @see rijndael::set_key()
- * @var String
- * @access private
- */
- var $key = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0";
-
- /**
- * The Initialization Vector
- *
- * @see rijndael::set_iv()
- * @var String
- * @access private
- */
- var $iv = '';
-
- /**
- * A "sliding" Initialization Vector
- *
- * @see rijndael::enable_continuous_buffer()
- * @var String
- * @access private
- */
- var $encryptIV = '';
-
- /**
- * A "sliding" Initialization Vector
- *
- * @see rijndael::enableContinuousBuffer()
- * @var String
- * @access private
- */
- var $decryptIV = '';
-
- /**
- * Continuous Buffer status
- *
- * @see rijndael::enable_continuous_buffer()
- * @var Boolean
- * @access private
- */
- var $continuousBuffer = false;
-
- /**
- * Padding status
- *
- * @see rijndael::enable_padding()
- * @var Boolean
- * @access private
- */
- var $padding = true;
-
- /**
- * Does the key schedule need to be (re)calculated?
- *
- * @see setKey()
- * @see setBlockLength()
- * @see setKeyLength()
- * @var Boolean
- * @access private
- */
- var $changed = true;
-
- /**
- * Has the key length explicitly been set or should it be derived from the key, itself?
- *
- * @see setKeyLength()
- * @var Boolean
- * @access private
- */
- var $explicit_key_length = false;
-
- /**
- * The Key Schedule
- *
- * @see _setup()
- * @var Array
- * @access private
- */
- var $w;
-
- /**
- * The Inverse Key Schedule
- *
- * @see _setup()
- * @var Array
- * @access private
- */
- var $dw;
-
- /**
- * The Block Length
- *
- * @see setBlockLength()
- * @var Integer
- * @access private
- * @internal The max value is 32, the min value is 16. All valid values are multiples of 4. Exists in conjunction with
- * $Nb because we need this value and not $Nb to pad strings appropriately.
- */
- var $block_size = 16;
-
- /**
- * The Block Length divided by 32
- *
- * @see setBlockLength()
- * @var Integer
- * @access private
- * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $block_size
- * because the encryption / decryption / key schedule creation requires this number and not $block_size. We could
- * derive this from $block_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
- * of that, we'll just precompute it once.
- *
- */
- var $Nb = 4;
-
- /**
- * The Key Length
- *
- * @see setKeyLength()
- * @var Integer
- * @access private
- * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4. Exists in conjunction with $key_size
- * because the encryption / decryption / key schedule creation requires this number and not $key_size. We could
- * derive this from $key_size or vice versa, but that'd mean we'd have to do multiple shift operations, so in lieu
- * of that, we'll just precompute it once.
- */
- var $key_size = 16;
-
- /**
- * The Key Length divided by 32
- *
- * @see setKeyLength()
- * @var Integer
- * @access private
- * @internal The max value is 256 / 32 = 8, the min value is 128 / 32 = 4
- */
- var $Nk = 4;
-
- /**
- * The Number of Rounds
- *
- * @var Integer
- * @access private
- * @internal The max value is 14, the min value is 10.
- */
- var $Nr;
-
- /**
- * Shift offsets
- *
- * @var Array
- * @access private
- */
- var $c;
-
- /**
- * Precomputed mixColumns table
- *
- * @see rijndael()
- * @var Array
- * @access private
- */
- var $t0;
-
- /**
- * Precomputed mixColumns table
- *
- * @see rijndael()
- * @var Array
- * @access private
- */
- var $t1;
-
- /**
- * Precomputed mixColumns table
- *
- * @see rijndael()
- * @var Array
- * @access private
- */
- var $t2;
-
- /**
- * Precomputed mixColumns table
- *
- * @see rijndael()
- * @var Array
- * @access private
- */
- var $t3;
-
- /**
- * Precomputed invMixColumns table
- *
- * @see rijndael()
- * @var Array
- * @access private
- */
- var $dt0;
-
- /**
- * Precomputed invMixColumns table
- *
- * @see rijndael()
- * @var Array
- * @access private
- */
- var $dt1;
-
- /**
- * Precomputed invMixColumns table
- *
- * @see rijndael()
- * @var Array
- * @access private
- */
- var $dt2;
-
- /**
- * Precomputed invMixColumns table
- *
- * @see rijndael()
- * @var Array
- * @access private
- */
- var $dt3;
-
- /**
- * Default Constructor.
- *
- * Determines whether or not the mcrypt extension should be used. $mode should only, at present, be
- * CRYPT_RIJNDAEL_MODE_ECB or CRYPT_RIJNDAEL_MODE_CBC. If not explictly set, CRYPT_RIJNDAEL_MODE_CBC will be used.
- *
- * @param optional Integer $mode
- * @return rijndael
- * @access public
- */
- function __construct($mode = CRYPT_MODE_CRYPT_RIJNDAEL_CBC)
- {
- switch ($mode)
- {
- case CRYPT_RIJNDAEL_MODE_ECB:
- case CRYPT_RIJNDAEL_MODE_CBC:
- $this->mode = $mode;
- break;
- default:
- $this->mode = CRYPT_RIJNDAEL_MODE_CBC;
- }
-
- // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=19> (section 5.2.1),
- // precomputed tables can be used in the mixColumns phase. in that example, they're assigned t0...t3, so
- // those are the names we'll use.
- $this->t3 = array(
- 0x6363A5C6, 0x7C7C84F8, 0x777799EE, 0x7B7B8DF6, 0xF2F20DFF, 0x6B6BBDD6, 0x6F6FB1DE, 0xC5C55491,
- 0x30305060, 0x01010302, 0x6767A9CE, 0x2B2B7D56, 0xFEFE19E7, 0xD7D762B5, 0xABABE64D, 0x76769AEC,
- 0xCACA458F, 0x82829D1F, 0xC9C94089, 0x7D7D87FA, 0xFAFA15EF, 0x5959EBB2, 0x4747C98E, 0xF0F00BFB,
- 0xADADEC41, 0xD4D467B3, 0xA2A2FD5F, 0xAFAFEA45, 0x9C9CBF23, 0xA4A4F753, 0x727296E4, 0xC0C05B9B,
- 0xB7B7C275, 0xFDFD1CE1, 0x9393AE3D, 0x26266A4C, 0x36365A6C, 0x3F3F417E, 0xF7F702F5, 0xCCCC4F83,
- 0x34345C68, 0xA5A5F451, 0xE5E534D1, 0xF1F108F9, 0x717193E2, 0xD8D873AB, 0x31315362, 0x15153F2A,
- 0x04040C08, 0xC7C75295, 0x23236546, 0xC3C35E9D, 0x18182830, 0x9696A137, 0x05050F0A, 0x9A9AB52F,
- 0x0707090E, 0x12123624, 0x80809B1B, 0xE2E23DDF, 0xEBEB26CD, 0x2727694E, 0xB2B2CD7F, 0x75759FEA,
- 0x09091B12, 0x83839E1D, 0x2C2C7458, 0x1A1A2E34, 0x1B1B2D36, 0x6E6EB2DC, 0x5A5AEEB4, 0xA0A0FB5B,
- 0x5252F6A4, 0x3B3B4D76, 0xD6D661B7, 0xB3B3CE7D, 0x29297B52, 0xE3E33EDD, 0x2F2F715E, 0x84849713,
- 0x5353F5A6, 0xD1D168B9, 0x00000000, 0xEDED2CC1, 0x20206040, 0xFCFC1FE3, 0xB1B1C879, 0x5B5BEDB6,
- 0x6A6ABED4, 0xCBCB468D, 0xBEBED967, 0x39394B72, 0x4A4ADE94, 0x4C4CD498, 0x5858E8B0, 0xCFCF4A85,
- 0xD0D06BBB, 0xEFEF2AC5, 0xAAAAE54F, 0xFBFB16ED, 0x4343C586, 0x4D4DD79A, 0x33335566, 0x85859411,
- 0x4545CF8A, 0xF9F910E9, 0x02020604, 0x7F7F81FE, 0x5050F0A0, 0x3C3C4478, 0x9F9FBA25, 0xA8A8E34B,
- 0x5151F3A2, 0xA3A3FE5D, 0x4040C080, 0x8F8F8A05, 0x9292AD3F, 0x9D9DBC21, 0x38384870, 0xF5F504F1,
- 0xBCBCDF63, 0xB6B6C177, 0xDADA75AF, 0x21216342, 0x10103020, 0xFFFF1AE5, 0xF3F30EFD, 0xD2D26DBF,
- 0xCDCD4C81, 0x0C0C1418, 0x13133526, 0xECEC2FC3, 0x5F5FE1BE, 0x9797A235, 0x4444CC88, 0x1717392E,
- 0xC4C45793, 0xA7A7F255, 0x7E7E82FC, 0x3D3D477A, 0x6464ACC8, 0x5D5DE7BA, 0x19192B32, 0x737395E6,
- 0x6060A0C0, 0x81819819, 0x4F4FD19E, 0xDCDC7FA3, 0x22226644, 0x2A2A7E54, 0x9090AB3B, 0x8888830B,
- 0x4646CA8C, 0xEEEE29C7, 0xB8B8D36B, 0x14143C28, 0xDEDE79A7, 0x5E5EE2BC, 0x0B0B1D16, 0xDBDB76AD,
- 0xE0E03BDB, 0x32325664, 0x3A3A4E74, 0x0A0A1E14, 0x4949DB92, 0x06060A0C, 0x24246C48, 0x5C5CE4B8,
- 0xC2C25D9F, 0xD3D36EBD, 0xACACEF43, 0x6262A6C4, 0x9191A839, 0x9595A431, 0xE4E437D3, 0x79798BF2,
- 0xE7E732D5, 0xC8C8438B, 0x3737596E, 0x6D6DB7DA, 0x8D8D8C01, 0xD5D564B1, 0x4E4ED29C, 0xA9A9E049,
- 0x6C6CB4D8, 0x5656FAAC, 0xF4F407F3, 0xEAEA25CF, 0x6565AFCA, 0x7A7A8EF4, 0xAEAEE947, 0x08081810,
- 0xBABAD56F, 0x787888F0, 0x25256F4A, 0x2E2E725C, 0x1C1C2438, 0xA6A6F157, 0xB4B4C773, 0xC6C65197,
- 0xE8E823CB, 0xDDDD7CA1, 0x74749CE8, 0x1F1F213E, 0x4B4BDD96, 0xBDBDDC61, 0x8B8B860D, 0x8A8A850F,
- 0x707090E0, 0x3E3E427C, 0xB5B5C471, 0x6666AACC, 0x4848D890, 0x03030506, 0xF6F601F7, 0x0E0E121C,
- 0x6161A3C2, 0x35355F6A, 0x5757F9AE, 0xB9B9D069, 0x86869117, 0xC1C15899, 0x1D1D273A, 0x9E9EB927,
- 0xE1E138D9, 0xF8F813EB, 0x9898B32B, 0x11113322, 0x6969BBD2, 0xD9D970A9, 0x8E8E8907, 0x9494A733,
- 0x9B9BB62D, 0x1E1E223C, 0x87879215, 0xE9E920C9, 0xCECE4987, 0x5555FFAA, 0x28287850, 0xDFDF7AA5,
- 0x8C8C8F03, 0xA1A1F859, 0x89898009, 0x0D0D171A, 0xBFBFDA65, 0xE6E631D7, 0x4242C684, 0x6868B8D0,
- 0x4141C382, 0x9999B029, 0x2D2D775A, 0x0F0F111E, 0xB0B0CB7B, 0x5454FCA8, 0xBBBBD66D, 0x16163A2C
- );
-
- $this->dt3 = array(
- 0xF4A75051, 0x4165537E, 0x17A4C31A, 0x275E963A, 0xAB6BCB3B, 0x9D45F11F, 0xFA58ABAC, 0xE303934B,
- 0x30FA5520, 0x766DF6AD, 0xCC769188, 0x024C25F5, 0xE5D7FC4F, 0x2ACBD7C5, 0x35448026, 0x62A38FB5,
- 0xB15A49DE, 0xBA1B6725, 0xEA0E9845, 0xFEC0E15D, 0x2F7502C3, 0x4CF01281, 0x4697A38D, 0xD3F9C66B,
- 0x8F5FE703, 0x929C9515, 0x6D7AEBBF, 0x5259DA95, 0xBE832DD4, 0x7421D358, 0xE0692949, 0xC9C8448E,
- 0xC2896A75, 0x8E7978F4, 0x583E6B99, 0xB971DD27, 0xE14FB6BE, 0x88AD17F0, 0x20AC66C9, 0xCE3AB47D,
- 0xDF4A1863, 0x1A3182E5, 0x51336097, 0x537F4562, 0x6477E0B1, 0x6BAE84BB, 0x81A01CFE, 0x082B94F9,
- 0x48685870, 0x45FD198F, 0xDE6C8794, 0x7BF8B752, 0x73D323AB, 0x4B02E272, 0x1F8F57E3, 0x55AB2A66,
- 0xEB2807B2, 0xB5C2032F, 0xC57B9A86, 0x3708A5D3, 0x2887F230, 0xBFA5B223, 0x036ABA02, 0x16825CED,
- 0xCF1C2B8A, 0x79B492A7, 0x07F2F0F3, 0x69E2A14E, 0xDAF4CD65, 0x05BED506, 0x34621FD1, 0xA6FE8AC4,
- 0x2E539D34, 0xF355A0A2, 0x8AE13205, 0xF6EB75A4, 0x83EC390B, 0x60EFAA40, 0x719F065E, 0x6E1051BD,
- 0x218AF93E, 0xDD063D96, 0x3E05AEDD, 0xE6BD464D, 0x548DB591, 0xC45D0571, 0x06D46F04, 0x5015FF60,
- 0x98FB2419, 0xBDE997D6, 0x4043CC89, 0xD99E7767, 0xE842BDB0, 0x898B8807, 0x195B38E7, 0xC8EEDB79,
- 0x7C0A47A1, 0x420FE97C, 0x841EC9F8, 0x00000000, 0x80868309, 0x2BED4832, 0x1170AC1E, 0x5A724E6C,
- 0x0EFFFBFD, 0x8538560F, 0xAED51E3D, 0x2D392736, 0x0FD9640A, 0x5CA62168, 0x5B54D19B, 0x362E3A24,
- 0x0A67B10C, 0x57E70F93, 0xEE96D2B4, 0x9B919E1B, 0xC0C54F80, 0xDC20A261, 0x774B695A, 0x121A161C,
- 0x93BA0AE2, 0xA02AE5C0, 0x22E0433C, 0x1B171D12, 0x090D0B0E, 0x8BC7ADF2, 0xB6A8B92D, 0x1EA9C814,
- 0xF1198557, 0x75074CAF, 0x99DDBBEE, 0x7F60FDA3, 0x01269FF7, 0x72F5BC5C, 0x663BC544, 0xFB7E345B,
- 0x4329768B, 0x23C6DCCB, 0xEDFC68B6, 0xE4F163B8, 0x31DCCAD7, 0x63851042, 0x97224013, 0xC6112084,
- 0x4A247D85, 0xBB3DF8D2, 0xF93211AE, 0x29A16DC7, 0x9E2F4B1D, 0xB230F3DC, 0x8652EC0D, 0xC1E3D077,
- 0xB3166C2B, 0x70B999A9, 0x9448FA11, 0xE9642247, 0xFC8CC4A8, 0xF03F1AA0, 0x7D2CD856, 0x3390EF22,
- 0x494EC787, 0x38D1C1D9, 0xCAA2FE8C, 0xD40B3698, 0xF581CFA6, 0x7ADE28A5, 0xB78E26DA, 0xADBFA43F,
- 0x3A9DE42C, 0x78920D50, 0x5FCC9B6A, 0x7E466254, 0x8D13C2F6, 0xD8B8E890, 0x39F75E2E, 0xC3AFF582,
- 0x5D80BE9F, 0xD0937C69, 0xD52DA96F, 0x2512B3CF, 0xAC993BC8, 0x187DA710, 0x9C636EE8, 0x3BBB7BDB,
- 0x267809CD, 0x5918F46E, 0x9AB701EC, 0x4F9AA883, 0x956E65E6, 0xFFE67EAA, 0xBCCF0821, 0x15E8E6EF,
- 0xE79BD9BA, 0x6F36CE4A, 0x9F09D4EA, 0xB07CD629, 0xA4B2AF31, 0x3F23312A, 0xA59430C6, 0xA266C035,
- 0x4EBC3774, 0x82CAA6FC, 0x90D0B0E0, 0xA7D81533, 0x04984AF1, 0xECDAF741, 0xCD500E7F, 0x91F62F17,
- 0x4DD68D76, 0xEFB04D43, 0xAA4D54CC, 0x9604DFE4, 0xD1B5E39E, 0x6A881B4C, 0x2C1FB8C1, 0x65517F46,
- 0x5EEA049D, 0x8C355D01, 0x877473FA, 0x0B412EFB, 0x671D5AB3, 0xDBD25292, 0x105633E9, 0xD647136D,
- 0xD7618C9A, 0xA10C7A37, 0xF8148E59, 0x133C89EB, 0xA927EECE, 0x61C935B7, 0x1CE5EDE1, 0x47B13C7A,
- 0xD2DF599C, 0xF2733F55, 0x14CE7918, 0xC737BF73, 0xF7CDEA53, 0xFDAA5B5F, 0x3D6F14DF, 0x44DB8678,
- 0xAFF381CA, 0x68C43EB9, 0x24342C38, 0xA3405FC2, 0x1DC37216, 0xE2250CBC, 0x3C498B28, 0x0D9541FF,
- 0xA8017139, 0x0CB3DE08, 0xB4E49CD8, 0x56C19064, 0xCB84617B, 0x32B670D5, 0x6C5C7448, 0xB85742D0
- );
-
- for ($i = 0; $i < 256; $i++)
- {
- $this->t2[$i << 8] = (($this->t3[$i] << 8) & 0xFFFFFF00) | (($this->t3[$i] >> 24) & 0x000000FF);
- $this->t1[$i << 16] = (($this->t3[$i] << 16) & 0xFFFF0000) | (($this->t3[$i] >> 16) & 0x0000FFFF);
- $this->t0[$i << 24] = (($this->t3[$i] << 24) & 0xFF000000) | (($this->t3[$i] >> 8) & 0x00FFFFFF);
-
- $this->dt2[$i << 8] = (($this->dt3[$i] << 8) & 0xFFFFFF00) | (($this->dt3[$i] >> 24) & 0x000000FF);
- $this->dt1[$i << 16] = (($this->dt3[$i] << 16) & 0xFFFF0000) | (($this->dt3[$i] >> 16) & 0x0000FFFF);
- $this->dt0[$i << 24] = (($this->dt3[$i] << 24) & 0xFF000000) | (($this->dt3[$i] >> 8) & 0x00FFFFFF);
- }
- }
-
- /**
- * Sets the key.
- *
- * Keys can be of any length. Rijndael, itself, requires the use of a key that's between 128-bits and 256-bits long and
- * whose length is a multiple of 32. If the key is less than 256-bits and the key length isn't set, we round the length
- * up to the closest valid key length, padding $key with null bytes. If the key is more tan 256-bits, we trim the
- * excess bits.
- *
- * If the key is not explicitly set, it'll be assumed to be all null bytes.
- *
- * @access public
- * @param String $key
- */
- function set_key($key)
- {
- $this->key = $key;
- $this->changed = true;
- }
-
- /**
- * Sets the initialization vector. (optional)
- *
- * SetIV is not required when CRYPT_RIJNDAEL_MODE_ECB is being used. If not explictly set, it'll be assumed
- * to be all zero's.
- *
- * @access public
- * @param String $iv
- */
- function set_iv($iv)
- {
- $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, $this->block_size), $this->block_size, chr(0));;
- }
-
- /**
- * Sets the key length
- *
- * Valid key lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
- * 128. If the length is greater then 128 and invalid, it will be rounded down to the closest valid amount.
- *
- * @access public
- * @param Integer $length
- */
- function set_key_length($length)
- {
- $length >>= 5;
- if ($length > 8)
- {
- $length = 8;
- }
- else if ($length < 4)
- {
- $length = 4;
- }
- $this->Nk = $length;
- $this->key_size = $length << 2;
-
- $this->explicit_key_length = true;
- $this->changed = true;
- }
-
- /**
- * Sets the block length
- *
- * Valid block lengths are 128, 160, 192, 224, and 256. If the length is less than 128, it will be rounded up to
- * 128. If the length is greater then 128 and invalid, it will be rounded down to the closest valid amount.
- *
- * @access public
- * @param Integer $length
- */
- function set_block_length($length)
- {
- $length >>= 5;
- if ($length > 8)
- {
- $length = 8;
- }
- else if ($length < 4)
- {
- $length = 4;
- }
- $this->Nb = $length;
- $this->block_size = $length << 2;
- $this->changed = true;
- }
-
- /**
- * Encrypts a message.
- *
- * $plaintext will be padded with additional bytes such that it's length is a multiple of the block size. Other Rjindael
- * implementations may or may not pad in the same manner. Other common approaches to padding and the reasons why it's
- * necessary are discussed in the following
- * URL:
- *
- * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
- *
- * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
- * strlen($plaintext) will still need to be a multiple of 8, however, arbitrary values can be added to make it that
- * length.
- *
- * @see rijndael::decrypt()
- * @access public
- * @param String $plaintext
- */
- function encrypt($plaintext)
- {
- $this->_setup();
- $plaintext = $this->_pad($plaintext);
-
- $ciphertext = '';
- switch ($this->mode)
- {
- case CRYPT_RIJNDAEL_MODE_ECB:
- for ($i = 0; $i < strlen($plaintext); $i+=$this->block_size)
- {
- $ciphertext.= $this->_encrypt_block(substr($plaintext, $i, $this->block_size));
- }
- break;
- case CRYPT_RIJNDAEL_MODE_CBC:
- $xor = $this->encryptIV;
- for ($i = 0; $i < strlen($plaintext); $i+=$this->block_size)
- {
- $block = substr($plaintext, $i, $this->block_size);
- $block = $this->_encrypt_block($block ^ $xor);
- $xor = $block;
- $ciphertext.= $block;
- }
- if ($this->continuousBuffer)
- {
- $this->encryptIV = $xor;
- }
- }
-
- return $ciphertext;
- }
-
- /**
- * Decrypts a message.
- *
- * If strlen($ciphertext) is not a multiple of the block size, null bytes will be added to the end of the string until
- * it is.
- *
- * @see rijndael::encrypt()
- * @access public
- * @param String $ciphertext
- */
- function decrypt($ciphertext)
- {
- $this->_setup();
- // we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
- // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
- $ciphertext = str_pad($ciphertext, (strlen($ciphertext) + $this->block_size - 1) % $this->block_size, chr(0));
-
- $plaintext = '';
- switch ($this->mode)
- {
- case CRYPT_RIJNDAEL_MODE_ECB:
- for ($i = 0; $i < strlen($ciphertext); $i+=$this->block_size)
- {
- $plaintext.= $this->_decrypt_block(substr($ciphertext, $i, $this->block_size));
- }
- break;
- case CRYPT_RIJNDAEL_MODE_CBC:
- $xor = $this->decryptIV;
- for ($i = 0; $i < strlen($ciphertext); $i+=$this->block_size)
- {
- $block = substr($ciphertext, $i, $this->block_size);
- $plaintext.= $this->_decrypt_block($block) ^ $xor;
- $xor = $block;
- }
- if ($this->continuousBuffer)
- {
- $this->decryptIV = $xor;
- }
- }
-
- return $this->_unpad($plaintext);
- }
-
- /**
- * Encrypts a block
- *
- * @access private
- * @param String $in
- * @return String
- */
- function _encrypt_block($in)
- {
- // unpack starts it's indices at 1 - not 0.
- $state = unpack('N*', $in);
-
- // addRoundKey and reindex $state
- for ($i = 0; $i < $this->Nb; $i++)
- {
- $state[$i] = $state[$i + 1] ^ $this->w[0][$i];
- }
- unset($state[$i]);
-
- // fips-197.pdf#page=19, "Figure 5. Pseudo Code for the Cipher", states that this loop has four components -
- // subBytes, shiftRows, mixColumns, and addRoundKey. fips-197.pdf#page=30, "Implementation Suggestions Regarding
- // Various Platforms" suggests that performs enhanced implementations are described in Rijndael-ammended.pdf.
- // Rijndael-ammended.pdf#page=20, "Implementation aspects / 32-bit processor", discusses such an optimization.
- // Unfortunately, the description given there is not quite correct. Per aes.spec.v316.pdf#page=19 [1],
- // equation (7.4.7) is supposed to use addition instead of subtraction, so we'll do that here, as well.
-
- // [1] http://fp.gladman.plus.com/cryptography_technology/rijndael/aes.spec.v316.pdf
- $temp = array();
- for ($round = 1; $round < $this->Nr; $round++)
- {
- $i = 0; // $this->c[0] == 0
- $j = $this->c[1];
- $k = $this->c[2];
- $l = $this->c[3];
-
- while ($i < $this->Nb)
- {
- $temp[$i] = $this->t0[$state[$i] & 0xFF000000] ^
- $this->t1[$state[$j] & 0x00FF0000] ^
- $this->t2[$state[$k] & 0x0000FF00] ^
- $this->t3[$state[$l] & 0x000000FF] ^
- $this->w[$round][$i];
- $i++;
- $j = ($j + 1) % $this->Nb;
- $k = ($k + 1) % $this->Nb;
- $l = ($l + 1) % $this->Nb;
- }
-
- for ($i = 0; $i < $this->Nb; $i++)
- {
- $state[$i] = $temp[$i];
- }
- }
-
- // subWord
- for ($i = 0; $i < $this->Nb; $i++)
- {
- $state[$i] = $this->_sub_word($state[$i]);
- }
-
- // shiftRows + addRoundKey
- $i = 0; // $this->c[0] == 0
- $j = $this->c[1];
- $k = $this->c[2];
- $l = $this->c[3];
- while ($i < $this->Nb)
- {
- $temp[$i] = ($state[$i] & 0xFF000000) ^
- ($state[$j] & 0x00FF0000) ^
- ($state[$k] & 0x0000FF00) ^
- ($state[$l] & 0x000000FF) ^
- $this->w[$this->Nr][$i];
- $i++;
- $j = ($j + 1) % $this->Nb;
- $k = ($k + 1) % $this->Nb;
- $l = ($l + 1) % $this->Nb;
- }
- $state = $temp;
-
- array_unshift($state, 'N*');
-
- return call_user_func_array('pack', $state);
- }
-
- /**
- * Decrypts a block
- *
- * @access private
- * @param String $in
- * @return String
- */
- function _decrypt_block($in)
- {
- // unpack starts it's indices at 1 - not 0.
- $state = unpack('N*', $in);
-
- // addRoundKey and reindex $state
- for ($i = 0; $i < $this->Nb; $i++)
- {
- $state[$i] = $state[$i + 1] ^ $this->dw[$this->Nr][$i];
- }
- unset($state[$i]);
-
- $temp = array();
- for ($round = $this->Nr - 1; $round > 0; $round--)
- {
- $i = 0; // $this->c[0] == 0
- $j = $this->Nb - $this->c[1];
- $k = $this->Nb - $this->c[2];
- $l = $this->Nb - $this->c[3];
-
- while ($i < $this->Nb)
- {
- $temp[$i] = $this->dt0[$state[$i] & 0xFF000000] ^
- $this->dt1[$state[$j] & 0x00FF0000] ^
- $this->dt2[$state[$k] & 0x0000FF00] ^
- $this->dt3[$state[$l] & 0x000000FF] ^
- $this->dw[$round][$i];
- $i++;
- $j = ($j + 1) % $this->Nb;
- $k = ($k + 1) % $this->Nb;
- $l = ($l + 1) % $this->Nb;
- }
-
- for ($i = 0; $i < $this->Nb; $i++)
- {
- $state[$i] = $temp[$i];
- }
- }
-
- // invShiftRows + invSubWord + addRoundKey
- $i = 0; // $this->c[0] == 0
- $j = $this->Nb - $this->c[1];
- $k = $this->Nb - $this->c[2];
- $l = $this->Nb - $this->c[3];
-
- while ($i < $this->Nb)
- {
- $temp[$i] = $this->dw[0][$i] ^
- $this->_inv_sub_word(($state[$i] & 0xFF000000) |
- ($state[$j] & 0x00FF0000) |
- ($state[$k] & 0x0000FF00) |
- ($state[$l] & 0x000000FF));
- $i++;
- $j = ($j + 1) % $this->Nb;
- $k = ($k + 1) % $this->Nb;
- $l = ($l + 1) % $this->Nb;
- }
-
- $state = $temp;
-
- array_unshift($state, 'N*');
-
- return call_user_func_array('pack', $state);
- }
-
- /**
- * Setup Rijndael
- *
- * Validates all the variables and calculates $Nr - the number of rounds that need to be performed - and $w - the key
- * key schedule.
- *
- * @access private
- */
- function _setup()
- {
- // Each number in $rcon is equal to the previous number multiplied by two in Rijndael's finite field.
- // See http://en.wikipedia.org/wiki/Finite_field_arithmetic#Multiplicative_inverse
- static $rcon = array(0,
- 0x01000000, 0x02000000, 0x04000000, 0x08000000, 0x10000000,
- 0x20000000, 0x40000000, 0x80000000, 0x1B000000, 0x36000000,
- 0x6C000000, 0xD8000000, 0xAB000000, 0x4D000000, 0x9A000000,
- 0x2F000000, 0x5E000000, 0xBC000000, 0x63000000, 0xC6000000,
- 0x97000000, 0x35000000, 0x6A000000, 0xD4000000, 0xB3000000,
- 0x7D000000, 0xFA000000, 0xEF000000, 0xC5000000, 0x91000000
- );
-
- if (!$this->changed)
- {
- return;
- }
-
- if (!$this->explicit_key_length)
- {
- // we do >> 2, here, and not >> 5, as we do above, since strlen($this->key) tells us the number of bytes - not bits
- $length = strlen($this->key) >> 2;
- if ($length > 8)
- {
- $length = 8;
- }
- else if ($length < 4)
- {
- $length = 4;
- }
- $this->Nk = $length;
- $this->key_size = $length << 2;
- }
-
- $this->key = str_pad(substr($this->key, 0, $this->key_size), $this->key_size, chr(0));
- $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($this->iv, 0, $this->block_size), $this->block_size, chr(0));
-
- // see Rijndael-ammended.pdf#page=44
- $this->Nr = max($this->Nk, $this->Nb) + 6;
-
- // shift offsets for Nb = 5, 7 are defined in Rijndael-ammended.pdf#page=44,
- // "Table 8: Shift offsets in Shiftrow for the alternative block lengths"
- // shift offsets for Nb = 4, 6, 8 are defined in Rijndael-ammended.pdf#page=14,
- // "Table 2: Shift offsets for different block lengths"
- switch ($this->Nb)
- {
- case 4:
- case 5:
- case 6:
- $this->c = array(0, 1, 2, 3);
- break;
- case 7:
- $this->c = array(0, 1, 2, 4);
- break;
- case 8:
- $this->c = array(0, 1, 3, 4);
- }
-
- $key = $this->key;
-
- $w = array();
- for ($i = 0; $i < $this->Nk; $i++)
- {
- list(, $w[$i]) = unpack('N', $this->_string_shift($key, 4));
- }
-
- $length = $this->Nb * ($this->Nr + 1);
- for (; $i < $length; $i++)
- {
- $temp = $w[$i - 1];
- if ($i % $this->Nk == 0)
- {
- // according to <http://php.net/language.types.integer>, "the size of an integer is platform-dependent".
- // on a 32-bit machine, it's 32-bits, and on a 64-bit machine, it's 64-bits. on a 32-bit machine,
- // 0xFFFFFFFF << 8 == 0xFFFFFF00, but on a 64-bit machine, it equals 0xFFFFFFFF00. as such, doing 'and'
- // with 0xFFFFFFFF (or 0xFFFFFF00) on a 32-bit machine is unnecessary, but on a 64-bit machine, it is.
- $temp = (($temp << 8) & 0xFFFFFF00) | (($temp >> 24) & 0x000000FF); // rotWord
- $temp = $this->_sub_word($temp) ^ $rcon[$i / $this->Nk];
- }
- else if ($this->Nk > 6 && $i % $this->Nk == 4)
- {
- $temp = $this->_sub_word($temp);
- }
- $w[$i] = $w[$i - $this->Nk] ^ $temp;
- }
-
- // convert the key schedule from a vector of $Nb * ($Nr + 1) length to a matrix with $Nr + 1 rows and $Nb columns
- // and generate the inverse key schedule. more specifically,
- // according to <http://csrc.nist.gov/archive/aes/rijndael/Rijndael-ammended.pdf#page=23> (section 5.3.3),
- // "The key expansion for the Inverse Cipher is defined as follows:
- // 1. Apply the Key Expansion.
- // 2. Apply InvMixColumn to all Round Keys except the first and the last one."
- // also, see fips-197.pdf#page=27, "5.3.5 Equivalent Inverse Cipher"
- $temp = array();
- for ($i = $row = $col = 0; $i < $length; $i++, $col++)
- {
- if ($col == $this->Nb)
- {
- if ($row == 0)
- {
- $this->dw[0] = $this->w[0];
- }
- else
- {
- // subWord + invMixColumn + invSubWord = invMixColumn
- $j = 0;
- while ($j < $this->Nb)
- {
- $dw = $this->_sub_word($this->w[$row][$j]);
- $temp[$j] = $this->dt0[$dw & 0xFF000000] ^
- $this->dt1[$dw & 0x00FF0000] ^
- $this->dt2[$dw & 0x0000FF00] ^
- $this->dt3[$dw & 0x000000FF];
- $j++;
- }
- $this->dw[$row] = $temp;
- }
-
- $col = 0;
- $row++;
- }
- $this->w[$row][$col] = $w[$i];
- }
-
- $this->dw[$row] = $this->w[$row];
-
- $this->changed = false;
- }
-
- /**
- * Performs S-Box substitutions
- *
- * @access private
- */
- function _sub_word($word)
- {
- static $sbox0, $sbox1, $sbox2, $sbox3;
-
- if (empty($sbox0))
- {
- $sbox0 = array(
- 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76,
- 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0,
- 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15,
- 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75,
- 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84,
- 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF,
- 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8,
- 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2,
- 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73,
- 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB,
- 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79,
- 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08,
- 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A,
- 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E,
- 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF,
- 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16
- );
-
- $sbox1 = array();
- $sbox2 = array();
- $sbox3 = array();
-
- for ($i = 0; $i < 256; $i++)
- {
- $sbox1[$i << 8] = $sbox0[$i] << 8;
- $sbox2[$i << 16] = $sbox0[$i] << 16;
- $sbox3[$i << 24] = $sbox0[$i] << 24;
- }
- }
-
- return $sbox0[$word & 0x000000FF] |
- $sbox1[$word & 0x0000FF00] |
- $sbox2[$word & 0x00FF0000] |
- $sbox3[$word & 0xFF000000];
- }
-
- /**
- * Performs inverse S-Box substitutions
- *
- * @access private
- */
- function _inv_sub_word($word)
- {
- static $sbox0, $sbox1, $sbox2, $sbox3;
-
- if (empty($sbox0))
- {
- $sbox0 = array(
- 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB,
- 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB,
- 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E,
- 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25,
- 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92,
- 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84,
- 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06,
- 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B,
- 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73,
- 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E,
- 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B,
- 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4,
- 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F,
- 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF,
- 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61,
- 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D
- );
-
- $sbox1 = array();
- $sbox2 = array();
- $sbox3 = array();
-
- for ($i = 0; $i < 256; $i++)
- {
- $sbox1[$i << 8] = $sbox0[$i] << 8;
- $sbox2[$i << 16] = $sbox0[$i] << 16;
- $sbox3[$i << 24] = $sbox0[$i] << 24;
- }
- }
-
- return $sbox0[$word & 0x000000FF] |
- $sbox1[$word & 0x0000FF00] |
- $sbox2[$word & 0x00FF0000] |
- $sbox3[$word & 0xFF000000];
- }
-
- /**
- * Pad "packets".
- *
- * Rijndael works by encrypting between sixteen and thirty-two bytes at a time, provided that number is also a multiple
- * of four. If you ever need to encrypt or decrypt something that isn't of the proper length, it becomes necessary to
- * pad the input so that it is of the proper length.
- *
- * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH,
- * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
- * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
- * transmitted separately)
- *
- * @see rijndael::disable_padding()
- * @access public
- */
- function enable_padding()
- {
- $this->padding = true;
- }
-
- /**
- * Do not pad packets.
- *
- * @see rijndael::enable_padding()
- * @access public
- */
- function disable_padding()
- {
- $this->padding = false;
- }
-
- /**
- * Pads a string
- *
- * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize.
- * $block_size - (strlen($text) % $block_size) bytes are added, each of which is equal to
- * chr($block_size - (strlen($text) % $block_size)
- *
- * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
- * and padding will, hence forth, be enabled.
- *
- * @see rijndael::_unpad()
- * @access private
- */
- function _pad($text)
- {
- $length = strlen($text);
-
- if (!$this->padding)
- {
- if ($length % $this->block_size == 0)
- {
- return $text;
- }
- else
- {
- $this->padding = true;
- }
- }
-
- $pad = $this->block_size - ($length % $this->block_size);
-
- return str_pad($text, $length + $pad, chr($pad));
- }
-
- /**
- * Unpads a string.
- *
- * If padding is enabled and the reported padding length exceeds the block size, padding will be, hence forth, disabled.
- *
- * @see rijndael::_pad()
- * @access private
- */
- function _unpad($text)
- {
- if (!$this->padding)
- {
- return $text;
- }
-
- $length = ord($text[strlen($text) - 1]);
-
- if ($length > $this->block_size)
- {
- $this->padding = false;
- return $text;
- }
-
- return substr($text, 0, -$length);
- }
-
- /**
- * Treat consecutive "packets" as if they are a continuous buffer.
- *
- * Say you have a 32-byte plaintext $plaintext. Using the default behavior, the two following code snippets
- * will yield different outputs:
- *
- * <code>
- * echo $rijndael->encrypt(substr($plaintext, 0, 16));
- * echo $rijndael->encrypt(substr($plaintext, 16, 16));
- * </code>
- * <code>
- * echo $rijndael->encrypt($plaintext);
- * </code>
- *
- * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
- * another, as demonstrated with the following:
- *
- * <code>
- * $rijndael->encrypt(substr($plaintext, 0, 16));
- * echo $rijndael->decrypt($des->encrypt(substr($plaintext, 16, 16)));
- * </code>
- * <code>
- * echo $rijndael->decrypt($des->encrypt(substr($plaintext, 16, 16)));
- * </code>
- *
- * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
- * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
- * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
- *
- * Put another way, when the continuous buffer is enabled, the state of the rijndael() object changes after each
- * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
- * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
- * however, they are also less intuitive and more likely to cause you problems.
- *
- * @see rijndael::disable_continuous_buffer()
- * @access public
- */
- function enable_continuous_buffer()
- {
- $this->continuousBuffer = true;
- }
-
- /**
- * Treat consecutive packets as if they are a discontinuous buffer.
- *
- * The default behavior.
- *
- * @see rijndael::enable_continuous_buffer()
- * @access public
- */
- function disable_continuous_buffer()
- {
- $this->continuousBuffer = false;
- $this->encryptIV = $this->iv;
- $this->decryptIV = $this->iv;
- }
-
- /**
- * String Shift
- *
- * Inspired by array_shift
- *
- * @param String $string
- * @param optional Integer $index
- * @return String
- * @access private
- */
- function _string_shift(&$string, $index = 1)
- {
- $substr = substr($string, 0, $index);
- $string = substr($string, $index);
- return $substr;
- }
-}
-
-/**
- * Pure-PHP implementation of AES.
- *
- * @author Jim Wigginton <terrafrost@php.net>
- * @version 0.1.0
- * @access public
- * @package aes
- */
-class aes extends rijndael {
- /**
- * MCrypt parameters
- *
- * @see aes::set_mcypt()
- * @var Array
- * @access private
- */
- var $mcrypt = array('', '');
-
- /**
- * Default Constructor.
- *
- * Determines whether or not the mcrypt extension should be used. $mode should only, at present, be
- * CRYPT_AES_MODE_ECB or CRYPT_AES_MODE_CBC. If not explictly set, CRYPT_AES_MODE_CBC will be used.
- *
- * @param optional Integer $mode
- * @return aes
- * @access public
- */
- function __construct($mode = CRYPT_AES_MODE_CBC)
- {
- if ( !defined('CRYPT_AES_MODE') )
- {
- switch (true)
- {
- case extension_loaded('mcrypt'):
- // i'd check to see if aes was supported, by doing in_array('des', mcrypt_list_algorithms('')),
- // but since that can be changed after the object has been created, there doesn't seem to be
- // a lot of point...
- define('CRYPT_AES_MODE', CRYPT_AES_MODE_MCRYPT);
- break;
- default:
- define('CRYPT_AES_MODE', CRYPT_AES_MODE_INTERNAL);
- }
- }
-
- switch ( CRYPT_AES_MODE )
- {
- case CRYPT_AES_MODE_MCRYPT:
- switch ($mode)
- {
- case CRYPT_AES_MODE_ECB:
- $this->mode = MCRYPT_MODE_ECB;
- break;
- case CRYPT_AES_MODE_CBC:
- default:
- $this->mode = MCRYPT_MODE_CBC;
- }
-
- break;
- default:
- switch ($mode)
- {
- case CRYPT_AES_MODE_ECB:
- $this->mode = CRYPT_RIJNDAEL_MODE_ECB;
- break;
- case CRYPT_AES_MODE_CBC:
- default:
- $this->mode = CRYPT_RIJNDAEL_MODE_CBC;
- }
- }
-
- if (CRYPT_AES_MODE == CRYPT_AES_MODE_INTERNAL)
- {
- parent::__construct($this->mode);
- }
- }
-
- /**
- * Dummy function
- *
- * Since aes extends rijndael, this function is, technically, available, but it doesn't do anything.
- *
- * @access public
- * @param Integer $length
- */
- function set_block_length($length)
- {
- return;
- }
-
- /**
- * Encrypts a message.
- *
- * $plaintext will be padded with up to 16 additional bytes. Other AES implementations may or may not pad in the
- * same manner. Other common approaches to padding and the reasons why it's necessary are discussed in the following
- * URL:
- *
- * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
- *
- * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
- * strlen($plaintext) will still need to be a multiple of 16, however, arbitrary values can be added to make it that
- * length.
- *
- * @see aes::decrypt()
- * @access public
- * @param String $plaintext
- */
- function encrypt($plaintext)
- {
- if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT )
- {
- $this->_mcrypt_setup();
- $plaintext = $this->_pad($plaintext);
-
- $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);
- mcrypt_generic_init($td, $this->key, $this->encryptIV);
-
- $ciphertext = mcrypt_generic($td, $plaintext);
-
- mcrypt_generic_deinit($td);
- mcrypt_module_close($td);
-
- if ($this->continuousBuffer)
- {
- $this->encryptIV = substr($ciphertext, -16);
- }
-
- return $ciphertext;
- }
-
- return parent::encrypt($plaintext);
- }
-
- /**
- * Decrypts a message.
- *
- * If strlen($ciphertext) is not a multiple of 16, null bytes will be added to the end of the string until it is.
- *
- * @see aes::encrypt()
- * @access public
- * @param String $ciphertext
- */
- function decrypt($ciphertext)
- {
- // we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
- // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
- $ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 15) & 0xFFFFFFF0, chr(0));
-
- if ( CRYPT_AES_MODE == CRYPT_AES_MODE_MCRYPT )
- {
- $this->_mcryptSetup();
-
- $td = mcrypt_module_open(MCRYPT_RIJNDAEL_128, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);
- mcrypt_generic_init($td, $this->key, $this->decryptIV);
-
- $plaintext = mdecrypt_generic($td, $ciphertext);
-
- mcrypt_generic_deinit($td);
- mcrypt_module_close($td);
-
- if ($this->continuousBuffer)
- {
- $this->decryptIV = substr($ciphertext, -16);
- }
-
- return $this->_unpad($plaintext);
- }
-
- return parent::decrypt($ciphertext);
- }
-
- /**
- * Sets MCrypt parameters. (optional)
- *
- * If MCrypt is being used, empty strings will be used, unless otherwise specified.
- *
- * @link http://php.net/function.mcrypt-module-open#function.mcrypt-module-open
- * @access public
- * @param optional Integer $algorithm_directory
- * @param optional Integer $mode_directory
- */
- function set_mcrypt($algorithm_directory = '', $mode_directory = '')
- {
- $this->mcrypt = array($algorithm_directory, $mode_directory);
- }
-
- /**
- * Setup mcrypt
- *
- * Validates all the variables.
- *
- * @access private
- */
- function _mcrypt_setup()
- {
- if (!$this->changed)
- {
- return;
- }
-
- if (!$this->explicit_key_length)
- {
- // this just copied from rijndael::_setup()
- $length = strlen($this->key) >> 2;
- if ($length > 8)
- {
- $length = 8;
- }
- else if ($length < 4)
- {
- $length = 4;
- }
- $this->Nk = $length;
- $this->key_size = $length << 2;
- }
-
- switch ($this->Nk)
- {
- case 4: // 128
- $this->key_size = 16;
- break;
- case 5: // 160
- case 6: // 192
- $this->key_size = 24;
- break;
- case 7: // 224
- case 8: // 256
- $this->key_size = 32;
- }
-
- $this->key = substr($this->key, 0, $this->key_size);
- $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($this->iv, 0, 16), 16, chr(0));
-
- $this->changed = false;
- }
-
- /**
- * Encrypts a block
- *
- * Optimized over rijndael's implementation by means of loop unrolling.
- *
- * @see rijndael::_encrypt_block()
- * @access private
- * @param String $in
- * @return String
- */
- function _encrypt_block($in)
- {
- // unpack starts it's indices at 1 - not 0.
- $state = unpack('N*', $in);
-
- // addRoundKey and reindex $state
- $state = array(
- $state[1] ^ $this->w[0][0],
- $state[2] ^ $this->w[0][1],
- $state[3] ^ $this->w[0][2],
- $state[4] ^ $this->w[0][3]
- );
-
- // shiftRows + subWord + mixColumns + addRoundKey
- // we could loop unroll this and use if statements to do more rounds as necessary, but, in my tests, that yields
- // only a marginal improvement. since that also, imho, hinders the readability of the code, i've opted not to do it.
- for ($round = 1; $round < $this->Nr; $round++)
- {
- $state = array(
- $this->t0[$state[0] & 0xFF000000] ^ $this->t1[$state[1] & 0x00FF0000] ^ $this->t2[$state[2] & 0x0000FF00] ^ $this->t3[$state[3] & 0x000000FF] ^ $this->w[$round][0],
- $this->t0[$state[1] & 0xFF000000] ^ $this->t1[$state[2] & 0x00FF0000] ^ $this->t2[$state[3] & 0x0000FF00] ^ $this->t3[$state[0] & 0x000000FF] ^ $this->w[$round][1],
- $this->t0[$state[2] & 0xFF000000] ^ $this->t1[$state[3] & 0x00FF0000] ^ $this->t2[$state[0] & 0x0000FF00] ^ $this->t3[$state[1] & 0x000000FF] ^ $this->w[$round][2],
- $this->t0[$state[3] & 0xFF000000] ^ $this->t1[$state[0] & 0x00FF0000] ^ $this->t2[$state[1] & 0x0000FF00] ^ $this->t3[$state[2] & 0x000000FF] ^ $this->w[$round][3]
- );
-
- }
-
- // subWord
- $state = array(
- $this->_sub_word($state[0]),
- $this->_sub_word($state[1]),
- $this->_sub_word($state[2]),
- $this->_sub_word($state[3])
- );
-
- // shiftRows + addRoundKey
- $state = array(
- ($state[0] & 0xFF000000) ^ ($state[1] & 0x00FF0000) ^ ($state[2] & 0x0000FF00) ^ ($state[3] & 0x000000FF) ^ $this->w[$this->Nr][0],
- ($state[1] & 0xFF000000) ^ ($state[2] & 0x00FF0000) ^ ($state[3] & 0x0000FF00) ^ ($state[0] & 0x000000FF) ^ $this->w[$this->Nr][1],
- ($state[2] & 0xFF000000) ^ ($state[3] & 0x00FF0000) ^ ($state[0] & 0x0000FF00) ^ ($state[1] & 0x000000FF) ^ $this->w[$this->Nr][2],
- ($state[3] & 0xFF000000) ^ ($state[0] & 0x00FF0000) ^ ($state[1] & 0x0000FF00) ^ ($state[2] & 0x000000FF) ^ $this->w[$this->Nr][3]
- );
-
- return pack('N*', $state[0], $state[1], $state[2], $state[3]);
- }
-
- /**
- * Decrypts a block
- *
- * Optimized over rijndael's implementation by means of loop unrolling.
- *
- * @see rijndael::_decrypt_block()
- * @access private
- * @param String $in
- * @return String
- */
- function _decrypt_block($in)
- {
- // unpack starts it's indices at 1 - not 0.
- $state = unpack('N*', $in);
-
- // addRoundKey and reindex $state
- $state = array(
- $state[1] ^ $this->dw[$this->Nr][0],
- $state[2] ^ $this->dw[$this->Nr][1],
- $state[3] ^ $this->dw[$this->Nr][2],
- $state[4] ^ $this->dw[$this->Nr][3]
- );
-
- // invShiftRows + invSubBytes + invMixColumns + addRoundKey
- for ($round = $this->Nr - 1; $round > 0; $round--)
- {
- $state = array(
- $this->dt0[$state[0] & 0xFF000000] ^ $this->dt1[$state[3] & 0x00FF0000] ^ $this->dt2[$state[2] & 0x0000FF00] ^ $this->dt3[$state[1] & 0x000000FF] ^ $this->dw[$round][0],
- $this->dt0[$state[1] & 0xFF000000] ^ $this->dt1[$state[0] & 0x00FF0000] ^ $this->dt2[$state[3] & 0x0000FF00] ^ $this->dt3[$state[2] & 0x000000FF] ^ $this->dw[$round][1],
- $this->dt0[$state[2] & 0xFF000000] ^ $this->dt1[$state[1] & 0x00FF0000] ^ $this->dt2[$state[0] & 0x0000FF00] ^ $this->dt3[$state[3] & 0x000000FF] ^ $this->dw[$round][2],
- $this->dt0[$state[3] & 0xFF000000] ^ $this->dt1[$state[2] & 0x00FF0000] ^ $this->dt2[$state[1] & 0x0000FF00] ^ $this->dt3[$state[0] & 0x000000FF] ^ $this->dw[$round][3]
- );
- }
-
- // invShiftRows + invSubWord + addRoundKey
- $state = array(
- $this->_inv_sub_word(($state[0] & 0xFF000000) ^ ($state[3] & 0x00FF0000) ^ ($state[2] & 0x0000FF00) ^ ($state[1] & 0x000000FF)) ^ $this->dw[0][0],
- $this->_inv_sub_word(($state[1] & 0xFF000000) ^ ($state[0] & 0x00FF0000) ^ ($state[3] & 0x0000FF00) ^ ($state[2] & 0x000000FF)) ^ $this->dw[0][1],
- $this->_inv_sub_word(($state[2] & 0xFF000000) ^ ($state[1] & 0x00FF0000) ^ ($state[0] & 0x0000FF00) ^ ($state[3] & 0x000000FF)) ^ $this->dw[0][2],
- $this->_inv_sub_word(($state[3] & 0xFF000000) ^ ($state[2] & 0x00FF0000) ^ ($state[1] & 0x0000FF00) ^ ($state[0] & 0x000000FF)) ^ $this->dw[0][3]
- );
-
- return pack('N*', $state[0], $state[1], $state[2], $state[3]);
- }
-}
-
-?>
\ No newline at end of file diff --git a/phpBB/includes/libraries/sftp/biginteger.php b/phpBB/includes/libraries/sftp/biginteger.php deleted file mode 100644 index d9b90dacb8..0000000000 --- a/phpBB/includes/libraries/sftp/biginteger.php +++ /dev/null @@ -1,2162 +0,0 @@ -<?php
-/**
-*
-* @package sftp
-* @version $Id$
-* @copyright (c) 2006 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Code from http://phpseclib.sourceforge.net/
-*
-* Modified by phpBB Group to meet our coding standards
-* and being able to integrate into phpBB
-*
-* Pure-PHP arbitrary precission integer arithmetic library
-*
-* Copyright 2007-2009 TerraFrost <terrafrost@php.net>
-* Copyright 2009+ phpBB
-*
-* @package sftp
-* @author TerraFrost <terrafrost@php.net>
-*/
-
-/**#@+
- * @access private
- * @see biginteger::_sliding_window()
- */
-/**
- * @see biginteger::_montgomery()
- * @see biginteger::_undo_montgomery()
- */
-define('MATH_BIGINTEGER_MONTGOMERY', 0);
-/**
- * @see biginteger::_barrett()
- */
-define('MATH_BIGINTEGER_BARRETT', 1);
-/**
- * @see biginteger::_mod2()
- */
-define('MATH_BIGINTEGER_POWEROF2', 2);
-/**
- * @see biginteger::_remainder()
- */
-define('MATH_BIGINTEGER_CLASSIC', 3);
-/**
- * @see biginteger::_copy()
- */
-define('MATH_BIGINTEGER_NONE', 4);
-/**#@-*/
-
-/**#@+
- * @access private
- * @see biginteger::_montgomery()
- * @see biginteger::_barrett()
- */
-/**
- * $cache[MATH_BIGINTEGER_VARIABLE] tells us whether or not the cached data is still valid.
- */
-define('MATH_BIGINTEGER_VARIABLE', 0);
-/**
- * $cache[MATH_BIGINTEGER_DATA] contains the cached data.
- */
-define('MATH_BIGINTEGER_DATA', 1);
-/**#@-*/
-
-/**#@+
- * @access private
- * @see biginteger::biginteger()
- */
-/**
- * To use the pure-PHP implementation
- */
-define('MATH_BIGINTEGER_MODE_INTERNAL', 1);
-/**
- * To use the BCMath library
- *
- * (if enabled; otherwise, the internal implementation will be used)
- */
-define('MATH_BIGINTEGER_MODE_BCMATH', 2);
-/**
- * To use the GMP library
- *
- * (if present; otherwise, either the BCMath or the internal implementation will be used)
- */
-define('MATH_BIGINTEGER_MODE_GMP', 3);
-/**#@-*/
-
-/**
- * Pure-PHP arbitrary precision integer arithmetic library. Supports base-2, base-10, base-16, and base-256
- * numbers.
- *
- * @author Jim Wigginton <terrafrost@php.net>
- * @version 1.0.0RC3
- * @access public
- * @package biginteger
- */
-class biginteger
-{
- /**
- * Holds the BigInteger's value.
- *
- * @var Array
- * @access private
- */
- var $value;
-
- /**
- * Holds the BigInteger's magnitude.
- *
- * @var Boolean
- * @access private
- */
- var $is_negative = false;
-
- /**
- * Converts base-2, base-10, base-16, and binary strings (eg. base-256) to BigIntegers.
- *
- * If the second parameter - $base - is negative, then it will be assumed that the number's are encoded using
- * two's compliment. The sole exception to this is -10, which is treated the same as 10 is.
- *
- * @param optional $x base-10 number or base-$base number if $base set.
- * @param optional integer $base
- * @return biginteger
- * @access public
- */
- function __construct($x = 0, $base = 10)
- {
- if ( !defined('MATH_BIGINTEGER_MODE') )
- {
- switch (true)
- {
- case extension_loaded('gmp'):
- define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_GMP);
- break;
- case extension_loaded('bcmath'):
- define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_BCMATH);
- break;
- default:
- define('MATH_BIGINTEGER_MODE', MATH_BIGINTEGER_MODE_INTERNAL);
- }
- }
-
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $this->value = gmp_init(0);
- break;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $this->value = '0';
- break;
- default:
- $this->value = array();
- }
-
- if ($x === 0)
- {
- return;
- }
-
- switch ($base)
- {
- case -256:
- if (ord($x[0]) & 0x80)
- {
- $x = ~$x;
- $this->is_negative = true;
- }
- case 256:
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = unpack('H*hex', $x);
- $sign = $this->is_negative ? '-' : '';
- $this->value = gmp_init($sign . '0x' . $temp['hex']);
- break;
- case MATH_BIGINTEGER_MODE_BCMATH:
- // round $len to the nearest 4 (thanks, DavidMJ!)
- $len = (strlen($x) + 3) & 0xFFFFFFFC;
-
- $x = str_pad($x, $len, chr(0), STR_PAD_LEFT);
-
- for ($i = 0; $i < $len; $i+= 4) {
- $this->value = bcmul($this->value, '4294967296'); // 4294967296 == 2**32
- $this->value = bcadd($this->value, 0x1000000 * ord($x[$i]) + ((ord($x[$i + 1]) << 16) | (ord($x[$i + 2]) << 8) | ord($x[$i + 3])));
- }
-
- if ($this->is_negative) {
- $this->value = '-' . $this->value;
- }
-
- break;
- // converts a base-2**8 (big endian / msb) number to base-2**26 (little endian / lsb)
- case MATH_BIGINTEGER_MODE_INTERNAL:
- while (strlen($x))
- {
- $this->value[] = $this->_bytes2int($this->_base256_rshift($x, 26));
- }
- }
-
- if ($this->is_negative)
- {
- if (MATH_BIGINTEGER_MODE != MATH_BIGINTEGER_MODE_INTERNAL)
- {
- $this->is_negative = false;
- }
- $temp = $this->add(new biginteger('-1'));
- $this->value = $temp->value;
- }
- break;
- case 16:
- case -16:
- if ($base > 0 && $x[0] == '-')
- {
- $this->is_negative = true;
- $x = substr($x, 1);
- }
-
- $x = preg_replace('#^(?:0x)?([A-Fa-f0-9]*).*#', '$1', $x);
-
- $is_negative = false;
- if ($base < 0 && hexdec($x[0]) >= 8)
- {
- $this->is_negative = $is_negative = true;
- $x = bin2hex(~pack('H*', $x));
- }
-
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = $this->is_negative ? '-0x' . $x : '0x' . $x;
- $this->value = gmp_init($temp);
- $this->is_negative = false;
- break;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $x = ( strlen($x) & 1 ) ? '0' . $x : $x;
- $temp = new biginteger(pack('H*', $x), 256);
- $this->value = $this->is_negative ? '-' . $temp->value : $temp->value;
- $this->is_negative = false;
- break;
- case MATH_BIGINTEGER_MODE_INTERNAL:
- $x = ( strlen($x) & 1 ) ? '0' . $x : $x;
- $temp = new biginteger(pack('H*', $x), 256);
- $this->value = $temp->value;
- }
-
- if ($is_negative)
- {
- $temp = $this->add(new biginteger('-1'));
- $this->value = $temp->value;
- }
- break;
- case 10:
- case -10:
- $x = preg_replace('#^(-?[0-9]*).*#', '$1', $x);
-
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $this->value = gmp_init($x);
- break;
- case MATH_BIGINTEGER_MODE_BCMATH:
- // explicitly casting $x to a string is necessary, here, since doing $x[0] on -1 yields different
- // results then doing it on '-1' does (modInverse does $x[0])
- $this->value = (string) $x;
- break;
- case MATH_BIGINTEGER_MODE_INTERNAL:
- $temp = new biginteger();
-
- // array(10000000) is 10**7 in base-2**26. 10**7 is the closest to 2**26 we can get without passing it.
- $multiplier = new biginteger();
- $multiplier->value = array(10000000);
-
- if ($x[0] == '-')
- {
- $this->is_negative = true;
- $x = substr($x, 1);
- }
-
- $x = str_pad($x, strlen($x) + (6 * strlen($x)) % 7, 0, STR_PAD_LEFT);
-
- while (strlen($x))
- {
- $temp = $temp->multiply($multiplier);
- $temp = $temp->add(new biginteger($this->_int2bytes(substr($x, 0, 7)), 256));
- $x = substr($x, 7);
- }
-
- $this->value = $temp->value;
- }
- break;
- case 2: // base-2 support originally implemented by Lluis Pamies - thanks!
- case -2:
- if ($base > 0 && $x[0] == '-')
- {
- $this->is_negative = true;
- $x = substr($x, 1);
- }
-
- $x = preg_replace('#^([01]*).*#', '$1', $x);
- $x = str_pad($x, strlen($x) + (3 * strlen($x)) % 4, 0, STR_PAD_LEFT);
-
- $str = '0x';
- while (strlen($x))
- {
- $part = substr($x, 0, 4);
- $str.= dechex(bindec($part));
- $x = substr($x, 4);
- }
-
- if ($this->is_negative)
- {
- $str = '-' . $str;
- }
-
- $temp = new biginteger($str, 8 * $base); // ie. either -16 or +16
- $this->value = $temp->value;
- $this->is_negative = $temp->is_negative;
-
- break;
- default:
- // base not supported, so we'll let $this == 0
- }
- }
-
- /**
- * Converts a BigInteger to a byte string (eg. base-256).
- *
- * Negative numbers are saved as positive numbers, unless $twos_compliment is set to true, at which point, they're
- * saved as two's compliment.
- *
- * @param Boolean $twos_compliment
- * @return String
- * @access public
- * @internal Converts a base-2**26 number to base-2**8
- */
- function to_bytes($twos_compliment = false)
- {
- if ($twos_compliment)
- {
- $comparison = $this->compare(new biginteger());
- if ($comparison == 0)
- {
- return '';
- }
-
- $temp = $comparison < 0 ? $this->add(new biginteger(1)) : $this->_copy();
- $bytes = $temp->to_bytes();
-
- if (empty($bytes)) // eg. if the number we're trying to convert is -1
- {
- $bytes = chr(0);
- }
-
- if (ord($bytes[0]) & 0x80)
- {
- $bytes = chr(0) . $bytes;
- }
-
- return $comparison < 0 ? ~$bytes : $bytes;
- }
-
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- if (gmp_cmp($this->value, gmp_init(0)) == 0)
- {
- return '';
- }
-
- $temp = gmp_strval(gmp_abs($this->value), 16);
- $temp = ( strlen($temp) & 1 ) ? '0' . $temp : $temp;
-
- return ltrim(pack('H*', $temp), chr(0));
- case MATH_BIGINTEGER_MODE_BCMATH:
- if ($this->value === '0')
- {
- return '';
- }
-
- $value = '';
- $current = $this->value;
-
- if ($current[0] == '-')
- {
- $current = substr($current, 1);
- }
-
- // we don't do four bytes at a time because then numbers larger than 1<<31 would be negative
- // two's complimented numbers, which would break chr.
- while (bccomp($current, '0') > 0)
- {
- $temp = bcmod($current, 0x1000000);
- $value = chr($temp >> 16) . chr($temp >> 8) . chr($temp) . $value;
- $current = bcdiv($current, 0x1000000);
- }
-
- return ltrim($value, chr(0));
- }
-
- if (!count($this->value))
- {
- return '';
- }
-
- $result = $this->_int2bytes($this->value[count($this->value) - 1]);
-
- $temp = $this->_copy();
-
- for ($i = count($temp->value) - 2; $i >= 0; $i--)
- {
- $temp->_base256_lshift($result, 26);
- $result = $result | str_pad($temp->_int2bytes($temp->value[$i]), strlen($result), chr(0), STR_PAD_LEFT);
- }
-
- return $result;
- }
-
- /**
- * Converts a BigInteger to a base-10 number.
- *
- * @return String
- * @access public
- * @internal Converts a base-2**26 number to base-10**7 (which is pretty much base-10)
- */
- function to_string()
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- return gmp_strval($this->value);
- case MATH_BIGINTEGER_MODE_BCMATH:
- if ($this->value === '0')
- {
- return '0';
- }
-
- return ltrim($this->value, '0');
- }
-
- if (!count($this->value))
- {
- return '0';
- }
-
- $temp = $this->_copy();
- $temp->is_negative = false;
-
- $divisor = new biginteger();
- $divisor->value = array(10000000); // eg. 10**7
- while (count($temp->value))
- {
- list($temp, $mod) = $temp->divide($divisor);
- $result = str_pad($this->_bytes2int($mod->to_bytes()), 7, '0', STR_PAD_LEFT) . $result;
- }
- $result = ltrim($result, '0');
-
- if ($this->is_negative)
- {
- $result = '-' . $result;
- }
-
- return $result;
- }
-
- /**
- * __toString() magic method
- *
- * Will be called, automatically, if you're supporting just PHP5. If you're supporting PHP4, you'll need to call
- * toString().
- *
- * @access public
- * @internal Implemented per a suggestion by Techie-Michael - thanks!
- */
- function __toString()
- {
- return $this->to_string();
- }
-
- /**
- * Adds two BigIntegers.
- *
- * @param biginteger $y
- * @return biginteger
- * @access public
- * @internal Performs base-2**52 addition
- */
- function add($y)
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new biginteger();
- $temp->value = gmp_add($this->value, $y->value);
-
- return $temp;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $temp = new biginteger();
- $temp->value = bcadd($this->value, $y->value);
-
- return $temp;
- }
-
- // subtract, if appropriate
- if ( $this->is_negative != $y->is_negative )
- {
- // is $y the negative number?
- $y_negative = $this->compare($y) > 0;
-
- $temp = $this->_copy();
- $y = $y->_copy();
- $temp->is_negative = $y->is_negative = false;
-
- $diff = $temp->compare($y);
- if ( !$diff )
- {
- return new biginteger();
- }
-
- $temp = $temp->subtract($y);
-
- $temp->is_negative = ($diff > 0) ? !$y_negative : $y_negative;
-
- return $temp;
- }
-
- $result = new biginteger();
- $carry = 0;
-
- $size = max(count($this->value), count($y->value));
- $size+= $size & 1; // rounds $size to the nearest 2.
-
- $x = array_pad($this->value, $size,0);
- $y = array_pad($y->value, $size, 0);
-
- for ($i = 0; $i < $size - 1; $i+=2)
- {
- $sum = $x[$i + 1] * 0x4000000 + $x[$i] + $y[$i + 1] * 0x4000000 + $y[$i] + $carry;
- $carry = $sum >= 4503599627370496; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
- $sum = $carry ? $sum - 4503599627370496 : $sum;
-
- $temp = floor($sum / 0x4000000);
-
- $result->value[] = $sum - 0x4000000 * $temp; // eg. a faster alternative to fmod($sum, 0x4000000)
- $result->value[] = $temp;
- }
-
- if ($carry)
- {
- $result->value[] = $carry;
- }
-
- $result->is_negative = $this->is_negative;
-
- return $result->_normalize();
- }
-
- /**
- * Subtracts two BigIntegers.
- *
- * @param biginteger $y
- * @return biginteger
- * @access public
- * @internal Performs base-2**52 subtraction
- */
- function subtract($y)
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new biginteger();
- $temp->value = gmp_sub($this->value, $y->value);
-
- return $temp;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $temp = new biginteger();
- $temp->value = bcsub($this->value, $y->value);
-
- return $temp;
- }
-
- // add, if appropriate
- if ( $this->is_negative != $y->is_negative )
- {
- $is_negative = $y->compare($this) > 0;
-
- $temp = $this->_copy();
- $y = $y->_copy();
- $temp->is_negative = $y->is_negative = false;
-
- $temp = $temp->add($y);
-
- $temp->is_negative = $is_negative;
-
- return $temp;
- }
-
- $diff = $this->compare($y);
-
- if ( !$diff )
- {
- return new biginteger();
- }
-
- // switch $this and $y around, if appropriate.
- if ( (!$this->is_negative && $diff < 0) || ($this->is_negative && $diff > 0) )
- {
- $is_negative = $y->is_negative;
-
- $temp = $this->_copy();
- $y = $y->_copy();
- $temp->is_negative = $y->is_negative = false;
-
- $temp = $y->subtract($temp);
- $temp->is_negative = !$is_negative;
-
- return $temp;
- }
-
- $result = new biginteger();
- $carry = 0;
-
- $size = max(count($this->value), count($y->value));
- $size+= $size % 2;
-
- $x = array_pad($this->value, $size, 0);
- $y = array_pad($y->value, $size, 0);
-
- for ($i = 0; $i < $size - 1; $i+=2)
- {
- $sum = $x[$i + 1] * 0x4000000 + $x[$i] - $y[$i + 1] * 0x4000000 - $y[$i] + $carry;
- $carry = $sum < 0 ? -1 : 0; // eg. floor($sum / 2**52); only possible values (in any base) are 0 and 1
- $sum = $carry ? $sum + 4503599627370496 : $sum;
-
- $temp = floor($sum / 0x4000000);
-
- $result->value[] = $sum - 0x4000000 * $temp;
- $result->value[] = $temp;
- }
-
- // $carry shouldn't be anything other than zero, at this point, since we already made sure that $this
- // was bigger than $y.
-
- $result->is_negative = $this->is_negative;
-
- return $result->_normalize();
- }
-
- /**
- * Multiplies two BigIntegers
- *
- * @param biginteger $x
- * @return biginteger
- * @access public
- * @internal Modeled after 'multiply' in MutableBigInteger.java.
- */
- function multiply($x)
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new biginteger();
- $temp->value = gmp_mul($this->value, $x->value);
-
- return $temp;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $temp = new biginteger();
- $temp->value = bcmul($this->value, $x->value);
-
- return $temp;
- }
-
- if ( !$this->compare($x) )
- {
- return $this->_square();
- }
-
- $this_length = count($this->value);
- $x_length = count($x->value);
-
- if ( !$this_length || !$x_length ) // a 0 is being multiplied
- {
- return new biginteger();
- }
-
- $product = new biginteger();
- $product->value = $this->_array_repeat(0, $this_length + $x_length);
-
- // the following for loop could be removed if the for loop following it
- // (the one with nested for loops) initially set $i to 0, but
- // doing so would also make the result in one set of unnecessary adds,
- // since on the outermost loops first pass, $product->value[$k] is going
- // to always be 0
-
- $carry = 0;
- $i = 0;
-
- for ($j = 0, $k = $i; $j < $this_length; $j++, $k++)
- {
- $temp = $product->value[$k] + $this->value[$j] * $x->value[$i] + $carry;
- $carry = floor($temp / 0x4000000);
- $product->value[$k] = $temp - 0x4000000 * $carry;
- }
-
- $product->value[$k] = $carry;
-
- // the above for loop is what the previous comment was talking about. the
- // following for loop is the "one with nested for loops"
-
- for ($i = 1; $i < $x_length; $i++)
- {
- $carry = 0;
-
- for ($j = 0, $k = $i; $j < $this_length; $j++, $k++)
- {
- $temp = $product->value[$k] + $this->value[$j] * $x->value[$i] + $carry;
- $carry = floor($temp / 0x4000000);
- $product->value[$k] = $temp - 0x4000000 * $carry;
- }
-
- $product->value[$k] = $carry;
- }
-
- $product->is_negative = $this->is_negative != $x->is_negative;
-
- return $product->_normalize();
- }
-
- /**
- * Squares a BigInteger
- *
- * Squaring can be done faster than multiplying a number by itself can be. See
- * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=7 HAC 14.2.4} /
- * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=141 MPM 5.3} for more information.
- *
- * @return biginteger
- * @access private
- */
- function _square()
- {
- if ( empty($this->value) )
- {
- return new biginteger();
- }
-
- $max_index = count($this->value) - 1;
-
- $square = new biginteger();
- $square->value = $this->_array_repeat(0, 2 * $max_index);
-
- for ($i = 0; $i <= $max_index; $i++)
- {
- $temp = $square->value[2 * $i] + $this->value[$i] * $this->value[$i];
- $carry = floor($temp / 0x4000000);
- $square->value[2 * $i] = $temp - 0x4000000 * $carry;
-
- // note how we start from $i+1 instead of 0 as we do in multiplication.
- for ($j = $i + 1; $j <= $max_index; $j++)
- {
- $temp = $square->value[$i + $j] + 2 * $this->value[$j] * $this->value[$i] + $carry;
- $carry = floor($temp / 0x4000000);
- $square->value[$i + $j] = $temp - 0x4000000 * $carry;
- }
-
- // the following line can yield values larger 2**15. at this point, PHP should switch
- // over to floats.
- $square->value[$i + $max_index + 1] = $carry;
- }
-
- return $square->_normalize();
- }
-
- /**
- * Divides two BigIntegers.
- *
- * Returns an array whose first element contains the quotient and whose second element contains the
- * "common residue". If the remainder would be positive, the "common residue" and the remainder are the
- * same. If the remainder would be negative, the "common residue" is equal to the sum of the remainder
- * and the divisor (basically, the "common residue" is the first positive modulo).
- *
- * @param biginteger $y
- * @return Array
- * @access public
- * @internal This function is based off of {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=9 HAC 14.20}
- * with a slight variation due to the fact that this script, initially, did not support negative numbers. Now,
- * it does, but I don't want to change that which already works.
- */
- function divide($y)
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $quotient = new biginteger();
- $remainder = new biginteger();
-
- list($quotient->value, $remainder->value) = gmp_div_qr($this->value, $y->value);
-
- if (gmp_sign($remainder->value) < 0)
- {
- $remainder->value = gmp_add($remainder->value, gmp_abs($y->value));
- }
-
- return array($quotient, $remainder);
- case MATH_BIGINTEGER_MODE_BCMATH:
- $quotient = new biginteger();
- $remainder = new biginteger();
-
- $quotient->value = bcdiv($this->value, $y->value);
- $remainder->value = bcmod($this->value, $y->value);
-
- if ($remainder->value[0] == '-')
- {
- $remainder->value = bcadd($remainder->value, $y->value[0] == '-' ? substr($y->value, 1) : $y->value);
- }
-
- return array($quotient, $remainder);
- }
-
- $x = $this->_copy();
- $y = $y->_copy();
-
- $x_sign = $x->is_negative;
- $y_sign = $y->is_negative;
-
- $x->is_negative = $y->is_negative = false;
-
- $diff = $x->compare($y);
-
- if ( !$diff )
- {
- $temp = new biginteger();
- $temp->value = array(1);
- $temp->is_negative = $x_sign != $y_sign;
- return array($temp, new biginteger());
- }
-
- if ( $diff < 0 )
- {
- // if $x is negative, "add" $y.
- if ( $x_sign )
- {
- $x = $y->subtract($x);
- }
- return array(new biginteger(), $x);
- }
-
- // normalize $x and $y as described in HAC 14.23 / 14.24
- // (incidently, i haven't been able to find a definitive example showing that this
- // results in worth-while speedup, but whatever)
- $msb = $y->value[count($y->value) - 1];
- for ($shift = 0; !($msb & 0x2000000); $shift++)
- {
- $msb <<= 1;
- }
- $x->_lshift($shift);
- $y->_lshift($shift);
-
- $x_max = count($x->value) - 1;
- $y_max = count($y->value) - 1;
-
- $quotient = new biginteger();
- $quotient->value = $this->_array_repeat(0, $x_max - $y_max + 1);
-
- // $temp = $y << ($x_max - $y_max-1) in base 2**26
- $temp = new biginteger();
- $temp->value = array_merge($this->_array_repeat(0, $x_max - $y_max), $y->value);
-
- while ( $x->compare($temp) >= 0 )
- {
- // calculate the "common residue"
- $quotient->value[$x_max - $y_max]++;
- $x = $x->subtract($temp);
- $x_max = count($x->value) - 1;
- }
-
- for ($i = $x_max; $i >= $y_max + 1; $i--)
- {
- $x_value = array(
- $x->value[$i],
- ( $i > 0 ) ? $x->value[$i - 1] : 0,
- ( $i - 1 > 0 ) ? $x->value[$i - 2] : 0
- );
- $y_value = array(
- $y->value[$y_max],
- ( $y_max > 0 ) ? $y_max - 1 : 0
- );
-
-
- $q_index = $i - $y_max - 1;
- if ($x_value[0] == $y_value[0])
- {
- $quotient->value[$q_index] = 0x3FFFFFF;
- }
- else
- {
- $quotient->value[$q_index] = floor(
- ($x_value[0] * 0x4000000 + $x_value[1])
- /
- $y_value[0]
- );
- }
-
- $temp = new biginteger();
- $temp->value = array($y_value[1], $y_value[0]);
-
- $lhs = new biginteger();
- $lhs->value = array($quotient->value[$q_index]);
- $lhs = $lhs->multiply($temp);
-
- $rhs = new biginteger();
- $rhs->value = array($x_value[2], $x_value[1], $x_value[0]);
-
- while ( $lhs->compare($rhs) > 0 )
- {
- $quotient->value[$q_index]--;
-
- $lhs = new biginteger();
- $lhs->value = array($quotient->value[$q_index]);
- $lhs = $lhs->multiply($temp);
- }
-
- $corrector = new biginteger();
- $temp = new biginteger();
- $corrector->value = $temp->value = $this->_array_repeat(0, $q_index);
- $temp->value[] = $quotient->value[$q_index];
-
- $temp = $temp->multiply($y);
-
- if ( $x->compare($temp) < 0 )
- {
- $corrector->value[] = 1;
- $x = $x->add($corrector->multiply($y));
- $quotient->value[$q_index]--;
- }
-
- $x = $x->subtract($temp);
- $x_max = count($x->value) - 1;
- }
-
- // unnormalize the remainder
- $x->_rshift($shift);
-
- $quotient->is_negative = $x_sign != $y_sign;
-
- // calculate the "common residue", if appropriate
- if ( $x_sign )
- {
- $y->_rshift($shift);
- $x = $y->subtract($x);
- }
-
- return array($quotient->_normalize(), $x);
- }
-
- /**
- * Performs modular exponentiation.
- *
- * @param biginteger $e
- * @param biginteger $n
- * @return biginteger
- * @access public
- * @internal The most naive approach to modular exponentiation has very unreasonable requirements, and
- * and although the approach involving repeated squaring does vastly better, it, too, is impractical
- * for our purposes. The reason being that division - by far the most complicated and time-consuming
- * of the basic operations (eg. +,-,*,/) - occurs multiple times within it.
- *
- * Modular reductions resolve this issue. Although an individual modular reduction takes more time
- * then an individual division, when performed in succession (with the same modulo), they're a lot faster.
- *
- * The two most commonly used modular reductions are Barrett and Montgomery reduction. Montgomery reduction,
- * although faster, only works when the gcd of the modulo and of the base being used is 1. In RSA, when the
- * base is a power of two, the modulo - a product of two primes - is always going to have a gcd of 1 (because
- * the product of two odd numbers is odd), but what about when RSA isn't used?
- *
- * In contrast, Barrett reduction has no such constraint. As such, some bigint implementations perform a
- * Barrett reduction after every operation in the modpow function. Others perform Barrett reductions when the
- * modulo is even and Montgomery reductions when the modulo is odd. BigInteger.java's modPow method, however,
- * uses a trick involving the Chinese Remainder Theorem to factor the even modulo into two numbers - one odd and
- * the other, a power of two - and recombine them, later. This is the method that this modPow function uses.
- * {@link http://islab.oregonstate.edu/papers/j34monex.pdf Montgomery Reduction with Even Modulus} elaborates.
- */
- function mod_pow($e, $n)
- {
- $n = $n->abs();
- if ($e->compare(new biginteger()) < 0)
- {
- $e = $e->abs();
-
- $temp = $this->modInverse($n);
- if ($temp === false)
- {
- return false;
- }
-
- return $temp->modPow($e, $n);
- }
-
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new biginteger();
- $temp->value = gmp_powm($this->value, $e->value, $n->value);
-
- return $temp;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $temp = new biginteger();
- $temp->value = bcpowmod($this->value, $e->value, $n->value);
-
- return $temp;
- }
-
- if ( empty($e->value) )
- {
- $temp = new biginteger();
- $temp->value = array(1);
- return $temp;
- }
-
- if ( $e->value == array(1) )
- {
- list(, $temp) = $this->divide($n);
- return $temp;
- }
-
- if ( $e->value == array(2) )
- {
- $temp = $this->_square();
- list(, $temp) = $temp->divide($n);
- return $temp;
- }
-
- // is the modulo odd?
- if ( $n->value[0] & 1 )
- {
- return $this->_slidingWindow($e, $n, MATH_BIGINTEGER_MONTGOMERY);
- }
- // if it's not, it's even
-
- // find the lowest set bit (eg. the max pow of 2 that divides $n)
- for ($i = 0; $i < count($n->value); $i++)
- {
- if ( $n->value[$i] )
- {
- $temp = decbin($n->value[$i]);
- $j = strlen($temp) - strrpos($temp, '1') - 1;
- $j+= 26 * $i;
- break;
- }
- }
- // at this point, 2^$j * $n/(2^$j) == $n
-
- $mod1 = $n->_copy();
- $mod1->_rshift($j);
- $mod2 = new biginteger();
- $mod2->value = array(1);
- $mod2->_lshift($j);
-
- $part1 = ( $mod1->value != array(1) ) ? $this->_slidingWindow($e, $mod1, MATH_BIGINTEGER_MONTGOMERY) : new biginteger();
- $part2 = $this->_sliding_window($e, $mod2, MATH_BIGINTEGER_POWEROF2);
-
- $y1 = $mod2->mod_inverse($mod1);
- $y2 = $mod1->mod_inverse($mod2);
-
- $result = $part1->multiply($mod2);
- $result = $result->multiply($y1);
-
- $temp = $part2->multiply($mod1);
- $temp = $temp->multiply($y2);
-
- $result = $result->add($temp);
- list(, $result) = $result->divide($n);
-
- return $result;
- }
-
- /**
- * Sliding Window k-ary Modular Exponentiation
- *
- * Based on {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=27 HAC 14.85} /
- * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=210 MPM 7.7}. In a departure from those algorithims,
- * however, this function performs a modular reduction after every multiplication and squaring operation.
- * As such, this function has the same preconditions that the reductions being used do.
- *
- * @param biginteger $e
- * @param biginteger $n
- * @param Integer $mode
- * @return biginteger
- * @access private
- */
- function _sliding_window($e, $n, $mode)
- {
- static $window_ranges = array(7, 25, 81, 241, 673, 1793); // from BigInteger.java's oddModPow function
- //static $window_ranges = array(0, 7, 36, 140, 450, 1303, 3529); // from MPM 7.3.1
-
- $e_length = count($e->value) - 1;
- $e_bits = decbin($e->value[$e_length]);
- for ($i = $e_length - 1; $i >= 0; $i--)
- {
- $e_bits.= str_pad(decbin($e->value[$i]), 26, '0', STR_PAD_LEFT);
- }
- $e_length = strlen($e_bits);
-
- // calculate the appropriate window size.
- // $window_size == 3 if $window_ranges is between 25 and 81, for example.
- for ($i = 0, $window_size = 1; $e_length > $window_ranges[$i] && $i < count($window_ranges); $window_size++, $i++);
-
- switch ($mode)
- {
- case MATH_BIGINTEGER_MONTGOMERY:
- $reduce = '_montgomery';
- $undo = '_undo_montgomery';
- break;
- case MATH_BIGINTEGER_BARRETT:
- $reduce = '_barrett';
- $undo = '_barrett';
- break;
- case MATH_BIGINTEGER_POWEROF2:
- $reduce = '_mod2';
- $undo = '_mod2';
- break;
- case MATH_BIGINTEGER_CLASSIC:
- $reduce = '_remainder';
- $undo = '_remainder';
- break;
- case MATH_BIGINTEGER_NONE:
- // ie. do no modular reduction. useful if you want to just do pow as opposed to modPow.
- $reduce = '_copy';
- $undo = '_copy';
- break;
- default:
- // an invalid $mode was provided
- }
-
- // precompute $this^0 through $this^$window_size
- $powers = array();
- $powers[1] = $this->$undo($n);
- $powers[2] = $powers[1]->_square();
- $powers[2] = $powers[2]->$reduce($n);
-
- // we do every other number since substr($e_bits, $i, $j+1) (see below) is supposed to end
- // in a 1. ie. it's supposed to be odd.
- $temp = 1 << ($window_size - 1);
- for ($i = 1; $i < $temp; $i++)
- {
- $powers[2 * $i + 1] = $powers[2 * $i - 1]->multiply($powers[2]);
- $powers[2 * $i + 1] = $powers[2 * $i + 1]->$reduce($n);
- }
-
- $result = new biginteger();
- $result->value = array(1);
- $result = $result->$undo($n);
-
- for ($i = 0; $i < $e_length; )
- {
- if ( !$e_bits[$i] )
- {
- $result = $result->_square();
- $result = $result->$reduce($n);
- $i++;
- }
- else
- {
- for ($j = $window_size - 1; $j >= 0; $j--)
- {
- if ( $e_bits[$i + $j] )
- {
- break;
- }
- }
-
- for ($k = 0; $k <= $j; $k++) // eg. the length of substr($e_bits, $i, $j+1)
- {
- $result = $result->_square();
- $result = $result->$reduce($n);
- }
-
- $result = $result->multiply($powers[bindec(substr($e_bits, $i, $j + 1))]);
- $result = $result->$reduce($n);
-
- $i+=$j + 1;
- }
- }
-
- $result = $result->$reduce($n);
- return $result->_normalize();
- }
-
- /**
- * Remainder
- *
- * A wrapper for the divide function.
- *
- * @see divide()
- * @see _slidingWindow()
- * @access private
- * @param biginteger
- * @return biginteger
- */
- function _remainder($n)
- {
- list(, $temp) = $this->divide($n);
- return $temp;
- }
-
- /**
- * Modulos for Powers of Two
- *
- * Calculates $x%$n, where $n = 2**$e, for some $e. Since this is basically the same as doing $x & ($n-1),
- * we'll just use this function as a wrapper for doing that.
- *
- * @see _slidingWindow()
- * @access private
- * @param biginteger
- * @return biginteger
- */
- function _mod2($n)
- {
- $temp = new biginteger();
- $temp->value = array(1);
- return $this->bitwise_and($n->subtract($temp));
- }
-
- /**
- * Barrett Modular Reduction
- *
- * See {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=14 HAC 14.3.3} /
- * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=165 MPM 6.2.5} for more information. Modified slightly,
- * so as not to require negative numbers (initially, this script didn't support negative numbers).
- *
- * @see _slidingWindow()
- * @access private
- * @param biginteger
- * @return biginteger
- */
- function _barrett($n)
- {
- static $cache;
-
- $n_length = count($n->value);
-
- if ( !isset($cache[MATH_BIGINTEGER_VARIABLE]) || $n->compare($cache[MATH_BIGINTEGER_VARIABLE]) )
- {
- $cache[MATH_BIGINTEGER_VARIABLE] = $n;
- $temp = new biginteger();
- $temp->value = $this->_array_repeat(0, 2 * $n_length);
- $temp->value[] = 1;
- list($cache[MATH_BIGINTEGER_DATA], ) = $temp->divide($n);
- }
-
- $temp = new biginteger();
- $temp->value = array_slice($this->value, $n_length - 1);
- $temp = $temp->multiply($cache[MATH_BIGINTEGER_DATA]);
- $temp->value = array_slice($temp->value, $n_length + 1);
-
- $result = new biginteger();
- $result->value = array_slice($this->value, 0, $n_length + 1);
- $temp = $temp->multiply($n);
- $temp->value = array_slice($temp->value, 0, $n_length + 1);
-
- if ($result->compare($temp) < 0)
- {
- $corrector = new biginteger();
- $corrector->value = $this->_array_repeat(0, $n_length + 1);
- $corrector->value[] = 1;
- $result = $result->add($corrector);
- }
-
- $result = $result->subtract($temp);
- while ($result->compare($n) > 0)
- {
- $result = $result->subtract($n);
- }
-
- return $result;
- }
-
- /**
- * Montgomery Modular Reduction
- *
- * ($this->_montgomery($n))->_undoMontgomery($n) yields $x%$n.
- * {@link http://math.libtomcrypt.com/files/tommath.pdf#page=170 MPM 6.3} provides insights on how this can be
- * improved upon (basically, by using the comba method). gcd($n, 2) must be equal to one for this function
- * to work correctly.
- *
- * @see _undoMontgomery()
- * @see _slidingWindow()
- * @access private
- * @param biginteger
- * @return biginteger
- */
- function _montgomery($n)
- {
- static $cache;
-
- if ( !isset($cache[MATH_BIGINTEGER_VARIABLE]) || $n->compare($cache[MATH_BIGINTEGER_VARIABLE]) )
- {
- $cache[MATH_BIGINTEGER_VARIABLE] = $n;
- $cache[MATH_BIGINTEGER_DATA] = $n->_mod_inverse67108864();
- }
-
- $result = $this->_copy();
-
- $n_length = count($n->value);
-
- for ($i = 0; $i < $n_length; $i++)
- {
- $temp = new biginteger();
- $temp->value = array(
- ($result->value[$i] * $cache[MATH_BIGINTEGER_DATA]) & 0x3FFFFFF
- );
- $temp = $temp->multiply($n);
- $temp->value = array_merge($this->_array_repeat(0, $i), $temp->value);
- $result = $result->add($temp);
- }
-
- $result->value = array_slice($result->value, $n_length);
-
- if ($result->compare($n) >= 0)
- {
- $result = $result->subtract($n);
- }
-
- return $result->_normalize();
- }
-
- /**
- * Undo Montgomery Modular Reduction
- *
- * @see _montgomery()
- * @see _slidingWindow()
- * @access private
- * @param biginteger
- * @return biginteger
- */
- function _undo_montgomery($n)
- {
- $temp = new biginteger();
- $temp->value = array_merge($this->_array_repeat(0, count($n->value)), $this->value);
- list(, $temp) = $temp->divide($n);
- return $temp->_normalize();
- }
-
- /**
- * Modular Inverse of a number mod 2**26 (eg. 67108864)
- *
- * Based off of the bnpInvDigit function implemented and justified in the following URL:
- *
- * {@link http://www-cs-students.stanford.edu/~tjw/jsbn/jsbn.js}
- *
- * The following URL provides more info:
- *
- * {@link http://groups.google.com/group/sci.crypt/msg/7a137205c1be7d85}
- *
- * As for why we do all the bitmasking... strange things can happen when converting from floats to ints. For
- * instance, on some computers, var_dump((int) -4294967297) yields int(-1) and on others, it yields
- * int(-2147483648). To avoid problems stemming from this, we use bitmasks to guarantee that ints aren't
- * auto-converted to floats. The outermost bitmask is present because without it, there's no guarantee that
- * the "residue" returned would be the so-called "common residue". We use fmod, in the last step, because the
- * maximum possible $x is 26 bits and the maximum $result is 16 bits. Thus, we have to be able to handle up to
- * 40 bits, which only 64-bit floating points will support.
- *
- * Thanks to Pedro Gimeno Fortea for input!
- *
- * @see _montgomery()
- * @access private
- * @return Integer
- */
- function _mod_inverse67108864() // 2**26 == 67108864
- {
- $x = -$this->value[0];
- $result = $x & 0x3; // x**-1 mod 2**2
- $result = ($result * (2 - $x * $result)) & 0xF; // x**-1 mod 2**4
- $result = ($result * (2 - ($x & 0xFF) * $result)) & 0xFF; // x**-1 mod 2**8
- $result = ($result * ((2 - ($x & 0xFFFF) * $result) & 0xFFFF)) & 0xFFFF; // x**-1 mod 2**16
- $result = fmod($result * (2 - fmod($x * $result, 0x4000000)), 0x4000000); // x**-1 mod 2**26
- return $result & 0x3FFFFFF;
- }
-
- /**
- * Calculates modular inverses.
- *
- * @param biginteger $n
- * @return mixed false, if no modular inverse exists, biginteger, otherwise.
- * @access public
- * @internal Calculates the modular inverse of $this mod $n using the binary xGCD algorithim described in
- * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=19 HAC 14.61}. As the text above 14.61 notes,
- * the more traditional algorithim requires "relatively costly multiple-precision divisions". See
- * {@link http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf#page=21 HAC 14.64} for more information.
- */
- function mod_inverse($n)
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new biginteger();
- $temp->value = gmp_invert($this->value, $n->value);
-
- return ( $temp->value === false ) ? false : $temp;
- case MATH_BIGINTEGER_MODE_BCMATH:
- // it might be faster to use the binary xGCD algorithim here, as well, but (1) that algorithim works
- // best when the base is a power of 2 and (2) i don't think it'd make much difference, anyway. as is,
- // the basic extended euclidean algorithim is what we're using.
-
- // if $x is less than 0, the first character of $x is a '-', so we'll remove it. we can do this because
- // $x mod $n == $x mod -$n.
- $n = (bccomp($n->value, '0') < 0) ? substr($n->value, 1) : $n->value;
-
- if (bccomp($this->value,'0') < 0)
- {
- $negated_this = new biginteger();
- $negated_this->value = substr($this->value, 1);
-
- $temp = $negated_this->mod_inverse(new biginteger($n));
-
- if ($temp === false)
- {
- return false;
- }
-
- $temp->value = bcsub($n, $temp->value);
-
- return $temp;
- }
-
- $u = $this->value;
- $v = $n;
-
- $a = '1';
- $c = '0';
-
- while (true)
- {
- $q = bcdiv($u, $v);
- $temp = $u;
- $u = $v;
- $v = bcsub($temp, bcmul($v, $q));
-
- if (bccomp($v, '0') == 0) {
- break;
- }
-
- $temp = $a;
- $a = $c;
- $c = bcsub($temp, bcmul($c, $q));
- }
-
- $temp = new biginteger();
- $temp->value = (bccomp($c, '0') < 0) ? bcadd($c, $n) : $c;
-
- // $u contains the gcd of $this and $n
- return (bccomp($u,'1') == 0) ? $temp : false;
- }
-
- // if $this and $n are even, return false.
- if ( !($this->value[0]&1) && !($n->value[0]&1) )
- {
- return false;
- }
-
- $n = $n->_copy();
- $n->is_negative = false;
-
- if ($this->compare(new biginteger()) < 0)
- {
- // is_negative is currently true. since we need it to be false, we'll just set it to false, temporarily,
- // and reset it as true, later.
- $this->is_negative = false;
-
- $temp = $this->mod_inverse($n);
-
- if ($temp === false)
- {
- return false;
- }
-
- $temp = $n->subtract($temp);
-
- $this->is_negative = true;
-
- return $temp;
- }
-
- $u = $n->_copy();
- $x = $this;
- //list(, $x) = $this->divide($n);
- $v = $x->_copy();
-
- $a = new biginteger();
- $b = new biginteger();
- $c = new biginteger();
- $d = new biginteger();
-
- $a->value = $d->value = array(1);
-
- while ( !empty($u->value) )
- {
- while ( !($u->value[0] & 1) )
- {
- $u->_rshift(1);
- if ( ($a->value[0] & 1) || ($b->value[0] & 1) )
- {
- $a = $a->add($x);
- $b = $b->subtract($n);
- }
- $a->_rshift(1);
- $b->_rshift(1);
- }
-
- while ( !($v->value[0] & 1) )
- {
- $v->_rshift(1);
- if ( ($c->value[0] & 1) || ($d->value[0] & 1) )
- {
- $c = $c->add($x);
- $d = $d->subtract($n);
- }
- $c->_rshift(1);
- $d->_rshift(1);
- }
-
- if ($u->compare($v) >= 0)
- {
- $u = $u->subtract($v);
- $a = $a->subtract($c);
- $b = $b->subtract($d);
- }
- else
- {
- $v = $v->subtract($u);
- $c = $c->subtract($a);
- $d = $d->subtract($b);
- }
-
- $u->_normalize();
- }
-
- // at this point, $v == gcd($this, $n). if it's not equal to 1, no modular inverse exists.
- if ( $v->value != array(1) )
- {
- return false;
- }
-
- $d = ($d->compare(new biginteger()) < 0) ? $d->add($n) : $d;
-
- return ($this->is_negative) ? $n->subtract($d) : $d;
- }
-
- /**
- * Absolute value.
- *
- * @return biginteger
- * @access public
- */
- function abs()
- {
- $temp = new biginteger();
-
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp->value = gmp_abs($this->value);
- break;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $temp->value = (bccomp($this->value, '0') < 0) ? substr($this->value, 1) : $this->value;
- break;
- default:
- $temp->value = $this->value;
- }
-
- return $temp;
- }
-
- /**
- * Compares two numbers.
- *
- * @param biginteger $x
- * @return Integer < 0 if $this is less than $x; > 0 if $this is greater than $x, and 0 if they are equal.
- * @access public
- * @internal Could return $this->sub($x), but that's not as fast as what we do do.
- */
- function compare($x)
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- return gmp_cmp($this->value, $x->value);
- case MATH_BIGINTEGER_MODE_BCMATH:
- return bccomp($this->value, $x->value);
- }
-
- $this->_normalize();
- $x->_normalize();
-
- if ( $this->is_negative != $x->is_negative )
- {
- return ( !$this->is_negative && $x->is_negative ) ? 1 : -1;
- }
-
- $result = $this->is_negative ? -1 : 1;
-
- if ( count($this->value) != count($x->value) )
- {
- return ( count($this->value) > count($x->value) ) ? $result : -$result;
- }
-
- for ($i = count($this->value) - 1; $i >= 0; $i--)
- {
- if ($this->value[$i] != $x->value[$i])
- {
- return ( $this->value[$i] > $x->value[$i] ) ? $result : -$result;
- }
- }
-
- return 0;
- }
-
- /**
- * Returns a copy of $this
- *
- * PHP5 passes objects by reference while PHP4 passes by value. As such, we need a function to guarantee
- * that all objects are passed by value, when appropriate. More information can be found here:
- *
- * {@link http://www.php.net/manual/en/language.oop5.basic.php#51624}
- *
- * @access private
- * @return biginteger
- */
- function _copy()
- {
- $temp = new biginteger();
- $temp->value = $this->value;
- $temp->is_negative = $this->is_negative;
- return $temp;
- }
-
- /**
- * Logical And
- *
- * @param biginteger $x
- * @access public
- * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
- * @return biginteger
- */
- function bitwise_and($x)
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new biginteger();
- $temp->value = gmp_and($this->value, $x->value);
-
- return $temp;
- case MATH_BIGINTEGER_MODE_BCMATH:
- return new biginteger($this->to_bytes() & $x->to_bytes(), 256);
- }
-
- $result = new biginteger();
-
- $x_length = count($x->value);
- for ($i = 0; $i < $x_length; $i++)
- {
- $result->value[] = $this->value[$i] & $x->value[$i];
- }
-
- return $result->_normalize();
- }
-
- /**
- * Logical Or
- *
- * @param biginteger $x
- * @access public
- * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
- * @return biginteger
- */
- function bitwise_or($x)
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new biginteger();
- $temp->value = gmp_or($this->value, $x->value);
-
- return $temp;
- case MATH_BIGINTEGER_MODE_BCMATH:
- return new biginteger($this->to_bytes() | $x->to_bytes(), 256);
- }
-
- $result = $this->_copy();
-
- $x_length = count($x->value);
- for ($i = 0; $i < $x_length; $i++)
- {
- $result->value[$i] = $this->value[$i] | $x->value[$i];
- }
-
- return $result->_normalize();
- }
-
- /**
- * Logical Exclusive-Or
- *
- * @param biginteger $x
- * @access public
- * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
- * @return biginteger
- */
- function bitwise_xor($x)
- {
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- $temp = new biginteger();
- $temp->value = gmp_xor($this->value, $x->value);
-
- return $temp;
- case MATH_BIGINTEGER_MODE_BCMATH:
- return new biginteger($this->to_bytes() ^ $x->to_bytes(), 256);
- }
-
- $result = $this->_copy();
-
- $x_length = count($x->value);
- for ($i = 0; $i < $x_length; $i++)
- {
- $result->value[$i] = $this->value[$i] ^ $x->value[$i];
- }
-
- return $result->_normalize();
- }
-
- /**
- * Logical Not
- *
- * Although integers can be converted to and from various bases with relative ease, there is one piece
- * of information that is lost during such conversions. The number of leading zeros that number had
- * or should have in any given base. Per that, if you convert 1 from decimal to binary, there's no
- * way to know just how many leading zero's there should be. In truth, there could be any number.
- *
- * Normally, the number of leading zero's is unimportant. When doing "not", however, it is. The "not"
- * of 1 on an 8-bit representation of 1 is 1111 1110. The "not" of 1 on a 16-bit representation of 1 is
- * 1111 1111 1111 1110. When doing it on a number that's preceeded by an infinite number of zero's, it's
- * infinite.
- *
- * This function assumes that there are no leading zero's - that the bit-representation being used is
- * equal to the minimum number of required bits, unless otherwise specified in the optional parameter,
- * where the optional parameter represents the bit-representation being used. If the specified
- * bit-representation is smaller than the minimum number of bits required to represent the number, the
- * latter will be used as the bit-representation.
- *
- * @param $bits Integer
- * @access public
- * @internal Implemented per a request by Lluis Pamies i Juarez <lluis _a_ pamies.cat>
- * @return biginteger
- */
- function bitwise_not($bits = -1)
- {
- // calculuate "not" without regard to $bits
- $temp = ~$this->to_bytes();
- $msb = decbin(ord($temp[0]));
- $msb = substr($msb, strpos($msb, '0'));
- $temp[0] = chr(bindec($msb));
-
- // see if we need to add extra leading 1's
- $current_bits = strlen($msb) + 8 * strlen($temp) - 8;
- $new_bits = $bits - $current_bits;
- if ($new_bits <= 0)
- {
- return new biginteger($temp, 256);
- }
-
- // generate as many leading 1's as we need to.
- $leading_ones = chr((1 << ($new_bits & 0x7)) - 1) . str_repeat(chr(0xFF), $new_bits >> 3);
- $this->_base256_lshift($leading_ones, $current_bits);
-
- $temp = str_pad($temp, ceil($bits / 8), chr(0), STR_PAD_LEFT);
-
- return new biginteger($leading_ones | $temp, 256);
- }
-
- /**
- * Logical Right Shift
- *
- * Shifts BigInteger's by $shift bits, effectively dividing by 2**$shift.
- *
- * @param Integer $shift
- * @return biginteger
- * @access public
- * @internal The only version that yields any speed increases is the internal version.
- */
- function bitwise_right_shift($shift)
- {
- $temp = new biginteger();
-
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- static $two;
-
- if (empty($two))
- {
- $two = gmp_init('2');
- }
-
- $temp->value = gmp_div_q($this->value, gmp_pow($two, $shift));
-
- break;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $temp->value = bcdiv($this->value, bcpow('2', $shift));
-
- break;
- default: // could just replace _lshift with this, but then all _lshift() calls would need to be rewritten
- // and I don't want to do that...
- $temp->value = $this->value;
- $temp->_rshift($shift);
- }
-
- return $temp;
- }
-
- /**
- * Logical Left Shift
- *
- * Shifts BigInteger's by $shift bits, effectively multiplying by 2**$shift.
- *
- * @param Integer $shift
- * @return biginteger
- * @access public
- * @internal The only version that yields any speed increases is the internal version.
- */
- function bitwise_left_shift($shift)
- {
- $temp = new biginteger();
-
- switch ( MATH_BIGINTEGER_MODE )
- {
- case MATH_BIGINTEGER_MODE_GMP:
- static $two;
-
- if (empty($two))
- {
- $two = gmp_init('2');
- }
-
- $temp->value = gmp_mul($this->value, gmp_pow($two, $shift));
-
- break;
- case MATH_BIGINTEGER_MODE_BCMATH:
- $temp->value = bcmul($this->value, bcpow('2', $shift));
-
- break;
- default: // could just replace _rshift with this, but then all _lshift() calls would need to be rewritten
- // and I don't want to do that...
- $temp->value = $this->value;
- $temp->_lshift($shift);
- }
-
- return $temp;
- }
-
- /**
- * Generate a random number
- *
- * $generator should be the name of a random number generating function whose first parameter is the minimum
- * value and whose second parameter is the maximum value. If this function needs to be seeded, it should be
- * done before this function is called.
- *
- * @param optional Integer $min
- * @param optional Integer $max
- * @param optional String $generator
- * @return biginteger
- * @access public
- */
- function random($min = false, $max = false, $generator = 'mt_rand')
- {
- if ($min === false)
- {
- $min = new biginteger(0);
- }
-
- if ($max === false)
- {
- $max = new biginteger(0x7FFFFFFF);
- }
-
- $compare = $max->compare($min);
-
- if (!$compare)
- {
- return $min;
- }
- else if ($compare < 0)
- {
- // if $min is bigger then $max, swap $min and $max
- $temp = $max;
- $max = $min;
- $min = $temp;
- }
-
- $max = $max->subtract($min);
- $max = ltrim($max->to_bytes(), chr(0));
- $size = strlen($max) - 1;
- $random = '';
-
- $bytes = $size & 3;
- for ($i = 0; $i < $bytes; $i++)
- {
- $random.= chr($generator(0, 255));
- }
-
- $blocks = $size >> 2;
- for ($i = 0; $i < $blocks; $i++)
- {
- $random.= pack('N', $generator(-2147483648, 0x7FFFFFFF));
- }
-
- $temp = new biginteger($random, 256);
- if ($temp->compare(new biginteger(substr($max, 1), 256)) > 0)
- {
- $random = chr($generator(0, ord($max[0]) - 1)) . $random;
- }
- else
- {
- $random = chr($generator(0, ord($max[0]) )) . $random;
- }
-
- $random = new biginteger($random, 256);
-
- return $random->add($min);
- }
-
- /**
- * Logical Left Shift
- *
- * Shifts BigInteger's by $shift bits.
- *
- * @param Integer $shift
- * @access private
- */
- function _lshift($shift)
- {
- if ( $shift == 0 )
- {
- return;
- }
-
- $num_digits = floor($shift / 26);
- $shift %= 26;
- $shift = 1 << $shift;
-
- $carry = 0;
-
- for ($i = 0; $i < count($this->value); $i++)
- {
- $temp = $this->value[$i] * $shift + $carry;
- $carry = floor($temp / 0x4000000);
- $this->value[$i] = $temp - $carry * 0x4000000;
- }
-
- if ( $carry )
- {
- $this->value[] = $carry;
- }
-
- while ($num_digits--)
- {
- array_unshift($this->value, 0);
- }
- }
-
- /**
- * Logical Right Shift
- *
- * Shifts BigInteger's by $shift bits.
- *
- * @param Integer $shift
- * @access private
- */
- function _rshift($shift)
- {
- if ($shift == 0)
- {
- $this->_normalize();
- }
-
- $num_digits = floor($shift / 26);
- $shift %= 26;
- $carry_shift = 26 - $shift;
- $carry_mask = (1 << $shift) - 1;
-
- if ( $num_digits )
- {
- $this->value = array_slice($this->value, $num_digits);
- }
-
- $carry = 0;
-
- for ($i = count($this->value) - 1; $i >= 0; $i--)
- {
- $temp = $this->value[$i] >> $shift | $carry;
- $carry = ($this->value[$i] & $carry_mask) << $carry_shift;
- $this->value[$i] = $temp;
- }
-
- $this->_normalize();
- }
-
- /**
- * Normalize
- *
- * Deletes leading zeros.
- *
- * @see divide()
- * @return Math_BigInteger
- * @access private
- */
- function _normalize()
- {
- if ( !count($this->value) )
- {
- return $this;
- }
-
- for ($i=count($this->value) - 1; $i >= 0; $i--)
- {
- if ( $this->value[$i] )
- {
- break;
- }
- unset($this->value[$i]);
- }
-
- return $this;
- }
-
- /**
- * Array Repeat
- *
- * @param $input Array
- * @param $multiplier mixed
- * @return Array
- * @access private
- */
- function _array_repeat($input, $multiplier)
- {
- return ($multiplier) ? array_fill(0, $multiplier, $input) : array();
- }
-
- /**
- * Logical Left Shift
- *
- * Shifts binary strings $shift bits, essentially multiplying by 2**$shift.
- *
- * @param $x String
- * @param $shift Integer
- * @return String
- * @access private
- */
- function _base256_lshift(&$x, $shift)
- {
- if ($shift == 0)
- {
- return;
- }
-
- $num_bytes = $shift >> 3; // eg. floor($shift/8)
- $shift &= 7; // eg. $shift % 8
-
- $carry = 0;
- for ($i = strlen($x) - 1; $i >= 0; $i--)
- {
- $temp = ord($x[$i]) << $shift | $carry;
- $x[$i] = chr($temp);
- $carry = $temp >> 8;
- }
- $carry = ($carry != 0) ? chr($carry) : '';
- $x = $carry . $x . str_repeat(chr(0), $num_bytes);
- }
-
- /**
- * Logical Right Shift
- *
- * Shifts binary strings $shift bits, essentially dividing by 2**$shift and returning the remainder.
- *
- * @param $x String
- * @param $shift Integer
- * @return String
- * @access private
- */
- function _base256_rshift(&$x, $shift)
- {
- if ($shift == 0)
- {
- $x = ltrim($x, chr(0));
- return '';
- }
-
- $num_bytes = $shift >> 3; // eg. floor($shift/8)
- $shift &= 7; // eg. $shift % 8
-
- $remainder = '';
- if ($num_bytes)
- {
- $start = $num_bytes > strlen($x) ? -strlen($x) : -$num_bytes;
- $remainder = substr($x, $start);
- $x = substr($x, 0, -$num_bytes);
- }
-
- $carry = 0;
- $carry_shift = 8 - $shift;
- for ($i = 0; $i < strlen($x); $i++)
- {
- $temp = (ord($x[$i]) >> $shift) | $carry;
- $carry = (ord($x[$i]) << $carry_shift) & 0xFF;
- $x[$i] = chr($temp);
- }
- $x = ltrim($x, chr(0));
-
- $remainder = chr($carry >> $carry_shift) . $remainder;
-
- return ltrim($remainder, chr(0));
- }
-
- // one quirk about how the following functions are implemented is that PHP defines N to be an unsigned long
- // at 32-bits, while java's longs are 64-bits.
-
- /**
- * Converts 32-bit integers to bytes.
- *
- * @param Integer $x
- * @return String
- * @access private
- */
- function _int2bytes($x)
- {
- return ltrim(pack('N', $x), chr(0));
- }
-
- /**
- * Converts bytes to 32-bit integers
- *
- * @param String $x
- * @return Integer
- * @access private
- */
- function _bytes2int($x)
- {
- $temp = unpack('Nint', str_pad($x, 4, chr(0), STR_PAD_LEFT));
- return $temp['int'];
- }
-}
-
-?>
\ No newline at end of file diff --git a/phpBB/includes/libraries/sftp/des.php b/phpBB/includes/libraries/sftp/des.php deleted file mode 100644 index 278de64a01..0000000000 --- a/phpBB/includes/libraries/sftp/des.php +++ /dev/null @@ -1,1428 +0,0 @@ -<?php
-/**
-*
-* @package sftp
-* @version $Id$
-* @copyright (c) 2006 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Code from http://phpseclib.sourceforge.net/
-*
-* Modified by phpBB Group to meet our coding standards
-* and being able to integrate into phpBB
-*
-* Pure-PHP implementation of DES.
-*
-* Copyright 2007-2009 TerraFrost <terrafrost@php.net>
-* Copyright 2009+ phpBB
-*
-* @package sftp
-* @author TerraFrost <terrafrost@php.net>
-*/
-
-/**#@+
- * @access private
- * @see des::_prepare_key()
- * @see des::_process_block()
- */
-/**
- * Contains array_reverse($keys[CRYPT_DES_DECRYPT])
- */
-define('CRYPT_DES_ENCRYPT', 0);
-/**
- * Contains array_reverse($keys[CRYPT_DES_ENCRYPT])
- */
-define('CRYPT_DES_DECRYPT', 1);
-/**#@-*/
-
-/**#@+
- * @access public
- * @see des::encrypt()
- * @see des::decrypt()
- */
-/**
- * Encrypt / decrypt using the Electronic Code Book mode.
- *
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Electronic_codebook_.28ECB.29
- */
-define('CRYPT_DES_MODE_ECB', 1);
-/**
- * Encrypt / decrypt using the Code Book Chaining mode.
- *
- * @link http://en.wikipedia.org/wiki/Block_cipher_modes_of_operation#Cipher-block_chaining_.28CBC.29
- */
-define('CRYPT_DES_MODE_CBC', 2);
-/**#@-*/
-
-/**
- * Encrypt / decrypt using inner chaining
- *
- * Inner chaining is used by SSH-1 and is generally considered to be less secure then outer chaining (CRYPT_DES_MODE_CBC3).
- */
-define('CRYPT_DES_MODE_3CBC', 3);
-
-/**
- * Encrypt / decrypt using outer chaining
- *
- * Outer chaining is used by SSH-2 and when the mode is set to CRYPT_DES_MODE_CBC.
- */
-define('CRYPT_DES_MODE_CBC3', CRYPT_DES_MODE_CBC);
-
-/**#@+
- * @access private
- * @see des::__construct()
- */
-/**
- * Toggles the internal implementation
- */
-define('CRYPT_DES_MODE_INTERNAL', 1);
-/**
- * Toggles the mcrypt implementation
- */
-define('CRYPT_DES_MODE_MCRYPT', 2);
-/**#@-*/
-
-/**
- * Pure-PHP implementation of DES.
- *
- * @author Jim Wigginton <terrafrost@php.net>
- * @version 0.1.0
- * @access public
- * @package des
- */
-class des
-{
- /**
- * The Key Schedule
- *
- * @see des::setKey()
- * @var Array
- * @access private
- */
- var $keys = "\0\0\0\0\0\0\0\0";
-
- /**
- * The Encryption Mode
- *
- * @see des::des()
- * @var Integer
- * @access private
- */
- var $mode;
-
- /**
- * Continuous Buffer status
- *
- * @see des::enableContinuousBuffer()
- * @var Boolean
- * @access private
- */
- var $continuousBuffer = false;
-
- /**
- * Padding status
- *
- * @see des::enablePadding()
- * @var Boolean
- * @access private
- */
- var $padding = true;
-
- /**
- * The Initialization Vector
- *
- * @see des::setIV()
- * @var String
- * @access private
- */
- var $iv = "\0\0\0\0\0\0\0\0";
-
- /**
- * A "sliding" Initialization Vector
- *
- * @see des::enableContinuousBuffer()
- * @var String
- * @access private
- */
- var $encryptIV = "\0\0\0\0\0\0\0\0";
-
- /**
- * A "sliding" Initialization Vector
- *
- * @see des::enableContinuousBuffer()
- * @var String
- * @access private
- */
- var $decryptIV = "\0\0\0\0\0\0\0\0";
-
- /**
- * MCrypt parameters
- *
- * @see des::setMCrypt()
- * @var Array
- * @access private
- */
- var $mcrypt = array('', '');
-
- /**
- * Default Constructor.
- *
- * Determines whether or not the mcrypt extension should be used. $mode should only, at present, be
- * CRYPT_DES_MODE_ECB or CRYPT_DES_MODE_CBC. If not explictly set, CRYPT_DES_MODE_CBC will be used.
- *
- * @param optional Integer $mode
- * @return des
- * @access public
- */
- function __construct($mode = CRYPT_MODE_DES_CBC)
- {
- if ( !defined('CRYPT_DES_MODE') )
- {
- switch (true)
- {
- case extension_loaded('mcrypt'):
- // i'd check to see if des was supported, by doing in_array('des', mcrypt_list_algorithms('')),
- // but since that can be changed after the object has been created, there doesn't seem to be
- // a lot of point...
- define('CRYPT_DES_MODE', CRYPT_DES_MODE_MCRYPT);
- break;
- default:
- define('CRYPT_DES_MODE', CRYPT_DES_MODE_INTERNAL);
- }
- }
-
- switch ( CRYPT_DES_MODE )
- {
- case CRYPT_DES_MODE_MCRYPT:
- switch ($mode)
- {
- case CRYPT_DES_MODE_ECB:
- $this->mode = MCRYPT_MODE_ECB;
- break;
- case CRYPT_DES_MODE_CBC:
- default:
- $this->mode = MCRYPT_MODE_CBC;
- }
-
- break;
- default:
- switch ($mode)
- {
- case CRYPT_DES_MODE_ECB:
- case CRYPT_DES_MODE_CBC:
- $this->mode = $mode;
- break;
- default:
- $this->mode = CRYPT_DES_MODE_CBC;
- }
- }
- }
-
- /**
- * Sets the key.
- *
- * Keys can be of any length. DES, itself, uses 64-bit keys (eg. strlen($key) == 8), however, we
- * only use the first eight, if $key has more then eight characters in it, and pad $key with the
- * null byte if it is less then eight characters long.
- *
- * DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
- *
- * If the key is not explicitly set, it'll be assumed to be all zero's.
- *
- * @access public
- * @param String $key
- */
- function set_key($key)
- {
- $this->keys = ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT ) ? substr($key, 0, 8) : $this->_prepare_key($key);
- }
-
- /**
- * Sets the initialization vector. (optional)
- *
- * SetIV is not required when CRYPT_DES_MODE_ECB is being used. If not explictly set, it'll be assumed
- * to be all zero's.
- *
- * @access public
- * @param String $iv
- */
- function set_iv($iv)
- {
- $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, 8), 8, chr(0));;
- }
-
- /**
- * Sets MCrypt parameters. (optional)
- *
- * If MCrypt is being used, empty strings will be used, unless otherwise specified.
- *
- * @link http://php.net/function.mcrypt-module-open#function.mcrypt-module-open
- * @access public
- * @param optional Integer $algorithm_directory
- * @param optional Integer $mode_directory
- */
- function set_mcrypt($algorithm_directory = '', $mode_directory = '')
- {
- $this->mcrypt = array($algorithm_directory, $mode_directory);
- }
-
- /**
- * Encrypts a message.
- *
- * $plaintext will be padded with up to 8 additional bytes. Other DES implementations may or may not pad in the
- * same manner. Other common approaches to padding and the reasons why it's necessary are discussed in the following
- * URL:
- *
- * {@link http://www.di-mgt.com.au/cryptopad.html http://www.di-mgt.com.au/cryptopad.html}
- *
- * An alternative to padding is to, separately, send the length of the file. This is what SSH, in fact, does.
- * strlen($plaintext) will still need to be a multiple of 8, however, arbitrary values can be added to make it that
- * length.
- *
- * @see des::decrypt()
- * @access public
- * @param String $plaintext
- */
- function encrypt($plaintext)
- {
- $plaintext = $this->_pad($plaintext);
-
- if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT )
- {
- $td = mcrypt_module_open(MCRYPT_DES, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);
- mcrypt_generic_init($td, $this->keys, $this->encryptIV);
-
- $ciphertext = mcrypt_generic($td, $plaintext);
-
- mcrypt_generic_deinit($td);
- mcrypt_module_close($td);
-
- if ($this->continuousBuffer)
- {
- $this->encryptIV = substr($ciphertext, -8);
- }
-
- return $ciphertext;
- }
-
- if (!is_array($this->keys))
- {
- $this->keys = $this->_prepare_key("\0\0\0\0\0\0\0\0");
- }
-
- $ciphertext = '';
- switch ($this->mode)
- {
- case CRYPT_DES_MODE_ECB:
- for ($i = 0; $i < strlen($plaintext); $i+=8)
- {
- $ciphertext.= $this->_process_block(substr($plaintext, $i, 8), CRYPT_DES_ENCRYPT);
- }
- break;
- case CRYPT_DES_MODE_CBC:
- $xor = $this->encryptIV;
- for ($i = 0; $i < strlen($plaintext); $i+=8)
- {
- $block = substr($plaintext, $i, 8);
- $block = $this->_process_block($block ^ $xor, CRYPT_DES_ENCRYPT);
- $xor = $block;
- $ciphertext.= $block;
- }
- if ($this->continuousBuffer)
- {
- $this->encryptIV = $xor;
- }
- }
-
- return $ciphertext;
- }
-
- /**
- * Decrypts a message.
- *
- * If strlen($ciphertext) is not a multiple of 8, null bytes will be added to the end of the string until it is.
- *
- * @see des::encrypt()
- * @access public
- * @param String $ciphertext
- */
- function decrypt($ciphertext)
- {
- // we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
- // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
- $ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, chr(0));
-
- if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT )
- {
- $td = mcrypt_module_open(MCRYPT_DES, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);
- mcrypt_generic_init($td, $this->keys, $this->decryptIV);
-
- $plaintext = mdecrypt_generic($td, $ciphertext);
-
- mcrypt_generic_deinit($td);
- mcrypt_module_close($td);
-
- if ($this->continuousBuffer)
- {
- $this->decryptIV = substr($ciphertext, -8);
- }
-
- return $this->_unpad($plaintext);
- }
-
- if (!is_array($this->keys))
- {
- $this->keys = $this->_prepare_key("\0\0\0\0\0\0\0\0");
- }
-
- $plaintext = '';
- switch ($this->mode)
- {
- case CRYPT_DES_MODE_ECB:
- for ($i = 0; $i < strlen($ciphertext); $i+=8)
- {
- $plaintext.= $this->_process_block(substr($ciphertext, $i, 8), CRYPT_DES_DECRYPT);
- }
- break;
- case CRYPT_DES_MODE_CBC:
- $xor = $this->decryptIV;
- for ($i = 0; $i < strlen($ciphertext); $i+=8)
- {
- $block = substr($ciphertext, $i, 8);
- $plaintext.= $this->_process_block($block, CRYPT_DES_DECRYPT) ^ $xor;
- $xor = $block;
- }
- if ($this->continuousBuffer)
- {
- $this->decryptIV = $xor;
- }
- }
-
- return $this->_unpad($plaintext);
- }
-
- /**
- * Treat consecutive "packets" as if they are a continuous buffer.
- *
- * Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
- * will yield different outputs:
- *
- * <code>
- * echo $des->encrypt(substr($plaintext, 0, 8));
- * echo $des->encrypt(substr($plaintext, 8, 8));
- * </code>
- * <code>
- * echo $des->encrypt($plaintext);
- * </code>
- *
- * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
- * another, as demonstrated with the following:
- *
- * <code>
- * $des->encrypt(substr($plaintext, 0, 8));
- * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
- * </code>
- * <code>
- * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
- * </code>
- *
- * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
- * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
- * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
- *
- * Put another way, when the continuous buffer is enabled, the state of the des() object changes after each
- * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
- * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
- * however, they are also less intuitive and more likely to cause you problems.
- *
- * @see des::disableContinuousBuffer()
- * @access public
- */
- function enable_continuous_buffer()
- {
- $this->continuousBuffer = true;
- }
-
- /**
- * Treat consecutive packets as if they are a discontinuous buffer.
- *
- * The default behavior.
- *
- * @see des::enableContinuousBuffer()
- * @access public
- */
- function disable_continuous_buffer()
- {
- $this->continuousBuffer = false;
- $this->encryptIV = $this->iv;
- $this->decryptIV = $this->iv;
- }
-
- /**
- * Pad "packets".
- *
- * DES works by encrypting eight bytes at a time. If you ever need to encrypt or decrypt something that's not
- * a multiple of eight, it becomes necessary to pad the input so that it's length is a multiple of eight.
- *
- * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH1,
- * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
- * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
- * transmitted separately)
- *
- * @see des::disablePadding()
- * @access public
- */
- function enable_padding()
- {
- $this->padding = true;
- }
-
- /**
- * Do not pad packets.
- *
- * @see des::enablePadding()
- * @access public
- */
- function disable_padding()
- {
- $this->padding = false;
- }
-
- /**
- * Pads a string
- *
- * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize (8).
- * 8 - (strlen($text) & 7) bytes are added, each of which is equal to chr(8 - (strlen($text) & 7)
- *
- * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
- * and padding will, hence forth, be enabled.
- *
- * @see des::_unpad()
- * @access private
- */
- function _pad($text)
- {
- $length = strlen($text);
-
- if (!$this->padding)
- {
- if (($length & 7) == 0)
- {
- return $text;
- }
- else
- {
- $this->padding = true;
- }
- }
-
- $pad = 8 - ($length & 7);
- return str_pad($text, $length + $pad, chr($pad));
- }
-
- /**
- * Unpads a string
- *
- * If padding is enabled and the reported padding length exceeds the block size, padding will be, hence forth, disabled.
- *
- * @see des::_pad()
- * @access private
- */
- function _unpad($text)
- {
- if (!$this->padding)
- {
- return $text;
- }
-
- $length = ord($text[strlen($text) - 1]);
-
- if ($length > 8)
- {
- $this->padding = false;
- return $text;
- }
-
- return substr($text, 0, -$length);
- }
-
- /**
- * Encrypts or decrypts a 64-bit block
- *
- * $mode should be either CRYPT_DES_ENCRYPT or CRYPT_DES_DECRYPT. See
- * {@link http://en.wikipedia.org/wiki/Image:Feistel.png Feistel.png} to get a general
- * idea of what this function does.
- *
- * @access private
- * @param String $block
- * @param Integer $mode
- * @return String
- */
- function _process_block($block, $mode)
- {
- // s-boxes. in the official DES docs, they're described as being matrices that
- // one accesses by using the first and last bits to determine the row and the
- // middle four bits to determine the column. in this implementation, they've
- // been converted to vectors
- static $sbox = array(
- array(
- 14, 0, 4, 15, 13, 7, 1, 4, 2, 14, 15, 2, 11, 13, 8, 1,
- 3, 10 ,10, 6, 6, 12, 12, 11, 5, 9, 9, 5, 0, 3, 7, 8,
- 4, 15, 1, 12, 14, 8, 8, 2, 13, 4, 6, 9, 2, 1, 11, 7,
- 15, 5, 12, 11, 9, 3, 7, 14, 3, 10, 10, 0, 5, 6, 0, 13
- ),
- array(
- 15, 3, 1, 13, 8, 4, 14, 7, 6, 15, 11, 2, 3, 8, 4, 14,
- 9, 12, 7, 0, 2, 1, 13, 10, 12, 6, 0, 9, 5, 11, 10, 5,
- 0, 13, 14, 8, 7, 10, 11, 1, 10, 3, 4, 15, 13, 4, 1, 2,
- 5, 11, 8, 6, 12, 7, 6, 12, 9, 0, 3, 5, 2, 14, 15, 9
- ),
- array(
- 10, 13, 0, 7, 9, 0, 14, 9, 6, 3, 3, 4, 15, 6, 5, 10,
- 1, 2, 13, 8, 12, 5, 7, 14, 11, 12, 4, 11, 2, 15, 8, 1,
- 13, 1, 6, 10, 4, 13, 9, 0, 8, 6, 15, 9, 3, 8, 0, 7,
- 11, 4, 1, 15, 2, 14, 12, 3, 5, 11, 10, 5, 14, 2, 7, 12
- ),
- array(
- 7, 13, 13, 8, 14, 11, 3, 5, 0, 6, 6, 15, 9, 0, 10, 3,
- 1, 4, 2, 7, 8, 2, 5, 12, 11, 1, 12, 10, 4, 14, 15, 9,
- 10, 3, 6, 15, 9, 0, 0, 6, 12, 10, 11, 1, 7, 13, 13, 8,
- 15, 9, 1, 4, 3, 5, 14, 11, 5, 12, 2, 7, 8, 2, 4, 14
- ),
- array(
- 2, 14, 12, 11, 4, 2, 1, 12, 7, 4, 10, 7, 11, 13, 6, 1,
- 8, 5, 5, 0, 3, 15, 15, 10, 13, 3, 0, 9, 14, 8, 9, 6,
- 4, 11, 2, 8, 1, 12, 11, 7, 10, 1, 13, 14, 7, 2, 8, 13,
- 15, 6, 9, 15, 12, 0, 5, 9, 6, 10, 3, 4, 0, 5, 14, 3
- ),
- array(
- 12, 10, 1, 15, 10, 4, 15, 2, 9, 7, 2, 12, 6, 9, 8, 5,
- 0, 6, 13, 1, 3, 13, 4, 14, 14, 0, 7, 11, 5, 3, 11, 8,
- 9, 4, 14, 3, 15, 2, 5, 12, 2, 9, 8, 5, 12, 15, 3, 10,
- 7, 11, 0, 14, 4, 1, 10, 7, 1, 6, 13, 0, 11, 8, 6, 13
- ),
- array(
- 4, 13, 11, 0, 2, 11, 14, 7, 15, 4, 0, 9, 8, 1, 13, 10,
- 3, 14, 12, 3, 9, 5, 7, 12, 5, 2, 10, 15, 6, 8, 1, 6,
- 1, 6, 4, 11, 11, 13, 13, 8, 12, 1, 3, 4, 7, 10, 14, 7,
- 10, 9, 15, 5, 6, 0, 8, 15, 0, 14, 5, 2, 9, 3, 2, 12
- ),
- array(
- 13, 1, 2, 15, 8, 13, 4, 8, 6, 10, 15, 3, 11, 7, 1, 4,
- 10, 12, 9, 5, 3, 6, 14, 11, 5, 0, 0, 14, 12, 9, 7, 2,
- 7, 2, 11, 1, 4, 14, 1, 7, 9, 4, 12, 10, 14, 8, 2, 13,
- 0, 15, 6, 12, 10, 9, 13, 0, 15, 3, 3, 5, 5, 6, 8, 11
- )
- );
-
- $temp = unpack('Na/Nb', $block);
- $block = array($temp['a'], $temp['b']);
-
- // because php does arithmetic right shifts, if the most significant bits are set, right
- // shifting those into the correct position will add 1's - not 0's. this will intefere
- // with the | operation unless a second & is done. so we isolate these bits and left shift
- // them into place. we then & each block with 0x7FFFFFFF to prevennt 1's from being added
- // for any other shifts.
- $msb = array(
- ($block[0] >> 31) & 1,
- ($block[1] >> 31) & 1
- );
- $block[0] &= 0x7FFFFFFF;
- $block[1] &= 0x7FFFFFFF;
-
- // we isolate the appropriate bit in the appropriate integer and shift as appropriate. in
- // some cases, there are going to be multiple bits in the same integer that need to be shifted
- // in the same way. we combine those into one shift operation.
- $block = array(
- (($block[1] & 0x00000040) << 25) | (($block[1] & 0x00004000) << 16) |
- (($block[1] & 0x00400001) << 7) | (($block[1] & 0x40000100) >> 2) |
- (($block[0] & 0x00000040) << 21) | (($block[0] & 0x00004000) << 12) |
- (($block[0] & 0x00400001) << 3) | (($block[0] & 0x40000100) >> 6) |
- (($block[1] & 0x00000010) << 19) | (($block[1] & 0x00001000) << 10) |
- (($block[1] & 0x00100000) << 1) | (($block[1] & 0x10000000) >> 8) |
- (($block[0] & 0x00000010) << 15) | (($block[0] & 0x00001000) << 6) |
- (($block[0] & 0x00100000) >> 3) | (($block[0] & 0x10000000) >> 12) |
- (($block[1] & 0x00000004) << 13) | (($block[1] & 0x00000400) << 4) |
- (($block[1] & 0x00040000) >> 5) | (($block[1] & 0x04000000) >> 14) |
- (($block[0] & 0x00000004) << 9) | ( $block[0] & 0x00000400 ) |
- (($block[0] & 0x00040000) >> 9) | (($block[0] & 0x04000000) >> 18) |
- (($block[1] & 0x00010000) >> 11) | (($block[1] & 0x01000000) >> 20) |
- (($block[0] & 0x00010000) >> 15) | (($block[0] & 0x01000000) >> 24)
- ,
- (($block[1] & 0x00000080) << 24) | (($block[1] & 0x00008000) << 15) |
- (($block[1] & 0x00800002) << 6) | (($block[0] & 0x00000080) << 20) |
- (($block[0] & 0x00008000) << 11) | (($block[0] & 0x00800002) << 2) |
- (($block[1] & 0x00000020) << 18) | (($block[1] & 0x00002000) << 9) |
- ( $block[1] & 0x00200000 ) | (($block[1] & 0x20000000) >> 9) |
- (($block[0] & 0x00000020) << 14) | (($block[0] & 0x00002000) << 5) |
- (($block[0] & 0x00200000) >> 4) | (($block[0] & 0x20000000) >> 13) |
- (($block[1] & 0x00000008) << 12) | (($block[1] & 0x00000800) << 3) |
- (($block[1] & 0x00080000) >> 6) | (($block[1] & 0x08000000) >> 15) |
- (($block[0] & 0x00000008) << 8) | (($block[0] & 0x00000800) >> 1) |
- (($block[0] & 0x00080000) >> 10) | (($block[0] & 0x08000000) >> 19) |
- (($block[1] & 0x00000200) >> 3) | (($block[0] & 0x00000200) >> 7) |
- (($block[1] & 0x00020000) >> 12) | (($block[1] & 0x02000000) >> 21) |
- (($block[0] & 0x00020000) >> 16) | (($block[0] & 0x02000000) >> 25) |
- ($msb[1] << 28) | ($msb[0] << 24)
- );
-
- for ($i = 0; $i < 16; $i++)
- {
- // start of "the Feistel (F) function" - see the following URL:
- // http://en.wikipedia.org/wiki/Image:Data_Encryption_Standard_InfoBox_Diagram.png
- $temp = (($sbox[0][((($block[1] >> 27) & 0x1F) | (($block[1] & 1) << 5)) ^ $this->keys[$mode][$i][0]]) << 28)
- | (($sbox[1][(($block[1] & 0x1F800000) >> 23) ^ $this->keys[$mode][$i][1]]) << 24)
- | (($sbox[2][(($block[1] & 0x01F80000) >> 19) ^ $this->keys[$mode][$i][2]]) << 20)
- | (($sbox[3][(($block[1] & 0x001F8000) >> 15) ^ $this->keys[$mode][$i][3]]) << 16)
- | (($sbox[4][(($block[1] & 0x0001F800) >> 11) ^ $this->keys[$mode][$i][4]]) << 12)
- | (($sbox[5][(($block[1] & 0x00001F80) >> 7) ^ $this->keys[$mode][$i][5]]) << 8)
- | (($sbox[6][(($block[1] & 0x000001F8) >> 3) ^ $this->keys[$mode][$i][6]]) << 4)
- | ( $sbox[7][((($block[1] & 0x1F) << 1) | (($block[1] >> 31) & 1)) ^ $this->keys[$mode][$i][7]]);
-
- $msb = ($temp >> 31) & 1;
- $temp &= 0x7FFFFFFF;
- $newBlock = (($temp & 0x00010000) << 15) | (($temp & 0x02020120) << 5)
- | (($temp & 0x00001800) << 17) | (($temp & 0x01000000) >> 10)
- | (($temp & 0x00000008) << 24) | (($temp & 0x00100000) << 6)
- | (($temp & 0x00000010) << 21) | (($temp & 0x00008000) << 9)
- | (($temp & 0x00000200) << 12) | (($temp & 0x10000000) >> 27)
- | (($temp & 0x00000040) << 14) | (($temp & 0x08000000) >> 8)
- | (($temp & 0x00004000) << 4) | (($temp & 0x00000002) << 16)
- | (($temp & 0x00442000) >> 6) | (($temp & 0x40800000) >> 15)
- | (($temp & 0x00000001) << 11) | (($temp & 0x20000000) >> 20)
- | (($temp & 0x00080000) >> 13) | (($temp & 0x00000004) << 3)
- | (($temp & 0x04000000) >> 22) | (($temp & 0x00000480) >> 7)
- | (($temp & 0x00200000) >> 19) | ($msb << 23);
- // end of "the Feistel (F) function" - $newBlock is F's output
-
- $temp = $block[1];
- $block[1] = $block[0] ^ $newBlock;
- $block[0] = $temp;
- }
-
- $msb = array(
- ($block[0] >> 31) & 1,
- ($block[1] >> 31) & 1
- );
- $block[0] &= 0x7FFFFFFF;
- $block[1] &= 0x7FFFFFFF;
-
- $block = array(
- (($block[0] & 0x01000004) << 7) | (($block[1] & 0x01000004) << 6) |
- (($block[0] & 0x00010000) << 13) | (($block[1] & 0x00010000) << 12) |
- (($block[0] & 0x00000100) << 19) | (($block[1] & 0x00000100) << 18) |
- (($block[0] & 0x00000001) << 25) | (($block[1] & 0x00000001) << 24) |
- (($block[0] & 0x02000008) >> 2) | (($block[1] & 0x02000008) >> 3) |
- (($block[0] & 0x00020000) << 4) | (($block[1] & 0x00020000) << 3) |
- (($block[0] & 0x00000200) << 10) | (($block[1] & 0x00000200) << 9) |
- (($block[0] & 0x00000002) << 16) | (($block[1] & 0x00000002) << 15) |
- (($block[0] & 0x04000000) >> 11) | (($block[1] & 0x04000000) >> 12) |
- (($block[0] & 0x00040000) >> 5) | (($block[1] & 0x00040000) >> 6) |
- (($block[0] & 0x00000400) << 1) | ( $block[1] & 0x00000400 ) |
- (($block[0] & 0x08000000) >> 20) | (($block[1] & 0x08000000) >> 21) |
- (($block[0] & 0x00080000) >> 14) | (($block[1] & 0x00080000) >> 15) |
- (($block[0] & 0x00000800) >> 8) | (($block[1] & 0x00000800) >> 9)
- ,
- (($block[0] & 0x10000040) << 3) | (($block[1] & 0x10000040) << 2) |
- (($block[0] & 0x00100000) << 9) | (($block[1] & 0x00100000) << 8) |
- (($block[0] & 0x00001000) << 15) | (($block[1] & 0x00001000) << 14) |
- (($block[0] & 0x00000010) << 21) | (($block[1] & 0x00000010) << 20) |
- (($block[0] & 0x20000080) >> 6) | (($block[1] & 0x20000080) >> 7) |
- ( $block[0] & 0x00200000 ) | (($block[1] & 0x00200000) >> 1) |
- (($block[0] & 0x00002000) << 6) | (($block[1] & 0x00002000) << 5) |
- (($block[0] & 0x00000020) << 12) | (($block[1] & 0x00000020) << 11) |
- (($block[0] & 0x40000000) >> 15) | (($block[1] & 0x40000000) >> 16) |
- (($block[0] & 0x00400000) >> 9) | (($block[1] & 0x00400000) >> 10) |
- (($block[0] & 0x00004000) >> 3) | (($block[1] & 0x00004000) >> 4) |
- (($block[0] & 0x00800000) >> 18) | (($block[1] & 0x00800000) >> 19) |
- (($block[0] & 0x00008000) >> 12) | (($block[1] & 0x00008000) >> 13) |
- ($msb[0] << 7) | ($msb[1] << 6)
- );
-
- return pack('NN', $block[0], $block[1]);
- }
-
- /**
- * Creates the key schedule.
- *
- * @access private
- * @param String $key
- * @return Array
- */
- function _prepare_key($key)
- {
- static $shifts = array( // number of key bits shifted per round
- 1, 1, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 1
- );
-
- // pad the key and remove extra characters as appropriate.
- $key = str_pad(substr($key, 0, 8), 8, chr(0));
-
- $temp = unpack('Na/Nb', $key);
- $key = array($temp['a'], $temp['b']);
- $msb = array(
- ($key[0] >> 31) & 1,
- ($key[1] >> 31) & 1
- );
- $key[0] &= 0x7FFFFFFF;
- $key[1] &= 0x7FFFFFFF;
-
- $key = array(
- (($key[1] & 0x00000002) << 26) | (($key[1] & 0x00000204) << 17) |
- (($key[1] & 0x00020408) << 8) | (($key[1] & 0x02040800) >> 1) |
- (($key[0] & 0x00000002) << 22) | (($key[0] & 0x00000204) << 13) |
- (($key[0] & 0x00020408) << 4) | (($key[0] & 0x02040800) >> 5) |
- (($key[1] & 0x04080000) >> 10) | (($key[0] & 0x04080000) >> 14) |
- (($key[1] & 0x08000000) >> 19) | (($key[0] & 0x08000000) >> 23) |
- (($key[0] & 0x00000010) >> 1) | (($key[0] & 0x00001000) >> 10) |
- (($key[0] & 0x00100000) >> 19) | (($key[0] & 0x10000000) >> 28)
- ,
- (($key[1] & 0x00000080) << 20) | (($key[1] & 0x00008000) << 11) |
- (($key[1] & 0x00800000) << 2) | (($key[0] & 0x00000080) << 16) |
- (($key[0] & 0x00008000) << 7) | (($key[0] & 0x00800000) >> 2) |
- (($key[1] & 0x00000040) << 13) | (($key[1] & 0x00004000) << 4) |
- (($key[1] & 0x00400000) >> 5) | (($key[1] & 0x40000000) >> 14) |
- (($key[0] & 0x00000040) << 9) | ( $key[0] & 0x00004000 ) |
- (($key[0] & 0x00400000) >> 9) | (($key[0] & 0x40000000) >> 18) |
- (($key[1] & 0x00000020) << 6) | (($key[1] & 0x00002000) >> 3) |
- (($key[1] & 0x00200000) >> 12) | (($key[1] & 0x20000000) >> 21) |
- (($key[0] & 0x00000020) << 2) | (($key[0] & 0x00002000) >> 7) |
- (($key[0] & 0x00200000) >> 16) | (($key[0] & 0x20000000) >> 25) |
- (($key[1] & 0x00000010) >> 1) | (($key[1] & 0x00001000) >> 10) |
- (($key[1] & 0x00100000) >> 19) | (($key[1] & 0x10000000) >> 28) |
- ($msb[1] << 24) | ($msb[0] << 20)
- );
-
- $keys = array();
- for ($i = 0; $i < 16; $i++)
- {
- $key[0] <<= $shifts[$i];
- $temp = ($key[0] & 0xF0000000) >> 28;
- $key[0] = ($key[0] | $temp) & 0x0FFFFFFF;
-
- $key[1] <<= $shifts[$i];
- $temp = ($key[1] & 0xF0000000) >> 28;
- $key[1] = ($key[1] | $temp) & 0x0FFFFFFF;
-
- $temp = array(
- (($key[1] & 0x00004000) >> 9) | (($key[1] & 0x00000800) >> 7) |
- (($key[1] & 0x00020000) >> 14) | (($key[1] & 0x00000010) >> 2) |
- (($key[1] & 0x08000000) >> 26) | (($key[1] & 0x00800000) >> 23)
- ,
- (($key[1] & 0x02400000) >> 20) | (($key[1] & 0x00000001) << 4) |
- (($key[1] & 0x00002000) >> 10) | (($key[1] & 0x00040000) >> 18) |
- (($key[1] & 0x00000080) >> 6)
- ,
- ( $key[1] & 0x00000020 ) | (($key[1] & 0x00000200) >> 5) |
- (($key[1] & 0x00010000) >> 13) | (($key[1] & 0x01000000) >> 22) |
- (($key[1] & 0x00000004) >> 1) | (($key[1] & 0x00100000) >> 20)
- ,
- (($key[1] & 0x00001000) >> 7) | (($key[1] & 0x00200000) >> 17) |
- (($key[1] & 0x00000002) << 2) | (($key[1] & 0x00000100) >> 6) |
- (($key[1] & 0x00008000) >> 14) | (($key[1] & 0x04000000) >> 26)
- ,
- (($key[0] & 0x00008000) >> 10) | ( $key[0] & 0x00000010 ) |
- (($key[0] & 0x02000000) >> 22) | (($key[0] & 0x00080000) >> 17) |
- (($key[0] & 0x00000200) >> 8) | (($key[0] & 0x00000002) >> 1)
- ,
- (($key[0] & 0x04000000) >> 21) | (($key[0] & 0x00010000) >> 12) |
- (($key[0] & 0x00000020) >> 2) | (($key[0] & 0x00000800) >> 9) |
- (($key[0] & 0x00800000) >> 22) | (($key[0] & 0x00000100) >> 8)
- ,
- (($key[0] & 0x00001000) >> 7) | (($key[0] & 0x00000088) >> 3) |
- (($key[0] & 0x00020000) >> 14) | (($key[0] & 0x00000001) << 2) |
- (($key[0] & 0x00400000) >> 21)
- ,
- (($key[0] & 0x00000400) >> 5) | (($key[0] & 0x00004000) >> 10) |
- (($key[0] & 0x00000040) >> 3) | (($key[0] & 0x00100000) >> 18) |
- (($key[0] & 0x08000000) >> 26) | (($key[0] & 0x01000000) >> 24)
- );
-
- $keys[] = $temp;
- }
-
- $temp = array(
- CRYPT_DES_ENCRYPT => $keys,
- CRYPT_DES_DECRYPT => array_reverse($keys)
- );
-
- return $temp;
- }
-}
-
-
-
-/**
- * Pure-PHP implementation of Triple DES.
- *
- * @author Jim Wigginton <terrafrost@php.net>
- * @version 0.1.0
- * @access public
- * @package Crypt_TerraDES
- */
-class tripledes
-{
- /**
- * The Three Keys
- *
- * @see tripledes::setKey()
- * @var String
- * @access private
- */
- var $key = "\0\0\0\0\0\0\0\0";
-
- /**
- * The Encryption Mode
- *
- * @see tripledes::tripledes()
- * @var Integer
- * @access private
- */
- var $mode = CRYPT_DES_MODE_CBC;
-
- /**
- * Continuous Buffer status
- *
- * @see tripledes::enableContinuousBuffer()
- * @var Boolean
- * @access private
- */
- var $continuousBuffer = false;
-
- /**
- * Padding status
- *
- * @see tripledes::enablePadding()
- * @var Boolean
- * @access private
- */
- var $padding = true;
-
- /**
- * The Initialization Vector
- *
- * @see tripledes::setIV()
- * @var String
- * @access private
- */
- var $iv = "\0\0\0\0\0\0\0\0";
-
- /**
- * A "sliding" Initialization Vector
- *
- * @see tripledes::enableContinuousBuffer()
- * @var String
- * @access private
- */
- var $encryptIV = "\0\0\0\0\0\0\0\0";
-
- /**
- * A "sliding" Initialization Vector
- *
- * @see tripledes::enableContinuousBuffer()
- * @var String
- * @access private
- */
- var $decryptIV = "\0\0\0\0\0\0\0\0";
-
- /**
- * MCrypt parameters
- *
- * @see tripledes::setMCrypt()
- * @var Array
- * @access private
- */
- var $mcrypt = array('', '');
-
- /**
- * The des objects
- *
- * @var Array
- * @access private
- */
- var $des;
-
- /**
- * Default Constructor.
- *
- * Determines whether or not the mcrypt extension should be used. $mode should only, at present, be
- * CRYPT_DES_MODE_ECB or CRYPT_DES_MODE_CBC. If not explictly set, CRYPT_DES_MODE_CBC will be used.
- *
- * @param optional Integer $mode
- * @return tripledes
- * @access public
- */
- function __construct($mode = CRYPT_DES_MODE_CBC)
- {
- if ( !defined('CRYPT_DES_MODE') )
- {
- switch (true)
- {
- case extension_loaded('mcrypt'):
- // i'd check to see if des was supported, by doing in_array('des', mcrypt_list_algorithms('')),
- // but since that can be changed after the object has been created, there doesn't seem to be
- // a lot of point...
- define('CRYPT_DES_MODE', CRYPT_DES_MODE_MCRYPT);
- break;
- default:
- define('CRYPT_DES_MODE', CRYPT_DES_MODE_INTERNAL);
- }
- }
-
- if ( $mode == CRYPT_DES_MODE_3CBC )
- {
- $this->mode = CRYPT_DES_MODE_3CBC;
- $this->des = array(
- new des(CRYPT_DES_MODE_CBC),
- new des(CRYPT_DES_MODE_CBC),
- new des(CRYPT_DES_MODE_CBC)
- );
-
- // we're going to be doing the padding, ourselves, so disable it in the des objects
- $this->des[0]->disable_padding();
- $this->des[1]->disable_padding();
- $this->des[2]->disable_padding();
-
- return;
- }
-
- switch ( CRYPT_DES_MODE )
- {
- case CRYPT_DES_MODE_MCRYPT:
- switch ($mode)
- {
- case CRYPT_DES_MODE_ECB:
- $this->mode = MCRYPT_MODE_ECB; break;
- case CRYPT_DES_MODE_CBC:
- default:
- $this->mode = MCRYPT_MODE_CBC;
- }
-
- break;
- default:
- $this->des = array(
- new des(CRYPT_DES_MODE_ECB),
- new des(CRYPT_DES_MODE_ECB),
- new des(CRYPT_DES_MODE_ECB)
- );
-
- // we're going to be doing the padding, ourselves, so disable it in the des objects
- $this->des[0]->disable_padding();
- $this->des[1]->disable_padding();
- $this->des[2]->disable_padding();
-
- switch ($mode)
- {
- case CRYPT_DES_MODE_ECB:
- case CRYPT_DES_MODE_CBC:
- $this->mode = $mode;
- break;
- default:
- $this->mode = CRYPT_DES_MODE_CBC;
- }
- }
- }
-
- /**
- * Sets the key.
- *
- * Keys can be of any length. Triple DES, itself, can use 128-bit (eg. strlen($key) == 16) or
- * 192-bit (eg. strlen($key) == 24) keys. This function pads and truncates $key as appropriate.
- *
- * DES also requires that every eighth bit be a parity bit, however, we'll ignore that.
- *
- * If the key is not explicitly set, it'll be assumed to be all zero's.
- *
- * @access public
- * @param String $key
- */
- function set_key($key)
- {
- $length = strlen($key);
- if ($length > 8)
- {
- $key = str_pad($key, 24, chr(0));
- // if $key is between 64 and 128-bits, use the first 64-bits as the last, per this:
- // http://php.net/function.mcrypt-encrypt#47973
- $key = $length <= 16 ? substr_replace($key, substr($key, 0, 8), 16) : substr($key, 0, 24);
- }
- $this->key = $key;
- switch (true)
- {
- case CRYPT_DES_MODE == CRYPT_DES_MODE_INTERNAL:
- case $this->mode == CRYPT_DES_MODE_3CBC:
- $this->des[0]->set_key(substr($key, 0, 8));
- $this->des[1]->set_key(substr($key, 8, 8));
- $this->des[2]->set_key(substr($key, 16, 8));
- }
- }
-
- /**
- * Sets the initialization vector. (optional)
- *
- * SetIV is not required when CRYPT_DES_MODE_ECB is being used. If not explictly set, it'll be assumed
- * to be all zero's.
- *
- * @access public
- * @param String $iv
- */
- function set_iv($iv)
- {
- $this->encryptIV = $this->decryptIV = $this->iv = str_pad(substr($iv, 0, 8), 8, chr(0));
- if ($this->mode == CRYPT_DES_MODE_3CBC)
- {
- $this->des[0]->set_iv($iv);
- $this->des[1]->set_iv($iv);
- $this->des[2]->set_iv($iv);
- }
- }
-
- /**
- * Sets MCrypt parameters. (optional)
- *
- * If MCrypt is being used, empty strings will be used, unless otherwise specified.
- *
- * @link http://php.net/function.mcrypt-module-open#function.mcrypt-module-open
- * @access public
- * @param optional Integer $algorithm_directory
- * @param optional Integer $mode_directory
- */
- function set_mcrypt($algorithm_directory = '', $mode_directory = '')
- {
- $this->mcrypt = array($algorithm_directory, $mode_directory);
- if ( $this->mode == CRYPT_DES_MODE_3CBC )
- {
- $this->des[0]->set_mcrypt($algorithm_directory, $mode_directory);
- $this->des[1]->set_mcrypt($algorithm_directory, $mode_directory);
- $this->des[2]->set_mcrypt($algorithm_directory, $mode_directory);
- }
- }
-
- /**
- * Encrypts a message.
- *
- * @access public
- * @param String $plaintext
- */
- function encrypt($plaintext)
- {
- $plaintext = $this->_pad($plaintext);
-
- // if the key is smaller then 8, do what we'd normally do
- if ($this->mode == CRYPT_DES_MODE_3CBC && strlen($this->key) > 8)
- {
- $ciphertext = $this->des[2]->encrypt($this->des[1]->decrypt($this->des[0]->encrypt($plaintext)));
-
- return $ciphertext;
- }
-
- if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT )
- {
- $td = mcrypt_module_open(MCRYPT_3DES, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);
- mcrypt_generic_init($td, $this->key, $this->encryptIV);
-
- $ciphertext = mcrypt_generic($td, $plaintext);
-
- mcrypt_generic_deinit($td);
- mcrypt_module_close($td);
-
- if ($this->continuousBuffer)
- {
- $this->encryptIV = substr($ciphertext, -8);
- }
-
- return $ciphertext;
- }
-
- if (strlen($this->key) <= 8)
- {
- $this->des[0]->mode = $this->mode;
-
- return $this->des[0]->encrypt($plaintext);
- }
-
- // we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
- // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
- $plaintext = str_pad($plaintext, ceil(strlen($plaintext) / 8) * 8, chr(0));
-
- $ciphertext = '';
- switch ($this->mode)
- {
- case CRYPT_DES_MODE_ECB:
- for ($i = 0; $i < strlen($plaintext); $i+=8)
- {
- $block = substr($plaintext, $i, 8);
- $block = $this->des[0]->_process_block($block, CRYPT_DES_ENCRYPT);
- $block = $this->des[1]->_process_block($block, CRYPT_DES_DECRYPT);
- $block = $this->des[2]->_process_block($block, CRYPT_DES_ENCRYPT);
- $ciphertext.= $block;
- }
- break;
- case CRYPT_DES_MODE_CBC:
- $xor = $this->encryptIV;
- for ($i = 0; $i < strlen($plaintext); $i+=8)
- {
- $block = substr($plaintext, $i, 8) ^ $xor;
- $block = $this->des[0]->_process_block($block, CRYPT_DES_ENCRYPT);
- $block = $this->des[1]->_process_block($block, CRYPT_DES_DECRYPT);
- $block = $this->des[2]->_process_block($block, CRYPT_DES_ENCRYPT);
- $xor = $block;
- $ciphertext.= $block;
- }
- if ($this->continuousBuffer)
- {
- $this->encryptIV = $xor;
- }
- }
-
- return $ciphertext;
- }
-
- /**
- * Decrypts a message.
- *
- * @access public
- * @param String $ciphertext
- */
- function decrypt($ciphertext)
- {
- if ($this->mode == CRYPT_DES_MODE_3CBC && strlen($this->key) > 8)
- {
- $plaintext = $this->des[0]->decrypt($this->des[1]->encrypt($this->des[2]->decrypt($ciphertext)));
-
- return $this->_unpad($plaintext);
- }
-
- // we pad with chr(0) since that's what mcrypt_generic does. to quote from http://php.net/function.mcrypt-generic :
- // "The data is padded with "\0" to make sure the length of the data is n * blocksize."
- $ciphertext = str_pad($ciphertext, (strlen($ciphertext) + 7) & 0xFFFFFFF8, chr(0));
-
- if ( CRYPT_DES_MODE == CRYPT_DES_MODE_MCRYPT )
- {
- $td = mcrypt_module_open(MCRYPT_3DES, $this->mcrypt[0], $this->mode, $this->mcrypt[1]);
- mcrypt_generic_init($td, $this->key, $this->decryptIV);
-
- $plaintext = mdecrypt_generic($td, $ciphertext);
-
- mcrypt_generic_deinit($td);
- mcrypt_module_close($td);
-
- if ($this->continuousBuffer)
- {
- $this->decryptIV = substr($ciphertext, -8);
- }
-
- return $this->_unpad($plaintext);
- }
-
- if (strlen($this->key) <= 8)
- {
- $this->des[0]->mode = $this->mode;
-
- return $this->_unpad($this->des[0]->decrypt($plaintext));
- }
-
- $plaintext = '';
- switch ($this->mode)
- {
- case CRYPT_DES_MODE_ECB:
- for ($i = 0; $i < strlen($ciphertext); $i+=8)
- {
- $block = substr($ciphertext, $i, 8);
- $block = $this->des[2]->_process_block($block, CRYPT_DES_DECRYPT);
- $block = $this->des[1]->_process_block($block, CRYPT_DES_ENCRYPT);
- $block = $this->des[0]->_process_block($block, CRYPT_DES_DECRYPT);
- $plaintext.= $block;
- }
- break;
- case CRYPT_DES_MODE_CBC:
- $xor = $this->decryptIV;
- for ($i = 0; $i < strlen($ciphertext); $i+=8)
- {
- $orig = $block = substr($ciphertext, $i, 8);
- $block = $this->des[2]->_process_block($block, CRYPT_DES_DECRYPT);
- $block = $this->des[1]->_process_block($block, CRYPT_DES_ENCRYPT);
- $block = $this->des[0]->_process_block($block, CRYPT_DES_DECRYPT);
- $plaintext.= $block ^ $xor;
- $xor = $orig;
- }
- if ($this->continuousBuffer)
- {
- $this->decryptIV = $xor;
- }
- }
-
- return $this->_unpad($plaintext);
- }
-
- /**
- * Treat consecutive "packets" as if they are a continuous buffer.
- *
- * Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
- * will yield different outputs:
- *
- * <code>
- * echo $des->encrypt(substr($plaintext, 0, 8));
- * echo $des->encrypt(substr($plaintext, 8, 8));
- * </code>
- * <code>
- * echo $des->encrypt($plaintext);
- * </code>
- *
- * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
- * another, as demonstrated with the following:
- *
- * <code>
- * $des->encrypt(substr($plaintext, 0, 8));
- * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
- * </code>
- * <code>
- * echo $des->decrypt($des->encrypt(substr($plaintext, 8, 8)));
- * </code>
- *
- * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
- * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
- * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
- *
- * Put another way, when the continuous buffer is enabled, the state of the des() object changes after each
- * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
- * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
- * however, they are also less intuitive and more likely to cause you problems.
- *
- * @see tripledes::disableContinuousBuffer()
- * @access public
- */
- function enable_continuous_buffer()
- {
- $this->continuousBuffer = true;
- if ($this->mode == CRYPT_DES_MODE_3CBC)
- {
- $this->des[0]->enable_continuous_buffer();
- $this->des[1]->enable_continuous_buffer();
- $this->des[2]->enable_continuous_buffer();
- }
- }
-
- /**
- * Treat consecutive packets as if they are a discontinuous buffer.
- *
- * The default behavior.
- *
- * @see tripledes::enableContinuousBuffer()
- * @access public
- */
- function disable_continuous_buffer()
- {
- $this->continuousBuffer = false;
- $this->encryptIV = $this->iv;
- $this->decryptIV = $this->iv;
-
- if ($this->mode == CRYPT_DES_MODE_3CBC)
- {
- $this->des[0]->disable_continuous_buffer();
- $this->des[1]->disable_continuous_buffer();
- $this->des[2]->disable_continuous_buffer();
- }
- }
-
- /**
- * Pad "packets".
- *
- * DES works by encrypting eight bytes at a time. If you ever need to encrypt or decrypt something that's not
- * a multiple of eight, it becomes necessary to pad the input so that it's length is a multiple of eight.
- *
- * Padding is enabled by default. Sometimes, however, it is undesirable to pad strings. Such is the case in SSH1,
- * where "packets" are padded with random bytes before being encrypted. Unpad these packets and you risk stripping
- * away characters that shouldn't be stripped away. (SSH knows how many bytes are added because the length is
- * transmitted separately)
- *
- * @see tripledes::disable_padding()
- * @access public
- */
- function enable_padding()
- {
- $this->padding = true;
- }
-
- /**
- * Do not pad packets.
- *
- * @see tripledes::enablePadding()
- * @access public
- */
- function disable_padding()
- {
- $this->padding = false;
- }
-
- /**
- * Pads a string
- *
- * Pads a string using the RSA PKCS padding standards so that its length is a multiple of the blocksize (8).
- * 8 - (strlen($text) & 7) bytes are added, each of which is equal to chr(8 - (strlen($text) & 7)
- *
- * If padding is disabled and $text is not a multiple of the blocksize, the string will be padded regardless
- * and padding will, hence forth, be enabled.
- *
- * @see tripledes::_unpad()
- * @access private
- */
- function _pad($text)
- {
- $length = strlen($text);
-
- if (!$this->padding)
- {
- if (($length & 7) == 0)
- {
- return $text;
- }
- else
- {
- $this->padding = true;
- }
- }
-
- $pad = 8 - ($length & 7);
- return str_pad($text, $length + $pad, chr($pad));
- }
-
- /**
- * Unpads a string
- *
- * If padding is enabled and the reported padding length exceeds the block size, padding will be, hence forth, disabled.
- *
- * @see tripledes::_pad()
- * @access private
- */
- function _unpad($text)
- {
- if (!$this->padding)
- {
- return $text;
- }
-
- $length = ord($text[strlen($text) - 1]);
-
- if ($length > 8)
- {
- $this->padding = false;
- return $text;
- }
-
- return substr($text, 0, -$length);
- }
-}
-
-?>
\ No newline at end of file diff --git a/phpBB/includes/libraries/sftp/hash.php b/phpBB/includes/libraries/sftp/hash.php deleted file mode 100644 index eb048f5d28..0000000000 --- a/phpBB/includes/libraries/sftp/hash.php +++ /dev/null @@ -1,278 +0,0 @@ -<?php
-/**
-*
-* @package sftp
-* @version $Id$
-* @copyright (c) 2006 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Code from http://phpseclib.sourceforge.net/
-*
-* Modified by phpBB Group to meet our coding standards
-* and being able to integrate into phpBB
-*
-* Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
-*
-* Copyright 2007-2009 TerraFrost <terrafrost@php.net>
-* Copyright 2009+ phpBB
-*
-* @package sftp
-* @author TerraFrost <terrafrost@php.net>
-*/
-
-/**#@+
- * @access private
- * @see hash::__construct()
- */
-/**
- * Toggles the internal implementation
- */
-define('CRYPT_HASH_MODE_INTERNAL', 1);
-/**
- * Toggles the mhash() implementation, which has been deprecated on PHP 5.3.0+.
- */
-define('CRYPT_HASH_MODE_MHASH', 2);
-/**
- * Toggles the hash() implementation, which works on PHP 5.1.2+.
- */
-define('CRYPT_HASH_MODE_HASH', 3);
-/**#@-*/
-
-/**
- * Pure-PHP implementations of keyed-hash message authentication codes (HMACs) and various cryptographic hashing functions.
- *
- * @author Jim Wigginton <terrafrost@php.net>
- * @version 0.1.0
- * @access public
- * @package hash
- */
-class hash
-{
- /**
- * Byte-length of compression blocks / key (Internal HMAC)
- *
- * @see hash::set_algorithm()
- * @var Integer
- * @access private
- */
- var $b;
-
- /**
- * Byte-length of hash output (Internal HMAC)
- *
- * @see hash::set_hash()
- * @var Integer
- * @access private
- */
- var $l;
-
- /**
- * Hash Algorithm
- *
- * @see hash::set_hash()
- * @var String
- * @access private
- */
- var $hash;
-
- /**
- * Key
- *
- * @see hash::setKey()
- * @var String
- * @access private
- */
- var $key = '';
-
- /**
- * Outer XOR (Internal HMAC)
- *
- * @see hash::setKey()
- * @var String
- * @access private
- */
- var $opad;
-
- /**
- * Inner XOR (Internal HMAC)
- *
- * @see hash::setKey()
- * @var String
- * @access private
- */
- var $ipad;
-
- /**
- * Default Constructor.
- *
- * @param optional String $hash
- * @return hash
- * @access public
- */
- function __construct($hash = 'sha1')
- {
- if ( !defined('CRYPT_HASH_MODE') )
- {
- switch (true)
- {
- case extension_loaded('hash'):
- define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_HASH);
- break;
- case extension_loaded('mhash'):
- define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_MHASH);
- break;
- default:
- define('CRYPT_HASH_MODE', CRYPT_HASH_MODE_INTERNAL);
- }
- }
-
- $this->set_hash($hash);
- }
-
- /**
- * Sets the key for HMACs
- *
- * Keys can be of any length.
- *
- * @access public
- * @param String $key
- */
- function set_key($key)
- {
- $this->key = $key;
- }
-
- /**
- * Sets the hash function.
- *
- * @access public
- * @param String $hash
- */
- function set_hash($hash)
- {
- switch ($hash)
- {
- case 'md5-96':
- case 'sha1-96':
- $this->l = 12; // 96 / 8 = 12
- break;
- case 'md5':
- $this->l = 16;
- break;
- case 'sha1':
- $this->l = 20;
- }
-
- switch (CRYPT_HASH_MODE)
- {
- case CRYPT_HASH_MODE_MHASH:
- switch ($hash)
- {
- case 'md5':
- case 'md5-96':
- $this->hash = MHASH_MD5;
- break;
- case 'sha1':
- case 'sha1-96':
- default:
- $this->hash = MHASH_SHA1;
- }
- return;
- case CRYPT_HASH_MODE_HASH:
- switch ($hash)
- {
- case 'md5':
- case 'md5-96':
- $this->hash = 'md5';
- return;
- case 'sha1':
- case 'sha1-96':
- default:
- $this->hash = 'sha1';
- }
- return;
- }
-
- switch ($hash)
- {
- case 'md5':
- case 'md5-96':
- $this->b = 64;
- $this->hash = 'md5';
- break;
- case 'sha1':
- case 'sha1-96':
- default:
- $this->b = 64;
- $this->hash = 'sha1';
- }
-
- $this->ipad = str_repeat(chr(0x36), $this->b);
- $this->opad = str_repeat(chr(0x5C), $this->b);
- }
-
- /**
- * Compute the HMAC.
- *
- * @access public
- * @param String $text
- */
- function create($text)
- {
- if (!empty($this->key))
- {
- switch (CRYPT_HASH_MODE)
- {
- case CRYPT_HASH_MODE_MHASH:
- $output = mhash($this->hash, $text, $this->key);
- break;
- case CRYPT_HASH_MODE_HASH:
- $output = hash_hmac($this->hash, $text, $this->key, true);
- break;
- case CRYPT_HASH_MODE_INTERNAL:
- $hash = $this->hash;
- /* "Applications that use keys longer than B bytes will first hash the key using H and then use the
- resultant L byte string as the actual key to HMAC."
-
- -- http://tools.ietf.org/html/rfc2104#section-2 */
- $key = strlen($this->key) > $this->b ? $hash($this->key) : $this->key;
-
- $key = str_pad($key, $this->b, chr(0));// step 1
- $temp = $this->ipad ^ $key; // step 2
- $temp .= $text; // step 3
- $temp = pack('H*', $hash($temp)); // step 4
- $output = $this->opad ^ $key; // step 5
- $output.= $temp; // step 6
- $output = pack('H*', $hash($output)); // step 7
- }
- }
- else
- {
- switch (CRYPT_HASH_MODE)
- {
- case CRYPT_HASH_MODE_MHASH:
- $output = mhash($this->hash, $text);
- break;
- case CRYPT_HASH_MODE_MHASH:
- $output = hash($this->hash, $text, true);
- break;
- case CRYPT_HASH_MODE_INTERNAL:
- $hash = $this->hash;
- $output = pack('H*', $hash($output));
- }
- }
-
- return substr($output, 0, $this->l);
- }
-}
\ No newline at end of file diff --git a/phpBB/includes/libraries/sftp/random.php b/phpBB/includes/libraries/sftp/random.php deleted file mode 100644 index cfc7ef0bc7..0000000000 --- a/phpBB/includes/libraries/sftp/random.php +++ /dev/null @@ -1,64 +0,0 @@ -<?php
-/**
-*
-* @package sftp
-* @version $Id$
-* @copyright (c) 2006 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Code from http://phpseclib.sourceforge.net/
-*
-* Modified by phpBB Group to meet our coding standards
-* and being able to integrate into phpBB
-*
-* Copyright 2007-2009 TerraFrost <terrafrost@php.net>
-* Copyright 2009+ phpBB
-*
-* @package sftp
-* @author TerraFrost <terrafrost@php.net>
-*/
-
-/**
- * Generate a random value. Feel free to replace this function with a cryptographically secure PRNG.
- *
- * @param optional Integer $min
- * @param optional Integer $max
- * @param optional String $randomness_path
- * @return Integer
- * @access public
- */
-function crypt_random($min = 0, $max = 0x7FFFFFFF, $randomness_path = '/dev/urandom')
-{
- static $seeded = false;
-
- if (!$seeded)
- {
- $seeded = true;
- if (file_exists($randomness_path))
- {
- $fp = fopen($randomness_path, 'r');
- $temp = unpack('Nint', fread($fp, 4));
- mt_srand($temp['int']);
- fclose($fp);
- }
- else
- {
- list($sec, $usec) = explode(' ', microtime());
- mt_srand((float) $sec + ((float) $usec * 100000));
- }
- }
-
- return mt_rand($min, $max);
-}
-?>
\ No newline at end of file diff --git a/phpBB/includes/libraries/sftp/rc4.php b/phpBB/includes/libraries/sftp/rc4.php deleted file mode 100644 index 88a5c2f345..0000000000 --- a/phpBB/includes/libraries/sftp/rc4.php +++ /dev/null @@ -1,490 +0,0 @@ -<?php
-/**
-*
-* @package sftp
-* @version $Id$
-* @copyright (c) 2006 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Code from http://phpseclib.sourceforge.net/
-*
-* Modified by phpBB Group to meet our coding standards
-* and being able to integrate into phpBB
-*
-* Pure-PHP implementation of RC4
-*
-* Copyright 2007-2009 TerraFrost <terrafrost@php.net>
-* Copyright 2009+ phpBB
-*
-* @package sftp
-* @author TerraFrost <terrafrost@php.net>
-*/
-
-/**#@+
- * @access private
- * @see rc4::__construct()
- */
-/**
- * Toggles the internal implementation
- */
-define('CRYPT_RC4_MODE_INTERNAL', 1);
-/**
- * Toggles the mcrypt implementation
- */
-define('CRYPT_RC4_MODE_MCRYPT', 2);
-/**#@-*/
-
-/**#@+
- * @access private
- * @see rc4::_crypt()
- */
-define('CRYPT_RC4_ENCRYPT', 0);
-define('CRYPT_RC4_DECRYPT', 1);
-/**#@-*/
-
-/**
- * Pure-PHP implementation of RC4.
- *
- * @author Jim Wigginton <terrafrost@php.net>
- * @version 0.1.0
- * @access public
- * @package rc4
- */
-class rc4
-{
- /**
- * The Key
- *
- * @see rc4::set_key()
- * @var String
- * @access private
- */
- var $key = "\0";
-
- /**
- * The Key Stream for encryption
- *
- * If CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT, this will be equal to the mcrypt object
- *
- * @see rc4::set_key()
- * @var Array
- * @access private
- */
- var $encryptStream = false;
-
- /**
- * The Key Stream for decryption
- *
- * If CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT, this will be equal to the mcrypt object
- *
- * @see rc4::set_key()
- * @var Array
- * @access private
- */
- var $decryptStream = false;
-
- /**
- * The $i and $j indexes for encryption
- *
- * @see rc4::_crypt()
- * @var Integer
- * @access private
- */
- var $encryptIndex = 0;
-
- /**
- * The $i and $j indexes for decryption
- *
- * @see rc4::_crypt()
- * @var Integer
- * @access private
- */
- var $decryptIndex = 0;
-
- /**
- * MCrypt parameters
- *
- * @see rc4::set_mcrypt()
- * @var Array
- * @access private
- */
- var $mcrypt = array('', '');
-
- /**
- * The Encryption Algorithm
- *
- * Only used if CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT. Only possible values are MCRYPT_RC4 or MCRYPT_ARCFOUR.
- *
- * @see rc4::__construct()
- * @var Integer
- * @access private
- */
- var $mode;
-
- /**
- * Default Constructor.
- *
- * Determines whether or not the mcrypt extension should be used.
- *
- * @param optional Integer $mode
- * @return rc4
- * @access public
- */
- function __construct()
- {
- if ( !defined('CRYPT_RC4_MODE') )
- {
- switch (true)
- {
- case extension_loaded('mcrypt') && (defined('MCRYPT_ARCFOUR') || defined('MCRYPT_RC4')):
- // i'd check to see if rc4 was supported, by doing in_array('arcfour', mcrypt_list_algorithms('')),
- // but since that can be changed after the object has been created, there doesn't seem to be
- // a lot of point...
- define('CRYPT_RC4_MODE', CRYPT_RC4_MODE_MCRYPT);
- break;
- default:
- define('CRYPT_RC4_MODE', CRYPT_RC4_MODE_INTERNAL);
- }
- }
-
- switch ( CRYPT_RC4_MODE )
- {
- case CRYPT_RC4_MODE_MCRYPT:
- switch (true)
- {
- case defined('MCRYPT_ARCFOUR'):
- $this->mode = MCRYPT_ARCFOUR;
- break;
- case defined('MCRYPT_RC4');
- $this->mode = MCRYPT_RC4;
- }
- }
- }
-
- /**
- * Sets the key.
- *
- * Keys can be between 1 and 256 bytes long. If they are longer then 256 bytes, the first 256 bytes will
- * be used. If no key is explicitly set, it'll be assumed to be a single null byte.
- *
- * @access public
- * @param String $key
- */
- function set_key($key)
- {
- $this->key = $key;
-
- if (CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT)
- {
- return;
- }
-
- $keyLength = strlen($key);
- $keyStream = array();
- for ($i = 0; $i < 256; $i++)
- {
- $keyStream[$i] = $i;
- }
- $j = 0;
- for ($i = 0; $i < 256; $i++)
- {
- $j = ($j + $keyStream[$i] + ord($key[$i % $keyLength])) & 255;
- $temp = $keyStream[$i];
- $keyStream[$i] = $keyStream[$j];
- $keyStream[$j] = $temp;
- }
-
- $this->encryptIndex = $this->decryptIndex = array(0, 0);
- $this->encryptStream = $this->decryptStream = $keyStream;
- }
-
- /**
- * Dummy function.
- *
- * Some protocols, such as WEP, prepend an "initialization vector" to the key, effectively creating a new key [1].
- * If you need to use an initialization vector in this manner, feel free to prepend it to the key, yourself, before
- * calling set_key().
- *
- * [1] WEP's initialization vectors (IV's) are used in a somewhat insecure way. Since, in that protocol,
- * the IV's are relatively easy to predict, an attack described by
- * {@link http://www.drizzle.com/~aboba/IEEE/rc4_ksaproc.pdf Scott Fluhrer, Itsik Mantin, and Adi Shamir}
- * can be used to quickly guess at the rest of the key. The following links elaborate:
- *
- * {@link http://www.rsa.com/rsalabs/node.asp?id=2009 http://www.rsa.com/rsalabs/node.asp?id=2009}
- * {@link http://en.wikipedia.org/wiki/Related_key_attack http://en.wikipedia.org/wiki/Related_key_attack}
- *
- * @param String $iv
- * @see rc4::set_key()
- * @access public
- */
- function setIV($iv)
- {
- }
-
- /**
- * Sets MCrypt parameters. (optional)
- *
- * If MCrypt is being used, empty strings will be used, unless otherwise specified.
- *
- * @link http://php.net/function.mcrypt-module-open#function.mcrypt-module-open
- * @access public
- * @param optional Integer $algorithm_directory
- * @param optional Integer $mode_directory
- */
- function set_mcrypt($algorithm_directory = '', $mode_directory = '')
- {
- if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT )
- {
- $this->mcrypt = array($algorithm_directory, $mode_directory);
- $this->_close_mcrypt();
- }
- }
-
- /**
- * Encrypts a message.
- *
- * @see rc4::_crypt()
- * @access public
- * @param String $plaintext
- */
- function encrypt($plaintext)
- {
- return $this->_crypt($plaintext, CRYPT_RC4_ENCRYPT);
- }
-
- /**
- * Decrypts a message.
- *
- * $this->decrypt($this->encrypt($plaintext)) == $this->encrypt($this->encrypt($plaintext)).
- * Atleast if the continuous buffer is disabled.
- *
- * @see rc4::_crypt()
- * @access public
- * @param String $ciphertext
- */
- function decrypt($ciphertext)
- {
- return $this->_crypt($ciphertext, CRYPT_RC4_DECRYPT);
- }
-
- /**
- * Encrypts or decrypts a message.
- *
- * @see rc4::encrypt()
- * @see rc4::decrypt()
- * @access private
- * @param String $text
- * @param Integer $mode
- */
- function _crypt($text, $mode)
- {
- if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT )
- {
- $keyStream = $mode == CRYPT_RC4_ENCRYPT ? 'encryptStream' : 'decryptStream';
-
- if ($this->$keyStream === false)
- {
- $this->$keyStream = mcrypt_module_open($this->mode, $this->mcrypt[0], MCRYPT_MODE_STREAM, $this->mcrypt[1]);
- mcrypt_generic_init($this->$keyStream, $this->key, '');
- }
- else if (!$this->continuousBuffer)
- {
- mcrypt_generic_init($this->$keyStream, $this->key, '');
- }
- $newText = mcrypt_generic($this->$keyStream, $text);
- if (!$this->continuousBuffer)
- {
- mcrypt_generic_deinit($this->$keyStream);
- }
-
- return $newText;
- }
-
- if ($this->encryptStream === false)
- {
- $this->set_key($this->key);
- }
-
- switch ($mode)
- {
- case CRYPT_RC4_ENCRYPT:
- $keyStream = $this->encryptStream;
- list($i, $j) = $this->encryptIndex;
- break;
- case CRYPT_RC4_DECRYPT:
- $keyStream = $this->decryptStream;
- list($i, $j) = $this->decryptIndex;
- }
-
- $newText = '';
- for ($k = 0; $k < strlen($text); $k++)
- {
- $i = ($i + 1) & 255;
- $j = ($j + $keyStream[$i]) & 255;
- $temp = $keyStream[$i];
- $keyStream[$i] = $keyStream[$j];
- $keyStream[$j] = $temp;
- $temp = $keyStream[($keyStream[$i] + $keyStream[$j]) & 255];
- $newText.= chr(ord($text[$k]) ^ $temp);
- }
-
- if ($this->continuousBuffer)
- {
- switch ($mode)
- {
- case CRYPT_RC4_ENCRYPT:
- $this->encryptStream = $keyStream;
- $this->encryptIndex = array($i, $j);
- break;
- case CRYPT_RC4_DECRYPT:
- $this->decryptStream = $keyStream;
- $this->decryptIndex = array($i, $j);
- }
- }
-
- return $newText;
- }
-
- /**
- * Treat consecutive "packets" as if they are a continuous buffer.
- *
- * Say you have a 16-byte plaintext $plaintext. Using the default behavior, the two following code snippets
- * will yield different outputs:
- *
- * <code>
- * echo $rc4->encrypt(substr($plaintext, 0, 8));
- * echo $rc4->encrypt(substr($plaintext, 8, 8));
- * </code>
- * <code>
- * echo $rc4->encrypt($plaintext);
- * </code>
- *
- * The solution is to enable the continuous buffer. Although this will resolve the above discrepancy, it creates
- * another, as demonstrated with the following:
- *
- * <code>
- * $rc4->encrypt(substr($plaintext, 0, 8));
- * echo $rc4->decrypt($des->encrypt(substr($plaintext, 8, 8)));
- * </code>
- * <code>
- * echo $rc4->decrypt($des->encrypt(substr($plaintext, 8, 8)));
- * </code>
- *
- * With the continuous buffer disabled, these would yield the same output. With it enabled, they yield different
- * outputs. The reason is due to the fact that the initialization vector's change after every encryption /
- * decryption round when the continuous buffer is enabled. When it's disabled, they remain constant.
- *
- * Put another way, when the continuous buffer is enabled, the state of the Crypt_DES() object changes after each
- * encryption / decryption round, whereas otherwise, it'd remain constant. For this reason, it's recommended that
- * continuous buffers not be used. They do offer better security and are, in fact, sometimes required (SSH uses them),
- * however, they are also less intuitive and more likely to cause you problems.
- *
- * @see rc4::disable_continuous_buffer()
- * @access public
- */
- function enable_continuous_buffer()
- {
- $this->continuousBuffer = true;
- }
-
- /**
- * Treat consecutive packets as if they are a discontinuous buffer.
- *
- * The default behavior.
- *
- * @see rc4::enable_continuous_buffer()
- * @access public
- */
- function disable_continuous_buffer()
- {
- if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_INTERNAL )
- {
- $this->encryptIndex = $this->decryptIndex = array(0, 0);
- $this->set_key($this->key);
- }
-
- $this->continuousBuffer = false;
- }
-
- /**
- * Dummy function.
- *
- * Since RC4 is a stream cipher and not a block cipher, no padding is necessary. The only reason this function is
- * included is so that you can switch between a block cipher and a stream cipher transparently.
- *
- * @see rc4::disable_padding()
- * @access public
- */
- function enable_padding()
- {
- }
-
- /**
- * Dummy function.
- *
- * @see rc4::enable_padding()
- * @access public
- */
- function disable_padding()
- {
- }
-
- /**
- * Class destructor.
- *
- * Will be called, automatically, if you're using PHP5. If you're using PHP4, call it yourself. Only really
- * needs to be called if mcrypt is being used.
- *
- * @access public
- */
- function __destruct()
- {
- if ( CRYPT_RC4_MODE == CRYPT_RC4_MODE_MCRYPT )
- {
- $this->_close_mcrypt();
- }
- }
-
- /**
- * Properly close the MCrypt objects.
- *
- * @access prviate
- */
- function _close_mcrypt()
- {
- if ( $this->encryptStream !== false )
- {
- if ( $this->continuousBuffer )
- {
- mcrypt_generic_deinit($this->encryptStream);
- }
-
- mcrypt_module_close($this->encryptStream);
-
- $this->encryptStream = false;
- }
-
- if ( $this->decryptStream !== false )
- {
- if ( $this->continuousBuffer )
- {
- mcrypt_generic_deinit($this->decryptStream);
- }
-
- mcrypt_module_close($this->decryptStream);
-
- $this->decryptStream = false;
- }
- }
-}
\ No newline at end of file diff --git a/phpBB/includes/libraries/sftp/sftp.php b/phpBB/includes/libraries/sftp/sftp.php deleted file mode 100644 index 41915c5ea9..0000000000 --- a/phpBB/includes/libraries/sftp/sftp.php +++ /dev/null @@ -1,3247 +0,0 @@ -<?php
-/**
-*
-* @package sftp
-* @version $Id$
-* @copyright (c) 2006 phpBB Group
-* @license http://opensource.org/licenses/gpl-license.php GNU Public License
-*
-*/
-
-/**
-* @ignore
-*/
-if (!defined('IN_PHPBB'))
-{
- exit;
-}
-
-/**
-* Code from http://phpseclib.sourceforge.net/
-*
-* Modified by phpBB Group to meet our coding standards
-* and being able to integrate into phpBB
-*
-* Pure-PHP implementation of ssh2
-*
-* Copyright 2007-2009 TerraFrost <terrafrost@php.net>
-* Copyright 2009+ phpBB
-*
-* @package sftp
-* @author TerraFrost <terrafrost@php.net>
-*/
-
-include('biginteger.' . PHP_EXT);
-include('random.' . PHP_EXT);
-include('hash.' . PHP_EXT);
-include('rc4.' . PHP_EXT);
-include('aes.' . PHP_EXT);
-include('des.' . PHP_EXT);
-
-/**#@+
- * Execution Bitmap Masks
- *
- * @see ssh2::bitmap
- * @access private
- */
-define('NET_SSH2_MASK_CONSTRUCTOR', 0x00000001);
-define('NET_SSH2_MASK_LOGIN', 0x00000002);
-/**#@-*/
-
-/**#@+
- * @access public
- * @see ssh2::getLog()
- */
-/**
- * Returns the message numbers
- */
-define('NET_SSH2_LOG_SIMPLE', 1);
-/**
- * Returns the message content
- */
-define('NET_SSH2_LOG_COMPLEX', 2);
-/**#@-*/
-
-/**#@+
- * @access public
- * @see ssh2_sftp::get_log()
- */
-/**
- * Returns the message numbers
- */
-define('NET_SFTP_LOG_SIMPLE', NET_SSH2_LOG_SIMPLE);
-/**
- * Returns the message content
- */
-define('NET_SFTP_LOG_COMPLEX', NET_SSH2_LOG_COMPLEX);
-/**#@-*/
-
-/**
- * Pure-PHP implementation of SSHv2.
- *
- * @author Jim Wigginton <terrafrost@php.net>
- * @version 0.1.0
- * @access public
- * @package ssh2
- */
-class ssh2
-{
- /**
- * The SSH identifier
- *
- * @var String
- * @access private
- */
- var $identifier = 'SSH-2.0-phpseclib_0.1';
-
- /**
- * The Socket Object
- *
- * @var Object
- * @access private
- */
- var $fsock;
-
- /**
- * Execution Bitmap
- *
- * The bits that are set reprsent functions that have been called already. This is used to determine
- * if a requisite function has been successfully executed. If not, an error should be thrown.
- *
- * @var Integer
- * @access private
- */
- var $bitmap = 0;
-
- /**
- * Debug Info
- *
- * @see ssh2::get_debug_info()
- * @var String
- * @access private
- */
- var $debug_info = '';
-
- /**
- * Server Identifier
- *
- * @see ssh2::get_server_identification()
- * @var String
- * @access private
- */
- var $server_identifier = '';
-
- /**
- * Key Exchange Algorithms
- *
- * @see ssh2::get_kex_algorithims()
- * @var Array
- * @access private
- */
- var $kex_algorithms;
-
- /**
- * Server Host Key Algorithms
- *
- * @see ssh2::get_server_host_key_algorithms()
- * @var Array
- * @access private
- */
- var $server_host_key_algorithms;
-
- /**
- * Encryption Algorithms: Client to Server
- *
- * @see ssh2::get_encryption_algorithms_client_to_server()
- * @var Array
- * @access private
- */
- var $encryption_algorithms_client_to_server;
-
- /**
- * Encryption Algorithms: Server to Client
- *
- * @see ssh2::get_encryption_algorithms_server_to_client()
- * @var Array
- * @access private
- */
- var $encryption_algorithms_server_to_client;
-
- /**
- * MAC Algorithms: Client to Server
- *
- * @see ssh2::get_mac_algorithms_client_to_server()
- * @var Array
- * @access private
- */
- var $mac_algorithms_client_to_server;
-
- /**
- * MAC Algorithms: Server to Client
- *
- * @see ssh2::get_mac_algorithms_server_to_client()
- * @var Array
- * @access private
- */
- var $mac_algorithms_server_to_client;
-
- /**
- * Compression Algorithms: Client to Server
- *
- * @see ssh2::get_compression_algorithms_client_to_server()
- * @var Array
- * @access private
- */
- var $compression_algorithms_client_to_server;
-
- /**
- * Compression Algorithms: Server to Client
- *
- * @see ssh2::get_compression_algorithms_server_to_client()
- * @var Array
- * @access private
- */
- var $compression_algorithms_server_to_client;
-
- /**
- * Languages: Server to Client
- *
- * @see ssh2::get_languages_server_to_client()
- * @var Array
- * @access private
- */
- var $languages_server_to_client;
-
- /**
- * Languages: Client to Server
- *
- * @see ssh2::get_languages_client_to_server()
- * @var Array
- * @access private
- */
- var $languages_client_to_server;
-
- /**
- * Block Size for Server to Client Encryption
- *
- * "Note that the length of the concatenation of 'packet_length',
- * 'padding_length', 'payload', and 'random padding' MUST be a multiple
- * of the cipher block size or 8, whichever is larger. This constraint
- * MUST be enforced, even when using stream ciphers."
- *
- * -- http://tools.ietf.org/html/rfc4253#section-6
- *
- * @see ssh2::__constructor()
- * @see ssh2::_send_binary_packet()
- * @var Integer
- * @access private
- */
- var $encrypt_block_size = 8;
-
- /**
- * Block Size for Client to Server Encryption
- *
- * @see ssh2::ssh2()
- * @see ssh2::_get_binary_packet()
- * @var Integer
- * @access private
- */
- var $decrypt_block_size = 8;
-
- /**
- * Server to Client Encryption Object
- *
- * @see ssh2::_get_binary_packet()
- * @var Object
- * @access private
- */
- var $decrypt = false;
-
- /**
- * Client to Server Encryption Object
- *
- * @see ssh2::_send_binary_packet()
- * @var Object
- * @access private
- */
- var $encrypt = false;
-
- /**
- * Client to Server HMAC Object
- *
- * @see ssh2::_send_binary_packet()
- * @var Object
- * @access private
- */
- var $hmac_create = false;
-
- /**
- * Server to Client HMAC Object
- *
- * @see ssh2::_get_binary_packet()
- * @var Object
- * @access private
- */
- var $hmac_check = false;
-
- /**
- * Size of server to client HMAC
- *
- * We need to know how big the HMAC will be for the server to client direction so that we know how many bytes to read.
- * For the client to server side, the HMAC object will make the HMAC as long as it needs to be. All we need to do is
- * append it.
- *
- * @see ssh2::_get_binary_packet()
- * @var Integer
- * @access private
- */
- var $hmac_size = false;
-
- /**
- * Server Public Host Key
- *
- * @see ssh2::getServerPublicHostKey()
- * @var String
- * @access private
- */
- var $server_public_host_key;
-
- /**
- * Session identifer
- *
- * "The exchange hash H from the first key exchange is additionally
- * used as the session identifier, which is a unique identifier for
- * this connection."
- *
- * -- http://tools.ietf.org/html/rfc4253#section-7.2
- *
- * @see ssh2::_key_exchange()
- * @var String
- * @access private
- */
- var $session_id = false;
-
- /**
- * Message Numbers
- *
- * @see ssh2::ssh2()
- * @var Array
- * @access private
- */
- var $message_numbers = array();
-
- /**
- * Disconnection Message 'reason codes' defined in RFC4253
- *
- * @see ssh2::ssh2()
- * @var Array
- * @access private
- */
- var $disconnect_reasons = array();
-
- /**
- * SSH_MSG_CHANNEL_OPEN_FAILURE 'reason codes', defined in RFC4254
- *
- * @see ssh2::ssh2()
- * @var Array
- * @access private
- */
- var $channel_open_failure_reasons = array();
-
- /**
- * Terminal Modes
- *
- * @link http://tools.ietf.org/html/rfc4254#section-8
- * @see ssh2::ssh2()
- * @var Array
- * @access private
- */
- var $terminal_modes = array();
-
- /**
- * SSH_MSG_CHANNEL_EXTENDED_DATA's data_type_codes
- *
- * @link http://tools.ietf.org/html/rfc4254#section-5.2
- * @see ssh2::ssh2()
- * @var Array
- * @access private
- */
- var $channel_extended_data_type_codes = array();
-
- /**
- * Send Sequence Number
- *
- * See 'Section 6.4. Data Integrity' of rfc4253 for more info.
- *
- * @see ssh2::_send_binary_packet()
- * @var Integer
- * @access private
- */
- var $send_seq_no = 0;
-
- /**
- * Get Sequence Number
- *
- * See 'Section 6.4. Data Integrity' of rfc4253 for more info.
- *
- * @see ssh2::_get_binary_packet()
- * @var Integer
- * @access private
- */
- var $get_seq_no = 0;
-
- /**
- * Message Number Log
- *
- * @see ssh2::getLog()
- * @var Array
- * @access private
- */
- var $message_number_log = array();
-
- /**
- * Message Log
- *
- * @see ssh2::getLog()
- * @var Array
- * @access private
- */
- var $message_log = array();
-
- /**
- * Default Constructor.
- *
- * Connects to an SSHv2 server
- *
- * @param String $host
- * @param optional Integer $port
- * @param optional Integer $timeout
- * @return ssh2
- * @access public
- */
- function __construct($host, $port = 22, $timeout = 10)
- {
- $this->message_numbers = array(
- 1 => 'NET_SSH2_MSG_DISCONNECT',
- 2 => 'NET_SSH2_MSG_IGNORE',
- 3 => 'NET_SSH2_MSG_UNIMPLEMENTED',
- 4 => 'NET_SSH2_MSG_DEBUG',
- 5 => 'NET_SSH2_MSG_SERVICE_REQUEST',
- 6 => 'NET_SSH2_MSG_SERVICE_ACCEPT',
- 20 => 'NET_SSH2_MSG_KEXINIT',
- 21 => 'NET_SSH2_MSG_NEWKEYS',
- 30 => 'NET_SSH2_MSG_KEXDH_INIT',
- 31 => 'NET_SSH2_MSG_KEXDH_REPLY',
- 50 => 'NET_SSH2_MSG_USERAUTH_REQUEST',
- 51 => 'NET_SSH2_MSG_USERAUTH_FAILURE',
- 52 => 'NET_SSH2_MSG_USERAUTH_SUCCESS',
- 53 => 'NET_SSH2_MSG_USERAUTH_BANNER',
- 60 => 'NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ',
-
- 80 => 'NET_SSH2_MSG_GLOBAL_REQUEST',
- 81 => 'NET_SSH2_MSG_REQUEST_SUCCESS',
- 82 => 'NET_SSH2_MSG_REQUEST_FAILURE',
- 90 => 'NET_SSH2_MSG_CHANNEL_OPEN',
- 91 => 'NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION',
- 92 => 'NET_SSH2_MSG_CHANNEL_OPEN_FAILURE',
- 93 => 'NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST',
- 94 => 'NET_SSH2_MSG_CHANNEL_DATA',
- 95 => 'NET_SSH2_MSG_CHANNEL_EXTENDED_DATA',
- 96 => 'NET_SSH2_MSG_CHANNEL_EOF',
- 97 => 'NET_SSH2_MSG_CHANNEL_CLOSE',
- 98 => 'NET_SSH2_MSG_CHANNEL_REQUEST',
- 99 => 'NET_SSH2_MSG_CHANNEL_SUCCESS',
- 100 => 'NET_SSH2_MSG_CHANNEL_FAILURE'
- );
- $this->disconnect_reasons = array(
- 1 => 'NET_SSH2_DISCONNECT_HOST_NOT_ALLOWED_TO_CONNECT',
- 2 => 'NET_SSH2_DISCONNECT_PROTOCOL_ERROR',
- 3 => 'NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED',
- 4 => 'NET_SSH2_DISCONNECT_RESERVED',
- 5 => 'NET_SSH2_DISCONNECT_MAC_ERROR',
- 6 => 'NET_SSH2_DISCONNECT_COMPRESSION_ERROR',
- 7 => 'NET_SSH2_DISCONNECT_SERVICE_NOT_AVAILABLE',
- 8 => 'NET_SSH2_DISCONNECT_PROTOCOL_VERSION_NOT_SUPPORTED',
- 9 => 'NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE',
- 10 => 'NET_SSH2_DISCONNECT_CONNECTION_LOST',
- 11 => 'NET_SSH2_DISCONNECT_BY_APPLICATION',
- 12 => 'NET_SSH2_DISCONNECT_TOO_MANY_CONNECTIONS',
- 13 => 'NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER',
- 14 => 'NET_SSH2_DISCONNECT_NO_MORE_AUTH_METHODS_AVAILABLE',
- 15 => 'NET_SSH2_DISCONNECT_ILLEGAL_USER_NAME'
- );
- $this->channel_open_failure_reasons = array(
- 1 => 'NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED'
- );
- $this->terminal_modes = array(
- 0 => 'NET_SSH2_TTY_OP_END'
- );
- $this->channel_extended_data_type_codes = array(
- 1 => 'NET_SSH2_EXTENDED_DATA_STDERR'
- );
-
- $this->_define_array(
- $this->message_numbers,
- $this->disconnect_reasons,
- $this->channel_open_failure_reasons,
- $this->terminal_modes,
- $this->channel_extended_data_type_codes
- );
-
- $this->fsock = @fsockopen($host, $port, $errno, $errstr, $timeout);
- if (!$this->fsock)
- {
- return;
- }
-
- /* According to the SSH2 specs,
-
- "The server MAY send other lines of data before sending the version
- string. Each line SHOULD be terminated by a Carriage Return and Line
- Feed. Such lines MUST NOT begin with "SSH-", and SHOULD be encoded
- in ISO-10646 UTF-8 [RFC3629] (language is not specified). Clients
- MUST be able to process such lines." */
- $temp = '';
- while (!feof($this->fsock) && !preg_match('#^SSH-(\d\.\d+)#', $temp, $matches))
- {
- if (substr($temp, -2) == "\r\n")
- {
- $this->debug_info.= $temp;
- $temp = '';
- }
- $temp.= fgets($this->fsock, 255);
- }
- $this->server_identifier = trim($temp);
- $this->debug_info = utf8_decode($this->debug_info);
-
- if ($matches[1] != '1.99' && $matches[1] != '2.0')
- {
- return;
- }
-
- fputs($this->fsock, $this->identifier . "\r\n");
-
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return;
- }
-
- if (ord($response[0]) != NET_SSH2_MSG_KEXINIT)
- {
- return;
- }
-
- if (!$this->_key_exchange($response))
- {
- return;
- }
-
- $this->bitmap = NET_SSH2_MASK_CONSTRUCTOR;
- }
-
- /**
- * Key Exchange
- *
- * @param String $kexinit_payload_server
- * @access private
- */
- function _key_exchange($kexinit_payload_server)
- {
- static $kex_algorithms = array(
- 'diffie-hellman-group1-sha1', // REQUIRED
- 'diffie-hellman-group14-sha1' // REQUIRED
- );
-
- static $server_host_key_algorithms = array(
- 'ssh-rsa', // RECOMMENDED sign Raw RSA Key
- 'ssh-dss' // REQUIRED sign Raw DSS Key
- );
-
- static $encryption_algorithms = array(
- 'arcfour', // OPTIONAL the ARCFOUR stream cipher with a 128-bit key
- 'aes128-cbc', // RECOMMENDED AES with a 128-bit key
- 'aes192-cbc', // OPTIONAL AES with a 192-bit key
- 'aes256-cbc', // OPTIONAL AES in CBC mode, with a 256-bit key
- '3des-cbc', // REQUIRED three-key 3DES in CBC mode
- 'none' // OPTIONAL no encryption; NOT RECOMMENDED
- );
-
- static $mac_algorithms = array(
- 'hmac-sha1-96', // RECOMMENDED first 96 bits of HMAC-SHA1 (digest length = 12, key length = 20)
- 'hmac-sha1', // REQUIRED HMAC-SHA1 (digest length = key length = 20)
- 'hmac-md5-96', // OPTIONAL first 96 bits of HMAC-MD5 (digest length = 12, key length = 16)
- 'hmac-md5', // OPTIONAL HMAC-MD5 (digest length = key length = 16)
- 'none' // OPTIONAL no MAC; NOT RECOMMENDED
- );
-
- static $compression_algorithms = array(
- 'none' // REQUIRED no compression
- //'zlib' // OPTIONAL ZLIB (LZ77) compression
- );
-
- static $str_kex_algorithms, $str_server_host_key_algorithms,
- $encryption_algorithms_server_to_client, $mac_algorithms_server_to_client, $compression_algorithms_server_to_client,
- $encryption_algorithms_client_to_server, $mac_algorithms_client_to_server, $compression_algorithms_client_to_server;
-
- if (empty($str_kex_algorithms)) {
- $str_kex_algorithms = implode(',', $kex_algorithms);
- $str_server_host_key_algorithms = implode(',', $server_host_key_algorithms);
- $encryption_algorithms_server_to_client = $encryption_algorithms_client_to_server = implode(',', $encryption_algorithms);
- $mac_algorithms_server_to_client = $mac_algorithms_client_to_server = implode(',', $mac_algorithms);
- $compression_algorithms_server_to_client = $compression_algorithms_client_to_server = implode(',', $compression_algorithms);
- }
-
- $client_cookie = '';
- for ($i = 0; $i < 16; $i++)
- {
- $client_cookie.= chr(crypt_random(0, 255));
- }
-
- $response = $kexinit_payload_server;
- $this->_string_shift($response, 1); // skip past the message number (it should be SSH_MSG_KEXINIT)
- list(, $server_cookie) = unpack('a16', $this->_string_shift($response, 16));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->kex_algorithms = explode(',', $this->_string_shift($response, $temp['length']));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->server_host_key_algorithms = explode(',', $this->_string_shift($response, $temp['length']));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->encryption_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->encryption_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->mac_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->mac_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->compression_algorithms_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->compression_algorithms_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->languages_client_to_server = explode(',', $this->_string_shift($response, $temp['length']));
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->languages_server_to_client = explode(',', $this->_string_shift($response, $temp['length']));
-
- list(, $first_kex_packet_follows) = unpack('C', $this->_string_shift($response, 1));
- $first_kex_packet_follows = $first_kex_packet_follows != 0;
-
- // the sending of NET_SSH2_MSG_KEXINIT could go in one of two places. this is the second place.
- $kexinit_payload_client = pack('Ca*Na*Na*Na*Na*Na*Na*Na*Na*Na*Na*CN',
- NET_SSH2_MSG_KEXINIT, $client_cookie, strlen($str_kex_algorithms), $str_kex_algorithms,
- strlen($str_server_host_key_algorithms), $str_server_host_key_algorithms, strlen($encryption_algorithms_client_to_server),
- $encryption_algorithms_client_to_server, strlen($encryption_algorithms_server_to_client), $encryption_algorithms_server_to_client,
- strlen($mac_algorithms_client_to_server), $mac_algorithms_client_to_server, strlen($mac_algorithms_server_to_client),
- $mac_algorithms_server_to_client, strlen($compression_algorithms_client_to_server), $compression_algorithms_client_to_server,
- strlen($compression_algorithms_server_to_client), $compression_algorithms_server_to_client, 0, '', 0, '',
- 0, 0
- );
-
- if (!$this->_send_binary_packet($kexinit_payload_client))
- {
- return false;
- }
- // here ends the second place.
-
- // we need to decide upon the symmetric encryption algorithms before we do the diffie-hellman key exchange
- for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_server_to_client); $i++);
- if ($i == count($encryption_algorithms))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- // we don't initialize any crypto-objects, yet - we do that, later. for now, we need the lengths to make the
- // diffie-hellman key exchange as fast as possible
- $decrypt = $encryption_algorithms[$i];
- switch ($decrypt)
- {
- case '3des-cbc':
- $decryptKeyLength = 24; // eg. 192 / 8
- break;
- case 'aes256-cbc':
- $decryptKeyLength = 32; // eg. 256 / 8
- break;
- case 'aes192-cbc':
- $decryptKeyLength = 24; // eg. 192 / 8
- break;
- case 'aes128-cbc':
- $decryptKeyLength = 16; // eg. 128 / 8
- break;
- case 'arcfour':
- $decryptKeyLength = 16; // eg. 128 / 8
- break;
- case 'none';
- $decryptKeyLength = 0;
- }
-
- for ($i = 0; $i < count($encryption_algorithms) && !in_array($encryption_algorithms[$i], $this->encryption_algorithms_client_to_server); $i++);
- if ($i == count($encryption_algorithms))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- $encrypt = $encryption_algorithms[$i];
- switch ($encrypt)
- {
- case '3des-cbc':
- $encryptKeyLength = 24;
- break;
- case 'aes256-cbc':
- $encryptKeyLength = 32;
- break;
- case 'aes192-cbc':
- $encryptKeyLength = 24;
- break;
- case 'aes128-cbc':
- $encryptKeyLength = 16;
- break;
- case 'arcfour':
- $encryptKeyLength = 16;
- break;
- case 'none';
- $encryptKeyLength = 0;
- }
-
- $keyLength = $decryptKeyLength > $encryptKeyLength ? $decryptKeyLength : $encryptKeyLength;
-
- // through diffie-hellman key exchange a symmetric key is obtained
- for ($i = 0; $i < count($kex_algorithms) && !in_array($kex_algorithms[$i], $this->kex_algorithms); $i++);
- if ($i == count($kex_algorithms))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- switch ($kex_algorithms[$i])
- {
- // see http://tools.ietf.org/html/rfc2409#section-6.2 and
- // http://tools.ietf.org/html/rfc2412, appendex E
- case 'diffie-hellman-group1-sha1':
- $p = pack('N32', 0xFFFFFFFF, 0xFFFFFFFF, 0xC90FDAA2, 0x2168C234, 0xC4C6628B, 0x80DC1CD1,
- 0x29024E08, 0x8A67CC74, 0x020BBEA6, 0x3B139B22, 0x514A0879, 0x8E3404DD,
- 0xEF9519B3, 0xCD3A431B, 0x302B0A6D, 0xF25F1437, 0x4FE1356D, 0x6D51C245,
- 0xE485B576, 0x625E7EC6, 0xF44C42E9, 0xA637ED6B, 0x0BFF5CB6, 0xF406B7ED,
- 0xEE386BFB, 0x5A899FA5, 0xAE9F2411, 0x7C4B1FE6, 0x49286651, 0xECE65381,
- 0xFFFFFFFF, 0xFFFFFFFF);
- $keyLength = $keyLength < 160 ? $keyLength : 160;
- $hash = 'sha1';
- break;
- // see http://tools.ietf.org/html/rfc3526#section-3
- case 'diffie-hellman-group14-sha1':
- $p = pack('N64', 0xFFFFFFFF, 0xFFFFFFFF, 0xC90FDAA2, 0x2168C234, 0xC4C6628B, 0x80DC1CD1,
- 0x29024E08, 0x8A67CC74, 0x020BBEA6, 0x3B139B22, 0x514A0879, 0x8E3404DD,
- 0xEF9519B3, 0xCD3A431B, 0x302B0A6D, 0xF25F1437, 0x4FE1356D, 0x6D51C245,
- 0xE485B576, 0x625E7EC6, 0xF44C42E9, 0xA637ED6B, 0x0BFF5CB6, 0xF406B7ED,
- 0xEE386BFB, 0x5A899FA5, 0xAE9F2411, 0x7C4B1FE6, 0x49286651, 0xECE45B3D,
- 0xC2007CB8, 0xA163BF05, 0x98DA4836, 0x1C55D39A, 0x69163FA8, 0xFD24CF5F,
- 0x83655D23, 0xDCA3AD96, 0x1C62F356, 0x208552BB, 0x9ED52907, 0x7096966D,
- 0x670C354E, 0x4ABC9804, 0xF1746C08, 0xCA18217C, 0x32905E46, 0x2E36CE3B,
- 0xE39E772C, 0x180E8603, 0x9B2783A2, 0xEC07A28F, 0xB5C55DF0, 0x6F4C52C9,
- 0xDE2BCBF6, 0x95581718, 0x3995497C, 0xEA956AE5, 0x15D22618, 0x98FA0510,
- 0x15728E5A, 0x8AACAA68, 0xFFFFFFFF, 0xFFFFFFFF);
- $keyLength = $keyLength < 160 ? $keyLength : 160;
- $hash = 'sha1';
- }
-
- $p = new biginteger($p, 256);
- //$q = $p->bitwise_right_shift(1);
-
- /* To increase the speed of the key exchange, both client and server may
- reduce the size of their private exponents. It should be at least
- twice as long as the key material that is generated from the shared
- secret. For more details, see the paper by van Oorschot and Wiener
- [VAN-OORSCHOT].
-
- -- http://tools.ietf.org/html/rfc4419#section-6.2 */
- $q = new biginteger(1);
- $q = $q->bitwise_left_shift(2 * $keyLength);
- $q = $q->subtract(new biginteger(1));
-
- $g = new biginteger(2);
- $x = new biginteger();
- $x = $x->random(new biginteger(1), $q, 'crypt_random');
- $e = $g->mod_pow($x, $p);
-
- $eBytes = $e->to_bytes(true);
- $data = pack('CNa*', NET_SSH2_MSG_KEXDH_INIT, strlen($eBytes), $eBytes);
-
- if (!$this->_send_binary_packet($data))
- {
- return false;
- }
-
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- if ($type != NET_SSH2_MSG_KEXDH_REPLY)
- {
- return false;
- }
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $this->server_public_host_key = $server_public_host_key = $this->_string_shift($response, $temp['length']);
-
- $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- $public_key_format = $this->_string_shift($server_public_host_key, $temp['length']);
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $fBytes = $this->_string_shift($response, $temp['length']);
- $f = new biginteger($fBytes, -256);
-
- $temp = unpack('Nlength', $this->_string_shift($response, 4));
- $signature = $this->_string_shift($response, $temp['length']);
-
- $temp = unpack('Nlength', $this->_string_shift($signature, 4));
- $signature_format = $this->_string_shift($signature, $temp['length']);
-
- $key = $f->mod_pow($x, $p);
- $keyBytes = $key->to_bytes(true);
-
- $source = pack('Na*Na*Na*Na*Na*Na*Na*Na*',
- strlen($this->identifier), $this->identifier, strlen($this->server_identifier), $this->server_identifier,
- strlen($kexinit_payload_client), $kexinit_payload_client, strlen($kexinit_payload_server),
- $kexinit_payload_server, strlen($this->server_public_host_key), $this->server_public_host_key, strlen($eBytes),
- $eBytes, strlen($fBytes), $fBytes, strlen($keyBytes), $keyBytes
- );
-
- $source = pack('H*', $hash($source));
-
- if ($this->session_id === false)
- {
- $this->session_id = $source;
- }
-
- // if you the server's assymetric key matches the one you have on file, then you should be able to decrypt the
- // "signature" and get something that should equal the "exchange hash", as defined in the SSH-2 specs.
- // here, we just check to see if the "signature" is good. you can verify whether or not the assymetric key is good,
- // later, with the getServerHostKeyAlgorithm() function
- for ($i = 0; $i < count($server_host_key_algorithms) && !in_array($server_host_key_algorithms[$i], $this->server_host_key_algorithms); $i++);
- if ($i == count($server_host_key_algorithms))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- if ($public_key_format != $server_host_key_algorithms[$i] || $signature_format != $server_host_key_algorithms[$i])
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- switch ($server_host_key_algorithms[$i])
- {
- case 'ssh-dss':
- $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- $p = new biginteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
-
- $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- $q = new biginteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
-
- $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- $g = new biginteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
-
- $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- $y = new biginteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
-
- /* The value for 'dss_signature_blob' is encoded as a string containing
- r, followed by s (which are 160-bit integers, without lengths or
- padding, unsigned, and in network byte order). */
- $temp = unpack('Nlength', $this->_string_shift($signature, 4));
- if ($temp['length'] != 40)
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- $r = new biginteger($this->_string_shift($signature, 20), 256);
- $s = new biginteger($this->_string_shift($signature, 20), 256);
-
- if ($r->compare($q) >= 0 || $s->compare($q) >= 0)
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- $w = $s->mod_inverse($q);
-
- $u1 = $w->multiply(new biginteger(sha1($source), 16));
- list(, $u1) = $u1->divide($q);
-
- $u2 = $w->multiply($r);
- list(, $u2) = $u2->divide($q);
-
- $g = $g->mod_pow($u1, $p);
- $y = $y->mod_pow($u2, $p);
-
- $v = $g->multiply($y);
- list(, $v) = $v->divide($p);
- list(, $v) = $v->divide($q);
-
- if ($v->compare($r) != 0)
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
- }
-
- break;
- case 'ssh-rsa':
- $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- $e = new biginteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
-
- $temp = unpack('Nlength', $this->_string_shift($server_public_host_key, 4));
- $n = new biginteger($this->_string_shift($server_public_host_key, $temp['length']), -256);
- $nLength = $temp['length'];
-
- $temp = unpack('Nlength', $this->_string_shift($signature, 4));
- $s = new biginteger($this->_string_shift($signature, $temp['length']), 256);
-
- // validate an RSA signature per "8.2 RSASSA-PKCS1-v1_5", "5.2.2 RSAVP1", and "9.1 EMSA-PSS" in the
- // following URL:
- // ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-1/pkcs-1v2-1.pdf
-
- // also, see SSHRSA.c (rsa2_verifysig) in PuTTy's source.
-
- if ($s->compare(new biginteger()) < 0 || $s->compare($n->subtract(new biginteger(1))) > 0)
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- $s = $s->mod_pow($e, $n);
- $s = $s->to_bytes();
-
- $h = pack('N4H*', 0x00302130, 0x0906052B, 0x0E03021A, 0x05000414, sha1($source));
- $h = chr(0x01) . str_repeat(chr(0xFF), $nLength - 3 - strlen($h)) . $h;
-
- if ($s != $h)
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_HOST_KEY_NOT_VERIFIABLE);
- }
- }
-
- $packet = pack('C',
- NET_SSH2_MSG_NEWKEYS
- );
-
- if (!$this->_send_binary_packet($packet))
- {
- return false;
- }
-
- $response = $this->_get_binary_packet();
-
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- if ($type != NET_SSH2_MSG_NEWKEYS)
- {
- return false;
- }
-
- switch ($encrypt)
- {
- case '3des-cbc':
- $this->encrypt = new tripledes();
- // $this->encrypt_block_size = 64 / 8 == the default
- break;
- case 'aes256-cbc':
- $this->encrypt = new aes();
- $this->encrypt_block_size = 16; // eg. 128 / 8
- break;
- case 'aes192-cbc':
- $this->encrypt = new aes();
- $this->encrypt_block_size = 16;
- break;
- case 'aes128-cbc':
- $this->encrypt = new aes();
- $this->encrypt_block_size = 16;
- break;
- case 'arcfour':
- $this->encrypt = new rc4();
- }
-
- switch ($decrypt)
- {
- case '3des-cbc':
- $this->decrypt = new tripledes();
- break;
- case 'aes256-cbc':
- $this->decrypt = new aes();
- $this->decrypt_block_size = 16;
- break;
- case 'aes192-cbc':
- $this->decrypt = new aes();
- $this->decrypt_block_size = 16;
- break;
- case 'aes128-cbc':
- $this->decrypt = new aes();
- $this->decrypt_block_size = 16;
- break;
- case 'arcfour':
- $this->decrypt = new rc4();
- }
-
- $keyBytes = pack('Na*', strlen($keyBytes), $keyBytes);
-
- if ($this->encrypt)
- {
- $this->encrypt->enable_continuous_buffer();
- $this->encrypt->disable_padding();
-
- $iv = pack('H*', $hash($keyBytes . $source . 'A' . $this->session_id));
- while ($this->encrypt_block_size > strlen($iv)) {
- $iv.= pack('H*', $hash($keyBytes . $source . $iv));
- }
- $this->encrypt->setIV(substr($iv, 0, $this->encrypt_block_size));
-
- $key = pack('H*', $hash($keyBytes . $source . 'C' . $this->session_id));
- while ($encryptKeyLength > strlen($key))
- {
- $key.= pack('H*', $hash($keyBytes . $source . $key));
- }
- $this->encrypt->set_key(substr($key, 0, $encryptKeyLength));
- }
-
- if ($this->decrypt)
- {
- $this->decrypt->enable_continuous_buffer();
- $this->decrypt->disable_padding();
-
- $iv = pack('H*', $hash($keyBytes . $source . 'B' . $this->session_id));
- while ($this->decrypt_block_size > strlen($iv))
- {
- $iv.= pack('H*', $hash($keyBytes . $source . $iv));
- }
- $this->decrypt->setIV(substr($iv, 0, $this->decrypt_block_size));
-
- $key = pack('H*', $hash($keyBytes . $source . 'D' . $this->session_id));
- while ($decryptKeyLength > strlen($key))
- {
- $key.= pack('H*', $hash($keyBytes . $source . $key));
- }
- $this->decrypt->set_key(substr($key, 0, $decryptKeyLength));
- }
-
- for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_client_to_server); $i++);
- if ($i == count($mac_algorithms))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- $createKeyLength = 0; // ie. $mac_algorithms[$i] == 'none'
- switch ($mac_algorithms[$i])
- {
- case 'hmac-sha1':
- $this->hmac_create = new hash('sha1');
- $createKeyLength = 20;
- break;
- case 'hmac-sha1-96':
- $this->hmac_create = new hash('sha1-96');
- $createKeyLength = 20;
- break;
- case 'hmac-md5':
- $this->hmac_create = new hash('md5');
- $createKeyLength = 16;
- break;
- case 'hmac-md5-96':
- $this->hmac_create = new hash('md5-96');
- $createKeyLength = 16;
- }
-
- for ($i = 0; $i < count($mac_algorithms) && !in_array($mac_algorithms[$i], $this->mac_algorithms_server_to_client); $i++);
- if ($i == count($mac_algorithms))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
-
- $checkKeyLength = 0;
- $this->hmac_size = 0;
- switch ($mac_algorithms[$i])
- {
- case 'hmac-sha1':
- $this->hmac_check = new hash('sha1');
- $checkKeyLength = 20;
- $this->hmac_size = 20;
- break;
- case 'hmac-sha1-96':
- $this->hmac_check = new hash('sha1-96');
- $checkKeyLength = 20;
- $this->hmac_size = 12;
- break;
- case 'hmac-md5':
- $this->hmac_check = new hash('md5');
- $checkKeyLength = 16;
- $this->hmac_size = 16;
- break;
- case 'hmac-md5-96':
- $this->hmac_check = new hash('md5-96');
- $checkKeyLength = 16;
- $this->hmac_size = 12;
- }
-
- $key = pack('H*', $hash($keyBytes . $source . 'E' . $this->session_id));
- while ($createKeyLength > strlen($key))
- {
- $key.= pack('H*', $hash($keyBytes . $source . $key));
- }
- $this->hmac_create->set_key(substr($key, 0, $createKeyLength));
-
- $key = pack('H*', $hash($keyBytes . $source . 'F' . $this->session_id));
- while ($checkKeyLength > strlen($key))
- {
- $key.= pack('H*', $hash($keyBytes . $source . $key));
- }
- $this->hmac_check->set_key(substr($key, 0, $checkKeyLength));
-
- for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_server_to_client); $i++);
- if ($i == count($compression_algorithms))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
- $this->decompress = $compression_algorithms[$i] == 'zlib';
-
- for ($i = 0; $i < count($compression_algorithms) && !in_array($compression_algorithms[$i], $this->compression_algorithms_client_to_server); $i++);
- if ($i == count($compression_algorithms))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_KEY_EXCHANGE_FAILED);
- }
- $this->compress = $compression_algorithms[$i] == 'zlib';
-
- return true;
- }
-
- /**
- * Login
- *
- * @param String $username
- * @param optional String $password
- * @return Boolean
- * @access public
- * @internal It might be worthwhile, at some point, to protect against {@link http://tools.ietf.org/html/rfc4251#section-9.3.9 traffic analysis}
- by sending dummy SSH_MSG_IGNORE messages.
- */
- function login($username, $password = '')
- {
- if (!($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR))
- {
- return false;
- }
-
- $packet = pack('CNa*',
- NET_SSH2_MSG_SERVICE_REQUEST, strlen('ssh-userauth'), 'ssh-userauth'
- );
-
- if (!$this->_send_binary_packet($packet))
- {
- return false;
- }
-
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- if ($type != NET_SSH2_MSG_SERVICE_ACCEPT)
- {
- return false;
- }
-
- // publickey authentication is required, per the SSH-2 specs, however, we don't support it.
- $utf8_password = utf8_encode($password);
- $packet = pack('CNa*Na*Na*CNa*',
- NET_SSH2_MSG_USERAUTH_REQUEST, strlen($username), $username, strlen('ssh-connection'), 'ssh-connection',
- strlen('password'), 'password', 0, strlen($utf8_password), $utf8_password
- );
-
- if (!$this->_send_binary_packet($packet))
- {
- return false;
- }
-
- // remove the username and password from the last logged packet
- if (defined('NET_SSH2_LOGGING'))
- {
- $packet = pack('CNa*Na*Na*CNa*',
- NET_SSH2_MSG_USERAUTH_REQUEST, strlen('username'), 'username', strlen('ssh-connection'), 'ssh-connection',
- strlen('password'), 'password', 0, strlen('password'), 'password'
- );
- $this->message_log[count($this->message_log) - 1] = $packet;
- }
-
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- switch ($type)
- {
- case NET_SSH2_MSG_USERAUTH_PASSWD_CHANGEREQ: // in theory, the password can be changed
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $this->debug_info.= "\r\n\r\nSSH_MSG_USERAUTH_PASSWD_CHANGEREQ:\r\n" . utf8_decode($this->_string_shift($response, $length));
- return $this->_disconnect(NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER);
- case NET_SSH2_MSG_USERAUTH_FAILURE:
- list(, $length) = unpack('Nlength', $this->_string_shift($response, 4));
- $this->debug_info.= "\r\n\r\nSSH_MSG_USERAUTH_FAILURE:\r\n" . $this->_string_shift($response, $length);
- return $this->_disconnect(NET_SSH2_DISCONNECT_AUTH_CANCELLED_BY_USER);
- case NET_SSH2_MSG_USERAUTH_SUCCESS:
- $this->bitmap |= NET_SSH2_MASK_LOGIN;
- return true;
- }
-
- return false;
- }
-
- /**
- * Execute Command
- *
- * @param String $command
- * @return String
- * @access public
- */
- function exec($command)
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- $client_channel = 0; // PuTTy uses 0x100
- // RFC4254 defines the window size as "bytes the other party can send before it must wait for the window to be
- // adjusted". 0x7FFFFFFF is, at 4GB, the max size. technically, it should probably be decremented, but, honestly,
- // if you're transfering more than 4GB, you probably shouldn't be using phpseclib, anyway.
- // see http://tools.ietf.org/html/rfc4254#section-5.2 for more info
- $window_size = 0x7FFFFFFF;
- // 0x8000 is the maximum max packet size, per http://tools.ietf.org/html/rfc4253#section-6.1, although since PuTTy
- // uses 0x4000, that's what will be used here, as well. 0x7FFFFFFF could be used, as well (i've not encountered
- // any problems, using it, myself), but that's not what the specs say, so whatever.
- $packet_size = 0x4000;
-
- $packet = pack('CNa*N3',
- NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', $client_channel, $window_size, $packet_size);
-
- if (!$this->_send_binary_packet($packet))
- {
- return false;
- }
-
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- switch ($type)
- {
- case NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
- $this->_string_shift($response, 4);
- list(, $server_channel) = unpack('N', $this->_string_shift($response, 4));
- break;
- case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE:
- return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- }
-
- $terminal_modes = pack('C', NET_SSH2_TTY_OP_END);
- $packet = pack('CNNa*CNa*N5a*',
- NET_SSH2_MSG_CHANNEL_REQUEST, $server_channel, strlen('pty-req'), 'pty-req', 1, strlen('vt100'), 'vt100',
- 80, 24, 0, 0, strlen($terminal_modes), $terminal_modes);
-
- if (!$this->_send_binary_packet($packet))
- {
- return false;
- }
-
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- switch ($type)
- {
- case NET_SSH2_MSG_CHANNEL_SUCCESS:
- break;
- case NET_SSH2_MSG_CHANNEL_FAILURE:
- default:
- return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- }
-
- $packet = pack('CNNa*CNa*',
- NET_SSH2_MSG_CHANNEL_REQUEST, $server_channel, strlen('exec'), 'exec', 1, strlen($command), $command);
- if (!$this->_send_binary_packet($packet))
- {
- return false;
- }
-
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- switch ($type)
- {
- case NET_SSH2_MSG_CHANNEL_SUCCESS:
- break;
- case NET_SSH2_MSG_CHANNEL_FAILURE:
- default:
- return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- }
-
- $output = '';
- while (true)
- {
- $temp = $this->_get_channel_packet();
- switch (true)
- {
- case $temp === true:
- return $output;
- case $temp === false:
- return false;
- default:
- $output.= $temp;
- }
- }
- }
-
- /**
- * Disconnect
- *
- * @access public
- */
- function disconnect()
- {
- $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- }
-
- /**
- * Destructor.
- *
- * Will be called, automatically, if you're supporting just PHP5. If you're supporting PHP4, you'll need to call
- * disconnect().
- *
- * @access public
- */
- function __destruct()
- {
- $this->disconnect();
- }
-
- /**
- * Gets Binary Packets
- *
- * See '6. Binary Packet Protocol' of rfc4253 for more info.
- *
- * @see ssh2::_send_binary_packet()
- * @return String
- * @access private
- */
- function _get_binary_packet()
- {
- if (feof($this->fsock))
- {
- return false;
- }
-
- $raw = fread($this->fsock, $this->decrypt_block_size);
-
- if ($this->decrypt !== false)
- {
- $raw = $this->decrypt->decrypt($raw);
- }
-
- $temp = unpack('Npacket_length/Cpadding_length', $this->_string_shift($raw, 5));
- $packet_length = $temp['packet_length'];
- $padding_length = $temp['padding_length'];
-
- $remaining_length = $packet_length + 4 - $this->decrypt_block_size;
- $buffer = '';
- while ($remaining_length > 0)
- {
- $temp = fread($this->fsock, $remaining_length);
- $buffer.= $temp;
- $remaining_length-= strlen($temp);
- }
- if (!empty($buffer))
- {
- $raw.= $this->decrypt !== false ? $this->decrypt->decrypt($buffer) : $buffer;
- $buffer = $temp = '';
- }
-
- $payload = $this->_string_shift($raw, $packet_length - $padding_length - 1);
- $padding = $this->_string_shift($raw, $padding_length); // should leave $raw empty
-
- if ($this->hmac_check !== false)
- {
- $hmac = fread($this->fsock, $this->hmac_size);
- if ($hmac != $this->hmac_check->create(pack('NNCa*', $this->get_seq_no, $packet_length, $padding_length, $payload . $padding)))
- {
- return false;
- }
- }
-
- //if ($this->decompress)
- //{
- // $payload = gzinflate(substr($payload, 2));
- //}
-
- $this->get_seq_no++;
-
- if (defined('NET_SSH2_LOGGING'))
- {
- $this->message_number_log[] = '<- ' . $this->message_numbers[ord($payload[0])];
- $this->message_log[] = $payload;
- }
-
- return $this->_filter($payload);
- }
-
- /**
- * Filter Binary Packets
- *
- * Because some binary packets need to be ignored...
- *
- * @see ssh2::_get_binary_packet()
- * @return String
- * @access private
- */
- function _filter($payload)
- {
- switch (ord($payload[0]))
- {
- case NET_SSH2_MSG_DISCONNECT:
- $this->_string_shift($payload, 1);
- list(, $reason_code, $length) = unpack('N2', $this->_string_shift($payload, 8));
- $this->debug_info.= "\r\n\r\nSSH_MSG_DISCONNECT:\r\n" . $this->disconnect_reasons[$reason_code] . "\r\n" . utf8_decode($this->_string_shift($payload, $temp['length']));
- $this->bitmask = 0;
- return false;
- case NET_SSH2_MSG_IGNORE:
- $payload = $this->_get_binary_packet();
- break;
- case NET_SSH2_MSG_DEBUG:
- $this->_string_shift($payload, 2);
- list(, $length) = unpack('N', $payload);
- $this->debug_info.= "\r\n\r\nSSH_MSG_DEBUG:\r\n" . utf8_decode($this->_string_shift($payload, $length));
- $payload = $this->_get_binary_packet();
- break;
- case NET_SSH2_MSG_UNIMPLEMENTED:
- return false;
- case NET_SSH2_MSG_KEXINIT:
- if ($this->session_id !== false)
- {
- if (!$this->_key_exchange($payload))
- {
- $this->bitmask = 0;
- return false;
- }
- $payload = $this->_get_binary_packet();
- }
- }
-
- // see http://tools.ietf.org/html/rfc4252#section-5.4; only called when the encryption has been activated and when we haven't already logged in
- if (($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR) && !($this->bitmap & NET_SSH2_MASK_LOGIN) && ord($payload[0]) == NET_SSH2_MSG_USERAUTH_BANNER)
- {
- $this->_string_shift($payload, 1);
- list(, $length) = unpack('N', $payload);
- $this->debug_info.= "\r\n\r\nSSH_MSG_USERAUTH_BANNER:\r\n" . utf8_decode($this->_string_shift($payload, $length));
- $payload = $this->_get_binary_packet();
- }
-
- // only called when we've already logged in
- if (($this->bitmap & NET_SSH2_MASK_CONSTRUCTOR) && ($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- switch (ord($payload[0]))
- {
- case NET_SSH2_MSG_GLOBAL_REQUEST: // see http://tools.ietf.org/html/rfc4254#section-4
- $this->_string_shift($payload, 1);
- list(, $length) = unpack('N', $payload);
- $this->debug_info.= "\r\n\r\nSSH_MSG_GLOBAL_REQUEST:\r\n" . utf8_decode($this->_string_shift($payload, $length));
-
- if (!$this->_send_binary_packet(pack('C', NET_SSH2_MSG_REQUEST_FAILURE)))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- }
-
- $payload = $this->_get_binary_packet();
- break;
- case NET_SSH2_MSG_CHANNEL_OPEN: // see http://tools.ietf.org/html/rfc4254#section-5.1
- $this->_string_shift($payload, 1);
- list(, $length) = unpack('N', $payload);
- $this->debug_info.= "\r\n\r\nSSH_MSG_CHANNEL_OPEN:\r\n" . utf8_decode($this->_string_shift($payload, $length));
-
- list(, $recipient_channel) = unpack('N', $this->_string_shift($payload, 4));
-
- $packet = pack('CN3a*Na*',
- NET_SSH2_MSG_REQUEST_FAILURE, $recipient_channel, NET_SSH2_OPEN_ADMINISTRATIVELY_PROHIBITED, 0, '', 0, '');
-
- if (!$this->_send_binary_packet($packet))
- {
- return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- }
-
- $payload = $this->_get_binary_packet();
- break;
- case NET_SSH2_MSG_CHANNEL_WINDOW_ADJUST:
- $payload = $this->_get_binary_packet();
- }
- }
-
- return $payload;
- }
-
- /**
- * Gets channel data
- *
- * Returns the data as a string if it's available and false if not.
- *
- * @return Mixed
- * @access private
- */
- function _get_channel_packet()
- {
- while (true)
- {
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- switch ($type)
- {
- case NET_SSH2_MSG_CHANNEL_DATA:
- $this->_string_shift($response, 4); // skip over server channel
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- return $this->_string_shift($response, $length);
- case NET_SSH2_MSG_CHANNEL_EXTENDED_DATA:
- $this->_string_shift($response, 4); // skip over server channel
- list(, $data_type_code, $length) = unpack('N2', $this->_string_shift($response, 8));
- $data = $this->_string_shift($response, $length);
- switch ($data_type_code)
- {
- case NET_SSH2_EXTENDED_DATA_STDERR:
- $this->debug_info.= "\r\n\r\nSSH_MSG_CHANNEL_EXTENDED_DATA (SSH_EXTENDED_DATA_STDERR):\r\n" . $data;
- }
- break;
- case NET_SSH2_MSG_CHANNEL_REQUEST:
- $this->_string_shift($response, 4); // skip over server channel
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $value = $this->_string_shift($response, $length);
- switch ($value)
- {
- case 'exit-signal':
- $this->_string_shift($response, 1);
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $this->debug_info.= "\r\n\r\nSSH_MSG_CHANNEL_REQUEST (exit-signal):\r\nSIG" . $this->_string_shift($response, $length);
- $this->_string_shift($response, 1);
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $this->debug_info.= "\r\n" . $this->_string_shift($response, $length);
- case 'exit-status':
- default:
- // "Some systems may not implement signals, in which case they SHOULD ignore this message."
- // -- http://tools.ietf.org/html/rfc4254#section-6.9
- //break 2;
- break;
- }
- break;
- case NET_SSH2_MSG_CHANNEL_CLOSE:
- $this->_send_binary_packet(pack('CN', NET_SSH2_MSG_CHANNEL_CLOSE, $server_channel));
- return true;
- case NET_SSH2_MSG_CHANNEL_EOF:
- break;
- default:
- return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- }
- }
- }
-
- /**
- * Sends Binary Packets
- *
- * See '6. Binary Packet Protocol' of rfc4253 for more info.
- *
- * @param String $data
- * @see ssh2::_get_binary_packet()
- * @return Boolean
- * @access private
- */
- function _send_binary_packet($data)
- {
- if (feof($this->fsock))
- {
- return false;
- }
-
- if (defined('NET_SSH2_LOGGING'))
- {
- $this->message_number_log[] = '-> ' . $this->message_numbers[ord($data[0])];
- $this->message_log[] = $data;
- }
-
- //if ($this->compress)
- //{
- // // the -4 removes the checksum:
- // // http://php.net/function.gzcompress#57710
- // $data = substr(gzcompress($data), 0, -4);
- //}
-
- // 4 (packet length) + 1 (padding length) + 4 (minimal padding amount) == 9
- $packet_length = strlen($data) + 9;
- // round up to the nearest $this->encrypt_block_size
- $packet_length+= (($this->encrypt_block_size - 1) * $packet_length) % $this->encrypt_block_size;
- // subtracting strlen($data) is obvious - subtracting 5 is necessary because of packet_length and padding_length
- $padding_length = $packet_length - strlen($data) - 5;
-
- $padding = '';
- for ($i = 0; $i < $padding_length; $i++)
- {
- $padding.= chr(crypt_random(0, 255));
- }
-
- // we subtract 4 from packet_length because the packet_length field isn't supposed to include itself
- $packet = pack('NCa*', $packet_length - 4, $padding_length, $data . $padding);
-
- $hmac = $this->hmac_create !== false ? $this->hmac_create->create(pack('Na*', $this->send_seq_no, $packet)) : '';
- $this->send_seq_no++;
-
- if ($this->encrypt !== false)
- {
- $packet = $this->encrypt->encrypt($packet);
- }
-
- $packet.= $hmac;
-
- return strlen($packet) == fputs($this->fsock, $packet);
- }
-
- /**
- * Disconnect
- *
- * @param Integer $reason
- * @return Boolean
- * @access private
- */
- function _disconnect($reason)
- {
- if ($this->bitmap)
- {
- $data = pack('CNNa*Na*', NET_SSH2_MSG_DISCONNECT, $reason, 0, '', 0, '');
- $this->_send_binary_packet($data);
- $this->bitmap = 0;
- fclose($this->fsock);
- return false;
- }
- }
-
- /**
- * String Shift
- *
- * Inspired by array_shift
- *
- * @param String $string
- * @param optional Integer $index
- * @return String
- * @access private
- */
- function _string_shift(&$string, $index = 1)
- {
- $substr = substr($string, 0, $index);
- $string = substr($string, $index);
- return $substr;
- }
-
- /**
- * Define Array
- *
- * Takes any number of arrays whose indices are integers and whose values are strings and defines a bunch of
- * named constants from it, using the value as the name of the constant and the index as the value of the constant.
- * If any of the constants that would be defined already exists, none of the constants will be defined.
- *
- * @param Array $array
- * @access private
- */
- function _define_array()
- {
- $args = func_get_args();
- foreach ($args as $arg)
- {
- foreach ($arg as $key=>$value)
- {
- if (!defined($value))
- {
- define($value, $key);
- }
- else
- {
- break 2;
- }
- }
- }
- }
-
- /**
- * Returns a log of the packets that have been sent and received.
- *
- * $type can be either NET_SSH2_LOG_SIMPLE or NET_SSH2_LOG_COMPLEX. Enable by defining NET_SSH2_LOGGING.
- *
- * @param Integer $type
- * @access public
- * @return String or Array
- */
- function get_log($type = NET_SSH2_LOG_COMPLEX)
- {
- if ($type == NET_SSH2_LOG_SIMPLE)
- {
- return $this->message_number_log;
- }
-
- static $boundary = ':', $long_width = 65, $short_width = 15;
-
- $output = '';
- for ($i = 0; $i < count($this->message_log); $i++)
- {
- $output.= $this->message_number_log[$i] . "\r\n";
- $current_log = $this->message_log[$i];
- do
- {
- $fragment = $this->_string_shift($current_log, $short_width);
- $hex = substr(
- preg_replace(
- '#(.)#es',
- '"' . $boundary . '" . str_pad(dechex(ord(substr("\\1", -1))), 2, "0", STR_PAD_LEFT)',
- $fragment),
- strlen($boundary)
- );
- // replace non ASCII printable characters with dots
- // http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters
- $raw = preg_replace('#[^\x20-\x7E]#', '.', $fragment);
- $output.= str_pad($hex, $long_width - $short_width, ' ') . $raw . "\r\n";
- }
- while (!empty($current_log));
- $output.= "\r\n";
- }
-
- return $output;
- }
-
- /**
- * Returns Debug Information
- *
- * If any debug information is sent by the server, this function can be used to access it.
- *
- * @return String
- * @access public
- */
- function get_debug_info()
- {
- return $this->debug_info;
- }
-
- /**
- * Return the server identification.
- *
- * @return String
- * @access public
- */
- function get_server_identification()
- {
- return $this->server_identifier;
- }
-
- /**
- * Return a list of the key exchange algorithms the server supports.
- *
- * @return Array
- * @access public
- */
- function get_kex_algorithms()
- {
- return $this->kex_algorithms;
- }
-
- /**
- * Return a list of the host key (public key) algorithms the server supports.
- *
- * @return Array
- * @access public
- */
- function get_server_host_key_algorithms()
- {
- return $this->server_host_key_algorithms;
- }
-
- /**
- * Return a list of the (symmetric key) encryption algorithms the server supports, when receiving stuff from the client.
- *
- * @return Array
- * @access public
- */
- function get_encryption_algorithms_client_to_server()
- {
- return $this->encryption_algorithms_client_to_server;
- }
-
- /**
- * Return a list of the (symmetric key) encryption algorithms the server supports, when sending stuff to the client.
- *
- * @return Array
- * @access public
- */
- function get_encryption_algorithms_server_to_client()
- {
- return $this->encryption_algorithms_server_to_client;
- }
-
- /**
- * Return a list of the MAC algorithms the server supports, when receiving stuff from the client.
- *
- * @return Array
- * @access public
- */
- function get_mac_algorithms_client_to_server()
- {
- return $this->mac_algorithms_client_to_server;
- }
-
- /**
- * Return a list of the MAC algorithms the server supports, when sending stuff to the client.
- *
- * @return Array
- * @access public
- */
- function get_mac_algorithms_server_to_client()
- {
- return $this->mac_algorithms_server_to_client;
- }
-
- /**
- * Return a list of the compression algorithms the server supports, when receiving stuff from the client.
- *
- * @return Array
- * @access public
- */
- function get_compression_algorithms_client_to_server()
- {
- return $this->compression_algorithms_client_to_server;
- }
-
- /**
- * Return a list of the compression algorithms the server supports, when sending stuff to the client.
- *
- * @return Array
- * @access public
- */
- function get_compression_algorithms_server_to_client()
- {
- return $this->compression_algorithms_server_to_client;
- }
-
- /**
- * Return a list of the languages the server supports, when sending stuff to the client.
- *
- * @return Array
- * @access public
- */
- function get_languages_server_to_client()
- {
- return $this->languages_server_to_client;
- }
-
- /**
- * Return a list of the languages the server supports, when receiving stuff from the client.
- *
- * @return Array
- * @access public
- */
- function get_languages_client_to_server()
- {
- return $this->languages_client_to_server;
- }
-
- /**
- * Returns the server public host key.
- *
- * Caching this the first time you connect to a server and checking the result on subsequent connections
- * is recommended.
- *
- * @return Array
- * @access public
- */
- function get_server_public_host_key()
- {
- return $this->server_public_host_key;
- }
-}
-
-/**
- * Pure-PHP implementation of SFTP.
- *
- * @author Jim Wigginton <terrafrost@php.net>
- * @version 0.1.0
- * @access public
- * @package sftp
- */
-class ssh2_sftp extends ssh2
-{
- /**
- * Packet Types
- *
- * @see ssh2_sftp::__construct()
- * @var Array
- * @access private
- */
- var $packet_types = array();
-
- /**
- * Status Codes
- *
- * @see ssh2_sftp::__construct()
- * @var Array
- * @access private
- */
- var $status_codes = array();
-
- /**
- * The Window Size
- *
- * Bytes the other party can send before it must wait for the window to be adjusted (0x7FFFFFFF = 4GB)
- *
- * @var Integer
- * @see ssh2::exec()
- * @access private
- */
- var $window_size = 0x7FFFFFFF;
-
- /**
- * The Packet Size
- *
- * Maximum max packet size
- *
- * @var Integer
- * @see ssh2::exec()
- * @access private
- */
- var $packet_size = 0x4000;
-
- /**
- * The Client Channel
- *
- * Net_SSH2::exec() uses 0
- *
- * @var Integer
- * @see ssh2::exec()
- * @access private
- */
- var $client_channel = 1;
-
- /**
- * The Server Channel
- *
- * @var Integer
- * @see ssh2_sftp::_init_channel()
- * @access private
- */
- var $server_channel = -1;
-
- /**
- * The Request ID
- *
- * The request ID exists in the off chance that a packet is sent out-of-order. Of course, this library doesn't support
- * concurrent actions, so it's somewhat academic, here.
- *
- * @var Integer
- * @see ssh2_sftp::_send_sftp_packet()
- * @access private
- */
- var $request_id = false;
-
- /**
- * The Packet Type
- *
- * The request ID exists in the off chance that a packet is sent out-of-order. Of course, this library doesn't support
- * concurrent actions, so it's somewhat academic, here.
- *
- * @var Integer
- * @see ssh2_sftp::_send_sftp_packet()
- * @access private
- */
- var $packet_type = -1;
-
- /**
- * Extensions supported by the server
- *
- * @var Array
- * @see ssh2_sftp::_init_channel()
- * @access private
- */
- var $extensions = array();
-
- /**
- * Server SFTP version
- *
- * @var Integer
- * @see ssh2_sftp::_init_channel()
- * @access private
- */
- var $version;
-
- /**
- * Current working directory
- *
- * @var String
- * @see ssh2_sftp::_realpath()
- * @see ssh2_sftp::chdir()
- * @access private
- */
- var $pwd = false;
-
- /**
- * Packet Type Log
- *
- * @see ssh2_sftp::get_log()
- * @var Array
- * @access private
- */
- var $packet_type_log = array();
-
- /**
- * Packet Log
- *
- * @see ssh2_sftp::get_log()
- * @var Array
- * @access private
- */
- var $packet_log = array();
-
- /**
- * Default Constructor.
- *
- * Connects to an SFTP server
- *
- * @param String $host
- * @param optional Integer $port
- * @param optional Integer $timeout
- * @return sftp
- * @access public
- */
- function __construct($host, $port = 22, $timeout = 10)
- {
- parent::__construct($host, $port, $timeout);
- $this->packet_types = array(
- 1 => 'NET_SFTP_INIT',
- 2 => 'NET_SFTP_VERSION',
- /* the format of SSH_FXP_OPEN changed between SFTPv4 and SFTPv5+:
- SFTPv5+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.1
- pre-SFTPv5 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3 */
- 3 => 'NET_SFTP_OPEN',
- 4 => 'NET_SFTP_CLOSE',
- 5 => 'NET_SFTP_READ',
- 6 => 'NET_SFTP_WRITE',
- 8 => 'NET_SFTP_FSTAT',
- 9 => 'NET_SFTP_SETSTAT',
- 11 => 'NET_SFTP_OPENDIR',
- 12 => 'NET_SFTP_READDIR',
- 13 => 'NET_SFTP_REMOVE',
- 14 => 'NET_SFTP_MKDIR',
- 15 => 'NET_SFTP_RMDIR',
- 16 => 'NET_SFTP_REALPATH',
- 17 => 'NET_SFTP_STAT',
- /* the format of SSH_FXP_RENAME changed between SFTPv4 and SFTPv5+:
- SFTPv5+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
- pre-SFTPv5 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.5 */
- 18 => 'NET_SFTP_RENAME',
-
- 101=> 'NET_SFTP_STATUS',
- 102=> 'NET_SFTP_HANDLE',
- /* the format of SSH_FXP_NAME changed between SFTPv3 and SFTPv4+:
- SFTPv4+: http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.4
- pre-SFTPv4 : http://tools.ietf.org/html/draft-ietf-secsh-filexfer-02#section-7 */
- 103=> 'NET_SFTP_DATA',
- 104=> 'NET_SFTP_NAME',
- 105=> 'NET_SFTP_ATTRS',
-
- 200=> 'NET_SFTP_EXTENDED'
- );
- $this->status_codes = array(
- 0 => 'NET_SFTP_STATUS_OK',
- 1 => 'NET_SFTP_STATUS_EOF'
- );
- // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-7.1
- // the order, in this case, matters quite a lot - see ssh2_sftp::_parse_attributes() to understand why
- $this->attributes = array(
- 0x00000001 => 'NET_SFTP_ATTR_SIZE',
- 0x00000002 => 'NET_SFTP_ATTR_UIDGID', // defined in SFTPv3, removed in SFTPv4+
- 0x00000004 => 'NET_SFTP_ATTR_PERMISSIONS',
- 0x00000008 => 'NET_SFTP_ATTR_ACCESSTIME',
- 0x80000000 => 'NET_SFTP_ATTR_EXTENDED'
- );
- // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-04#section-6.3
- // the flag definitions change somewhat in SFTPv5+. if SFTPv5+ support is added to this library, maybe name
- // the array for that $this->open5_flags and similarily alter the constant names.
- $this->open_flags = array(
- 0x00000001 => 'NET_SFTP_OPEN_READ',
- 0x00000002 => 'NET_SFTP_OPEN_WRITE',
- 0x00000008 => 'NET_SFTP_OPEN_CREATE'
- );
- $this->_define_array(
- $this->packet_types,
- $this->status_codes,
- $this->attributes,
- $this->open_flags
- );
- }
-
- /**
- * Login
- *
- * @param String $username
- * @param optional String $password
- * @return Boolean
- * @access public
- */
- function login($username, $password = '')
- {
- if (!parent::login($username, $password))
- {
- return false;
- }
-
- $packet = pack('CNa*N3',
- NET_SSH2_MSG_CHANNEL_OPEN, strlen('session'), 'session', $this->client_channel, $this->window_size, $this->packet_size);
-
- if (!$this->_send_binary_packet($packet))
- {
- return false;
- }
-
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- switch ($type)
- {
- case NET_SSH2_MSG_CHANNEL_OPEN_CONFIRMATION:
- $this->_string_shift($response, 4);
- list(, $this->server_channel) = unpack('N', $this->_string_shift($response, 4));
- break;
- case NET_SSH2_MSG_CHANNEL_OPEN_FAILURE:
- return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- }
-
- $packet = pack('CNNa*CNa*',
- NET_SSH2_MSG_CHANNEL_REQUEST, $this->server_channel, strlen('subsystem'), 'subsystem', 1, strlen('sftp'), 'sftp');
- if (!$this->_send_binary_packet($packet))
- {
- return false;
- }
-
- $response = $this->_get_binary_packet();
- if ($response === false)
- {
- return false;
- }
-
- list(, $type) = unpack('C', $this->_string_shift($response, 1));
-
- switch ($type)
- {
- case NET_SSH2_MSG_CHANNEL_SUCCESS:
- break;
- case NET_SSH2_MSG_CHANNEL_FAILURE:
- default:
- return $this->_disconnect(NET_SSH2_DISCONNECT_BY_APPLICATION);
- }
-
- if (!$this->_send_sftp_packet(NET_SFTP_INIT, "\0\0\0\3"))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_VERSION)
- {
- return false;
- }
-
- list(, $this->version) = unpack('N', $this->_string_shift($response, 4));
- while (!empty($response))
- {
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $key = $this->_string_shift($response, $length);
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $value = $this->_string_shift($response, $length);
- $this->extensions[$key] = $value;
- }
-
- /*
- SFTPv4+ defines a 'newline' extension. SFTPv3 seems to have unofficial support for it via 'newline@vandyke.com',
- however, I'm not sure what 'newline@vandyke.com' is supposed to do (the fact that it's unofficial means that it's
- not in the official SFTPv3 specs) and 'newline@vandyke.com' / 'newline' are likely not drop-in substitutes for
- one another due to the fact that 'newline' comes with a SSH_FXF_TEXT bitmask whereas it seems unlikely that
- 'newline@vandyke.com' would.
- */
- /*
- if (isset($this->extensions['newline@vandyke.com']))
- {
- $this->extensions['newline'] = $this->extensions['newline@vandyke.com'];
- unset($this->extensions['newline@vandyke.com']);
- }
- */
-
- $this->request_id = 1;
-
- /*
- A Note on SFTPv4/5/6 support:
- <http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-5.1> states the following:
-
- "If the client wishes to interoperate with servers that support noncontiguous version
- numbers it SHOULD send '3'"
-
- Given that the server only sends its version number after the client has already done so, the above
- seems to be suggesting that v3 should be the default version. This makes sense given that v3 is the
- most popular.
-
- <http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-5.5> states the following;
-
- "If the server did not send the "versions" extension, or the version-from-list was not included, the
- server MAY send a status response describing the failure, but MUST then close the channel without
- processing any further requests."
-
- So what do you do if you have a client whose initial SSH_FXP_INIT packet says it implements v3 and
- a server whose initial SSH_FXP_VERSION reply says it implements v4 and only v4? If it only implements
- v4, the "versions" extension is likely not going to have been sent so version re-negotiation as discussed
- in draft-ietf-secsh-filexfer-13 would be quite impossible. As such, what sftp would do is close the
- channel and reopen it with a new and updated SSH_FXP_INIT packet.
- */
- if ($this->version != 3)
- {
- return false;
- }
-
- $this->pwd = $this->_realpath('.');
-
- return true;
- }
-
- /**
- * Returns the current directory name
- *
- * @return Mixed
- * @access public
- */
- function pwd()
- {
- return $this->pwd;
- }
-
- /**
- * Canonicalize the Server-Side Path Name
- *
- * SFTP doesn't provide a mechanism by which the current working directory can be changed, so we'll emulate it. Returns
- * the absolute (canonicalized) path. If $mode is set to NET_SFTP_CONFIRM_DIR (as opposed to NET_SFTP_CONFIRM_NONE,
- * which is what it is set to by default), false is returned if $dir is not a valid directory.
- *
- * @see ssh2_sftp::chdir()
- * @param String $dir
- * @param optional Integer $mode
- * @return Mixed
- * @access private
- */
- function _realpath($dir)
- {
- /*
- "This protocol represents file names as strings. File names are
- assumed to use the slash ('/') character as a directory separator.
-
- File names starting with a slash are "absolute", and are relative to
- the root of the file system. Names starting with any other character
- are relative to the user's default directory (home directory). Note
- that identifying the user is assumed to take place outside of this
- protocol."
-
- -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-6
- */
- $file = '';
- if ($this->pwd !== false)
- {
- // if the SFTP server returned the canonicalized path even for non-existant files this wouldn't be necessary
- // on OpenSSH it isn't necessary but on other SFTP servers it is. that and since the specs say nothing on
- // the subject, we'll go ahead and work around it with the following.
- if ($dir[strlen($dir) - 1] != '/')
- {
- $file = basename($dir);
- $dir = dirname($dir);
- }
-
- if ($dir == '.' || $dir == $this->pwd)
- {
- return $this->pwd . $file;
- }
-
- if ($dir[0] != '/')
- {
- $dir = $this->pwd . '/' . $dir;
- }
- // on the surface it seems like maybe resolving a path beginning with / is unnecessary, but such paths
- // can contain .'s and ..'s just like any other. we could parse those out as appropriate or we can let
- // the server do it. we'll do the latter.
- }
-
- /*
- that SSH_FXP_REALPATH returns SSH_FXP_NAME does not necessarily mean that anything actually exists at the
- specified path. generally speaking, no attributes are returned with this particular SSH_FXP_NAME packet
- regardless of whether or not a file actually exists. and in SFTPv3, the longname field and the filename
- field match for this particular SSH_FXP_NAME packet. for other SSH_FXP_NAME packets, this will likely
- not be the case, but for this one, it is.
- */
- // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.9
- if (!$this->_send_sftp_packet(NET_SFTP_REALPATH, pack('Na*', strlen($dir), $dir)))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- switch ($this->packet_type)
- {
- case NET_SFTP_NAME:
- // although SSH_FXP_NAME is implemented differently in SFTPv3 than it is in SFTPv4+, the following
- // should work on all SFTP versions since the only part of the SSH_FXP_NAME packet the following looks
- // at is the first part and that part is defined the same in SFTP versions 3 through 6.
- $this->_string_shift($response, 4); // skip over the count - it should be 1, anyway
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $realpath = $this->_string_shift($response, $length);
- break;
- case NET_SFTP_STATUS:
- // skip over the status code - hopefully the error message will give us all the info we need, anyway
- $this->_string_shift($response, 4);
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $this->debug_info.= "\r\n\r\nSSH_FXP_STATUS:\r\n" . $this->_string_shift($response, $length);
- return false;
- default:
- return false;
- }
-
- // if $this->pwd isn't set than the only thing $realpath could be is for '.', which is pretty much guaranteed to
- // be a bonafide directory
- return $realpath . '/' . $file;
- }
-
- /**
- * Changes the current directory
- *
- * @param String $dir
- * @return Boolean
- * @access public
- */
- function chdir($dir)
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- if ($dir[strlen($dir) - 1] != '/')
- {
- $dir.= '/';
- }
- $dir = $this->_realpath($dir);
-
- // confirm that $dir is, in fact, a valid directory
- if (!$this->_send_sftp_packet(NET_SFTP_OPENDIR, pack('Na*', strlen($dir), $dir)))
- {
- return false;
- }
-
- // see ssh2_sftp::nlist() for a more thorough explanation of the following
- $response = $this->_get_sftp_packet();
- switch ($this->packet_type)
- {
- case NET_SFTP_HANDLE:
- $handle = substr($response, 4);
- break;
- case NET_SFTP_STATUS:
- return false;
- default:
- return false;
- }
-
- if (!$this->_send_sftp_packet(NET_SFTP_CLOSE, pack('Na*', strlen($handle), $handle)))
- {
- return false;
- }
-
- $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- $this->pwd = $dir;
- return true;
- }
-
- /**
- * Returns a list of files in the given directory
- *
- * @param optional String $dir
- * @return Mixed
- * @access public
- */
- function nlist($dir = '.')
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- $dir = $this->_realpath($dir);
- if ($dir === false)
- {
- return false;
- }
-
- // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.2
- if (!$this->_send_sftp_packet(NET_SFTP_OPENDIR, pack('Na*', strlen($dir), $dir)))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- switch ($this->packet_type)
- {
- case NET_SFTP_HANDLE:
- // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-9.2
- // since 'handle' is the last field in the SSH_FXP_HANDLE packet, we'll just remove the first four bytes that
- // represent the length of the string and leave it at that
- $handle = substr($response, 4);
- break;
- case NET_SFTP_STATUS:
- // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
- return false;
- default:
- return false;
- }
-
- $contents = array();
- while (true)
- {
- // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.2
- // why multiple SSH_FXP_READDIR packets would be sent when the response to a single one can span arbitrarily many
- // SSH_MSG_CHANNEL_DATA messages is not known to me.
- if (!$this->_send_sftp_packet(NET_SFTP_READDIR, pack('Na*', strlen($handle), $handle)))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- switch ($this->packet_type)
- {
- case NET_SFTP_NAME:
- list(, $count) = unpack('N', $this->_string_shift($response, 4));
- for ($i = 0; $i < $count; $i++)
- {
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $contents[] = $this->_string_shift($response, $length);
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $this->_string_shift($response, $length); // we don't care about the longname
- $this->_parse_attributes($response); // we also don't care about the attributes
- // SFTPv6 has an optional boolean end-of-list field, but we'll ignore that, since the
- // final SSH_FXP_STATUS packet should tell us that, already.
- }
- break;
- case NET_SFTP_STATUS:
- list(, $status) = unpack('N', $this->_string_shift($response, 4));
- if ($status != NET_SFTP_STATUS_EOF)
- {
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $this->debug_info.= "\r\n\r\nSSH_FXP_STATUS:\r\n" . $this->_string_shift($response, $length);
- return false;
- }
- break 2;
- default:
- return false;
- }
- }
-
- if (!$this->_send_sftp_packet(NET_SFTP_CLOSE, pack('Na*', strlen($handle), $handle)))
- {
- return false;
- }
-
- // "The client MUST release all resources associated with the handle regardless of the status."
- // -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.1.3
- $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- return $contents;
- }
-
- /**
- * Set permissions on a file.
- *
- * Returns the new file permissions on success or FALSE on error.
- *
- * @param Integer $mode
- * @param String $filename
- * @return Mixed
- * @access public
- */
- function chmod($mode, $filename)
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- $filename = $this->_realpath($filename);
- if ($filename === false)
- {
- return false;
- }
-
- // SFTPv4+ has an additional byte field - type - that would need to be sent, as well. setting it to
- // SSH_FILEXFER_TYPE_UNKNOWN might work. if not, we'd have to do an SSH_FXP_STAT before doing an SSH_FXP_SETSTAT.
- $attr = pack('N2', NET_SFTP_ATTR_PERMISSIONS, $mode & 07777);
- if (!$this->_send_sftp_packet(NET_SFTP_SETSTAT, pack('Na*a*', strlen($filename), $filename, $attr)))
- {
- return false;
- }
-
- /*
- "Because some systems must use separate system calls to set various attributes, it is possible that a failure
- response will be returned, but yet some of the attributes may be have been successfully modified. If possible,
- servers SHOULD avoid this situation; however, clients MUST be aware that this is possible."
-
- -- http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.6
- */
- $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- // rather than return what the permissions *should* be, we'll return what they actually are. this will also
- // tell us if the file actually exists.
- // incidentally ,SFTPv4+ adds an additional 32-bit integer field - flags - to the following:
- $packet = pack('Na*', strlen($filename), $filename);
- if (!$this->_send_sftp_packet(NET_SFTP_STAT, $packet))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- switch ($this->packet_type)
- {
- case NET_SFTP_ATTRS:
- $attrs = $this->_parse_attributes($response);
- return $attrs['permissions'];
- case NET_SFTP_STATUS:
- return false;
- }
-
- return false;
- }
-
- /**
- * Creates a directory.
- *
- * @param String $dir
- * @return Boolean
- * @access public
- */
- function mkdir($dir)
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- $dir = $this->_realpath(rtrim($dir, '/'));
- if ($dir === false)
- {
- return false;
- }
-
- // by not providing any permissions, hopefully the server will use the logged in users umask - their
- // default permissions.
- if (!$this->_send_sftp_packet(NET_SFTP_MKDIR, pack('Na*N', strlen($dir), $dir, 0)))
- {
- return false;
- }
-
- $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- list(, $status) = unpack('N', $this->_string_shift($response, 4));
- if ($status != NET_SFTP_STATUS_OK)
- {
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $this->debug_info.= "\r\n\r\nSSH_FXP_STATUS:\r\n" . $this->_string_shift($response, $length);
- return false;
- }
-
- return true;
- }
-
- /**
- * Removes a directory.
- *
- * @param String $dir
- * @return Boolean
- * @access public
- */
- function rmdir($dir)
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- $dir = $this->_realpath($dir);
- if ($dir === false)
- {
- return false;
- }
-
- if (!$this->_send_sftp_packet(NET_SFTP_RMDIR, pack('Na*', strlen($dir), $dir)))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- list(, $status) = unpack('N', $this->_string_shift($response, 4));
- if ($status != NET_SFTP_STATUS_OK)
- {
- // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED?
- return false;
- }
-
- return true;
- }
-
- /**
- * Uploads a file to the SFTP server.
- *
- * By default, ssh2_sftp::put() does not read from the local filesystem. $data is dumped directly into $remote_file.
- * So, for example, if you set $data to 'filename.ext' and then do ssh2_sftp::get(), you will get a file, twelve bytes
- * long, containing 'filename.ext' as its contents.
- *
- * Setting $mode to NET_SFTP_LOCAL_FILE will change the above behavior. With NET_SFTP_LOCAL_FILE, $remote_file will
- * contain as many bytes as filename.ext does on your local filesystem. If your filename.ext is 1MB then that is how
- * large $remote_file will be, as well.
- *
- * Currently, only binary mode is supported. As such, if the line endings need to be adjusted, you will need to take
- * care of that, yourself.
- *
- * @param String $remote_file
- * @param String $data
- * @param optional Integer $flags
- * @return Boolean
- * @access public
- * @internal ASCII mode for SFTPv4/5/6 can be supported by adding a new function - ssh2_sftp::setMode().
- */
- function put($remote_file, $data, $mode = NET_SFTP_STRING)
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- $remote_file = $this->_realpath($remote_file);
- if ($remote_file === false)
- {
- return false;
- }
-
- $packet = pack('Na*N2', strlen($remote_file), $remote_file, NET_SFTP_OPEN_WRITE | NET_SFTP_OPEN_CREATE, 0);
- if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- switch ($this->packet_type)
- {
- case NET_SFTP_HANDLE:
- $handle = substr($response, 4);
- break;
- case NET_SFTP_STATUS:
- $this->_string_shift($response, 4);
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $this->debug_info.= "\r\n\r\nSSH_FXP_STATUS:\r\n" . $this->_string_shift($response, $length);
- return false;
- default:
- return false;
- }
-
- $initialize = true;
-
- // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.2.3
- if ($mode == NET_SFTP_LOCAL_FILE)
- {
- if (!is_file($data))
- {
- return false;
- }
- $fp = fopen($data, 'r');
- if (!$fp)
- {
- return false;
- }
- $sent = 0;
- $size = filesize($data);
- while ($sent < $size)
- {
- /*
- "The 'maximum packet size' specifies the maximum size of an individual data packet that can be sent to the
- sender. For example, one might want to use smaller packets for interactive connections to get better
- interactive response on slow links."
-
- -- http://tools.ietf.org/html/rfc4254#section-5.1
-
- per that, we're going to assume that the 'maximum packet size' field of the SSH_MSG_CHANNEL_OPEN message
- does not apply to the client. the client is the one who sends the SSH_MSG_CHANNEL_OPEN message, anyway,
- so it's not as if the above could be referring to the server.
-
- the reason that's mentioned is because sending $this->packet_size as the payload will result in a packet
- that's larger than $this->packet_size, but that's not a problem, as per the above.
- */
- if ($initialize)
- {
- $temp = fread($fp, $this->packet_size);
- $sent+= strlen($temp);
- $packet = pack('NCN2a*N3a*',
- $size + strlen($handle) + 21, NET_SFTP_WRITE, $this->request_id, strlen($handle), $handle, 0, 0, $size, $temp
- );
- $initialize = false;
- if (defined('NET_SFTP_LOGGING'))
- {
- $log_index = count($this->packet_type_log);
- $this->packet_type_log[] = '<- ' . $this->packet_types[$packet_type];
- $this->packet_log[] = $packet;
- }
- }
- else
- {
- $packet = fread($fp, $this->packet_size);
- $sent+= strlen($packet);
- if (defined('NET_SFTP_LOGGING'))
- {
- $this->packet_log[$log_index].= $packet;
- }
- }
- if (!$this->_send_channel_packet($packet))
- {
- fclose($fp);
- return false;
- }
- }
- fclose($fp);
- }
- else
- {
- while (strlen($data))
- {
- if ($initialize)
- {
- $packet = pack('NCN2a*N3a*',
- strlen($data) + strlen($handle) + 21, NET_SFTP_WRITE, $this->request_id, strlen($handle), $handle, 0, 0, strlen($data),
- $this->_string_shift($data, $this->packet_size)
- );
- $initialize = false;
- }
- else
- {
- $packet = $this->_string_shift($data, $this->packet_size);
- }
- if (!$this->_send_channel_packet($packet))
- {
- return false;
- }
- }
- }
-
- $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- if (!$this->_send_sftp_packet(NET_SFTP_CLOSE, pack('Na*', strlen($handle), $handle)))
- {
- return false;
- }
-
- $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- return true;
- }
-
- /**
- * Downloads a file from the SFTP server.
- *
- * Returns a string containing the contents of $remote_file if $local_file is left undefined or a boolean false if
- * the operation was unsuccessful. If $local_file is defined, returns true or false depending on the success of the
- * operation
- *
- * @param String $remote_file
- * @param optional String $local_file
- * @return Mixed
- * @access public
- */
- function get($remote_file, $local_file = false)
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- $remote_file = $this->_realpath($remote_file);
- if ($remote_file === false)
- {
- return false;
- }
-
- $packet = pack('Na*N2', strlen($remote_file), $remote_file, NET_SFTP_OPEN_READ, 0);
- if (!$this->_send_sftp_packet(NET_SFTP_OPEN, $packet))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- switch ($this->packet_type)
- {
- case NET_SFTP_HANDLE:
- $handle = substr($response, 4);
- break;
- case NET_SFTP_STATUS: // presumably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
- return false;
- default:
- return false;
- }
-
- $packet = pack('Na*', strlen($handle), $handle);
- if (!$this->_send_sftp_packet(NET_SFTP_FSTAT, $packet))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- switch ($this->packet_type)
- {
- case NET_SFTP_ATTRS:
- $attrs = $this->_parse_attributes($response);
- break;
- case NET_SFTP_STATUS:
- return false;
- default:
- return false;
- }
-
-
- if ($local_file !== false)
- {
- $fp = fopen($local_file, 'w');
- if (!$fp)
- {
- return false;
- }
- }
- else
- {
- $content = '';
- }
-
- $read = 0;
- while ($read < $attrs['size'])
- {
- $packet = pack('Na*N3', strlen($handle), $handle, 0, $read, 100000); // 100000 is completely arbitrarily chosen
- if (!$this->_send_sftp_packet(NET_SFTP_READ, $packet))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- switch ($this->packet_type)
- {
- case NET_SFTP_DATA:
- $temp = substr($response, 4);
- $read+= strlen($temp);
- if ($local_file === false)
- {
- $content.= $temp;
- }
- else
- {
- fputs($fp, $temp);
- }
- break;
- case NET_SFTP_STATUS:
- $this->_string_shift($response, 4);
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $this->debug_info.= "\r\n\r\nSSH_FXP_STATUS:\r\n" . $this->_string_shift($response, $length);
- return false;
- default:
- return false;
- }
- }
-
- if (!$this->_send_sftp_packet(NET_SFTP_CLOSE, pack('Na*', strlen($handle), $handle)))
- {
- return false;
- }
-
- $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- if (isset($content))
- {
- return $content;
- }
-
- fclose($fp);
- return true;
- }
-
- /**
- * Deletes a file on the SFTP server.
- *
- * @param String $path
- * @return Boolean
- * @access public
- */
- function delete($path)
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- $remote_file = $this->_realpath($path);
- if ($path === false)
- {
- return false;
- }
-
- // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
- if (!$this->_send_sftp_packet(NET_SFTP_REMOVE, pack('Na*', strlen($path), $path)))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- list(, $status) = unpack('N', $this->_string_shift($response, 4));
-
- // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
- return $status == NET_SFTP_STATUS_OK;
- }
-
- /**
- * Renames a file or a directory on the SFTP server
- *
- * @param String $oldname
- * @param String $newname
- * @return Boolean
- * @access public
- */
- function rename($oldname, $newname)
- {
- if (!($this->bitmap & NET_SSH2_MASK_LOGIN))
- {
- return false;
- }
-
- $oldname = $this->_realpath($oldname);
- $newname = $this->_realpath($newname);
- if ($oldname === false || $newname === false)
- {
- return false;
- }
-
- // http://tools.ietf.org/html/draft-ietf-secsh-filexfer-13#section-8.3
- $packet = pack('Na*Na*', strlen($oldname), $oldname, strlen($newname), $newname);
- if (!$this->_send_sftp_packet(NET_SFTP_RENAME, $packet))
- {
- return false;
- }
-
- $response = $this->_get_sftp_packet();
- if ($this->packet_type != NET_SFTP_STATUS)
- {
- return false;
- }
-
- list(, $status) = unpack('N', $this->_string_shift($response, 4));
-
- // if $status isn't SSH_FX_OK it's probably SSH_FX_NO_SUCH_FILE or SSH_FX_PERMISSION_DENIED
- return $status == NET_SFTP_STATUS_OK;
- }
-
- /**
- * Parse Attributes
- *
- * See '7. File Attributes' of draft-ietf-secsh-filexfer-13 for more info.
- *
- * @param String $response
- * @return Array
- * @access private
- */
- function _parse_attributes(&$response)
- {
- $attr = array();
- list(, $flags) = unpack('N', $this->_string_shift($response, 4));
- // SFTPv4+ have a type field (a byte) that follows the above flag field
- foreach ($this->attributes as $key => $value)
- {
- switch ($flags & $key)
- {
- case NET_SFTP_ATTR_SIZE: // 0x00000001
- // size is represented by a 64-bit integer, so we perhaps ought to be doing the following:
- //$attr['size'] = new Math_BigInteger($this->_string_shift($response, 8), 256);
- // of course, you shouldn't be using sftp to transfer files that are in excess of 4GB
- // (0xFFFFFFFF bytes), anyway. as such, we'll just represent all file sizes that are bigger than
- // 4GB as being 4GB.
- list(, $upper) = unpack('N', $this->_string_shift($response, 4));
- list(, $attr['size']) = unpack('N', $this->_string_shift($response, 4));
- if ($upper)
- {
- $attr['size'] = 0xFFFFFFFF;
- }
- break;
- case NET_SFTP_ATTR_UIDGID: // 0x00000002 (SFTPv3 only)
- list(, $attr['uid']) = unpack('N', $this->_string_shift($response, 4));
- list(, $attr['gid']) = unpack('N', $this->_string_shift($response, 4));
- break;
- case NET_SFTP_ATTR_PERMISSIONS: // 0x00000004
- list(, $attr['permissions']) = unpack('N', $this->_string_shift($response, 4));
- break;
- case NET_SFTP_ATTR_ACCESSTIME: // 0x00000008
- list(, $attr['atime']) = unpack('N', $this->_string_shift($response, 4));
- list(, $attr['mtime']) = unpack('N', $this->_string_shift($response, 4));
- break;
- case NET_SFTP_ATTR_EXTENDED: // 0x80000000
- list(, $count) = unpack('N', $this->_string_shift($response, 4));
- for ($i = 0; $i < $count; $i++)
- {
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $key = $this->_string_shift($response, $length);
- list(, $length) = unpack('N', $this->_string_shift($response, 4));
- $attr[$key] = $this->_string_shift($response, $length);
- }
- }
- }
- return $attr;
- }
-
- /**
- * Sends SFTP Packets
- *
- * See '6. General Packet Format' of draft-ietf-secsh-filexfer-13 for more info.
- *
- * @param Integer $type
- * @param String $data
- * @see ssh2_sftp::_get_sftp_packet()
- * @see ssh2_sftp::_send_channel_packet()
- * @return Boolean
- * @access private
- */
- function _send_sftp_packet($type, $data)
- {
- $data = $this->request_id !== false ?
- pack('NCNa*', strlen($data) + 5, $type, $this->request_id, $data) :
- pack('NCa*', strlen($data) + 1, $type, $data);
-
- if (defined('NET_SFTP_LOGGING'))
- {
- $this->packet_type_log[] = '-> ' . $this->packet_types[$type];
- $this->packet_log[] = $data;
- }
-
- return $this->_send_channel_packet($data);
- }
-
- /**
- * Sends Channel Packets
- *
- * If this function were in Net_SSH2, there'd have to be an additional server channel parameter since the Net_SSH2 object
- * doesn't currently have one. Plus, it wouldn't actually make a lot of sense for Net_SSH2 even to have one - if it did
- * and if Net_SSH2::exec() used it then ssh2_sftp::exec() would also use it (through inheritance) and you'd have the
- * single server channel being overwritten and... all in all, I think this is easier.
- *
- * @param Integer $type
- * @param String $data
- * @see ssh2_sftp::_send_sftp_packet()
- * @return Boolean
- * @access private
- */
- function _send_channel_packet($data)
- {
- return $this->_send_binary_packet(pack('CN2a*', NET_SSH2_MSG_CHANNEL_DATA, $this->server_channel, strlen($data), $data));
- }
-
- /**
- * Receives SFTP Packets
- *
- * See '6. General Packet Format' of draft-ietf-secsh-filexfer-13 for more info.
- *
- * @see ssh2_sftp::_send_sftp_packet()
- * @return String
- * @access private
- */
- function _get_sftp_packet()
- {
- $packet = $this->_get_channel_packet();
- if (is_bool($packet))
- {
- $this->packet_type = false;
- return false;
- }
- /*
- normally, strlen($packet) == $length, however, for really large packets, strlen($packet) < $length. what this means,
- when it happens, is that the string is being spanned out across multiple SSH_MSG_CHANNEL_DATA messages and we'll
- need to read them multiple times until we reach $length bytes.
-
- presumably, strlen($packet) > $length would never happen unless you were trying to employ steganography or
- something
- */
- list(, $length) = unpack('N', $this->_string_shift($packet, 4));
- $this->packet_type = ord($this->_string_shift($packet));
- if ($this->request_id !== false)
- {
- $this->_string_shift($packet, 4); // remove the request id
- $length-= 5; // account for the request id and the packet type
- }
- else
- {
- $length-= 1; // account for the packet type
- }
- $packet = substr($packet, 0, $length); // just in case strlen($packet) > $length
- $length-= strlen($packet);
- while ($length > 0)
- {
- $temp = $this->_get_channel_packet();
- if (is_bool($temp))
- {
- $this->packet_type = false;
- return false;
- }
- $packet.= $temp;
- $length-= strlen($temp);
- }
-
- if (defined('NET_SFTP_LOGGING'))
- {
- $this->packet_type_log[] = '<- ' . $this->packet_types[$this->packet_type];
- $this->packet_log[] = $packet;
- }
-
- return $packet;
- }
-
- /**
- * Returns a log of the packets that have been sent and received.
- *
- * $type can be either NET_SFTP_LOG_SIMPLE or NET_SFTP_LOG_COMPLEX. Enable by defining NET_SSH2_LOGGING.
- *
- * @param Integer $type
- * @access public
- * @return String or Array
- */
- function get_sftp_log($type = NET_SFTP_LOG_COMPLEX)
- {
- $message_number_log = $this->message_number_log;
- $message_log = $this->message_log;
-
- $this->message_number_log = $this->packet_type_log;
- $this->message_log = $this->packet_log;
-
- $return = $this->getLog($type);
-
- $this->message_number_log = $message_number_log;
- $this->message_log = $message_log;
-
- return $return;
- }
-
- /**
- * Get supported SFTP versions
- *
- * @return Array
- * @access public
- */
- function get_supported_versions()
- {
- $temp = array('version' => $this->version);
- if (isset($this->extensions['versions']))
- {
- $temp['extensions'] = $this->extensions['versions'];
- }
- return $temp;
- }
-
- /**
- * Disconnect
- *
- * @param Integer $reason
- * @return Boolean
- * @access private
- */
- function _disconnect($reason)
- {
- $this->pwd = false;
- parent::_disconnect($reason);
- }
-}
-
-?>
\ No newline at end of file diff --git a/phpBB/includes/libraries/zend/Exception.php b/phpBB/includes/libraries/zend/Exception.php deleted file mode 100644 index 599d8a033e..0000000000 --- a/phpBB/includes/libraries/zend/Exception.php +++ /dev/null @@ -1,30 +0,0 @@ -<?php -/** - * Zend Framework - * - * LICENSE - * - * This source file is subject to the new BSD license that is bundled - * with this package in the file LICENSE.txt. - * It is also available through the world-wide-web at this URL: - * http://framework.zend.com/license/new-bsd - * If you did not receive a copy of the license and are unable to - * obtain it through the world-wide-web, please send an email - * to license@zend.com so we can send you a copy immediately. - * - * @category Zend - * @package Zend - * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ - - -/** - * @category Zend - * @package Zend - * @copyright Copyright (c) 2005-2008 Zend Technologies USA Inc. (http://www.zend.com) - * @license http://framework.zend.com/license/new-bsd New BSD License - */ -class Zend_Exception extends Exception -{} - diff --git a/phpBB/includes/libraries/zend/loader.php b/phpBB/includes/libraries/zend/loader.php deleted file mode 100644 index 99a5543901..0000000000 --- a/phpBB/includes/libraries/zend/loader.php +++ /dev/null @@ -1,58 +0,0 @@ -<?php -/** -* -* @package zend -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -if (version_compare(PHP_VERSION, '5.2.4', '<') || !function_exists('spl_autoload_register')) -{ - trigger_error('PHP >= 5.2.4 and spl_autoload_register() required', E_USER_ERROR); -} - -/** -* Autoload function for Zend framework classes -*/ -function phpbb_zend_autoload($class_name) -{ - global $phpbb_root_path; - - if (strpos($class_name, '_') !== false) - { - $path = str_replace('_', '/', $class_name) . '.php'; - require("{$phpbb_root_path}includes/" . $path); - return true; - } -} - -/** -* @ignore -*/ -// make sure Zend is in the include path -ini_set( 'include_path', ini_get( 'include_path' ) . PATH_SEPARATOR . $phpbb_root_path . 'includes' ); - -// check whether a regular autoload function already exists, so we can load it into the spl stack afterwards -$register_autoload = false; -if (function_exists('__autoload')) -{ - $register_autoload = true; -} - -spl_autoload_register('phpbb_zend_autoload'); - -// load the old autoload function into the spl stack if necessary -if ($register_autoload) -{ - spl_autoload_register('__autoload'); -}
\ No newline at end of file diff --git a/phpBB/includes/message_parser.php b/phpBB/includes/message_parser.php deleted file mode 100644 index 39c65e054d..0000000000 --- a/phpBB/includes/message_parser.php +++ /dev/null @@ -1,1623 +0,0 @@ -<?php -/** -* -* @package phpBB3 -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -if (!class_exists('bbcode')) -{ - include(PHPBB_ROOT_PATH . 'includes/bbcode.' . PHP_EXT); -} - -/** -* BBCODE FIRSTPASS -* BBCODE first pass class (functions for parsing messages for db storage) -* @package phpBB3 -*/ -class bbcode_firstpass extends bbcode -{ - var $message = ''; - var $warn_msg = array(); - var $parsed_items = array(); - - /** - * Parse BBCode - */ - function parse_bbcode() - { - if (!$this->bbcodes) - { - $this->bbcode_init(); - } - - $this->bbcode_bitfield = ''; - $bitfield = new bitfield(); - - foreach ($this->bbcodes as $bbcode_name => $bbcode_data) - { - if (isset($bbcode_data['disabled']) && $bbcode_data['disabled']) - { - foreach ($bbcode_data['regexp'] as $regexp => $replacement) - { - if (preg_match($regexp, $this->message)) - { - $this->warn_msg[] = sprintf(phpbb::$user->lang['UNAUTHORISED_BBCODE'] , '[' . $bbcode_name . ']'); - continue; - } - } - } - else - { - foreach ($bbcode_data['regexp'] as $regexp => $replacement) - { - // The pattern gets compiled and cached by the PCRE extension, - // it should not demand recompilation - if (preg_match($regexp, $this->message)) - { - $this->message = preg_replace($regexp, $replacement, $this->message); - $bitfield->set($bbcode_data['bbcode_id']); - } - } - } - } - - $this->bbcode_bitfield = $bitfield->get_base64(); - } - - /** - * Prepare some bbcodes for better parsing - */ - function prepare_bbcodes() - { - // Ok, seems like users instead want the no-parsing of urls, smilies, etc. after and before and within quote tags being tagged as "not a bug". - // Fine by me ;) Will ease our live... but do not come back and cry at us, we won't hear you. - - /* Add newline at the end and in front of each quote block to prevent parsing errors (urls, smilies, etc.) - if (strpos($this->message, '[quote') !== false && strpos($this->message, '[/quote]') !== false) - { - $this->message = str_replace("\r\n", "\n", $this->message); - - // We strip newlines and spaces after and before quotes in quotes (trimming) and then add exactly one newline - $this->message = preg_replace('#\[quote(=".*?")?\]\s*(.*?)\s*\[/quote\]#siu', '[quote\1]' . "\n" . '\2' ."\n[/quote]", $this->message); - } - */ - - // Add other checks which needs to be placed before actually parsing anything (be it bbcodes, smilies, urls...) - } - - /** - * Init bbcode data for later parsing - */ - function bbcode_init() - { - static $rowset; - - // This array holds all bbcode data. BBCodes will be processed in this - // order, so it is important to keep [code] in first position and - // [quote] in second position. - $this->bbcodes = array( - 'code' => array('bbcode_id' => 8, 'regexp' => array('#\[code(?:=([a-z]+))?\](.+\[/code\])#ise' => "\$this->bbcode_code('\$1', '\$2')")), - 'quote' => array('bbcode_id' => 0, 'regexp' => array('#\[quote(?:="(.*?)")?\](.+)\[/quote\]#ise' => "\$this->bbcode_quote('\$0')")), - 'attachment' => array('bbcode_id' => 12, 'regexp' => array('#\[attachment=([0-9]+)\](.*?)\[/attachment\]#ise' => "\$this->bbcode_attachment('\$1', '\$2')")), - 'b' => array('bbcode_id' => 1, 'regexp' => array('#\[b\](.*?)\[/b\]#ise' => "\$this->bbcode_strong('\$1')")), - 'i' => array('bbcode_id' => 2, 'regexp' => array('#\[i\](.*?)\[/i\]#ise' => "\$this->bbcode_italic('\$1')")), - 'url' => array('bbcode_id' => 3, 'regexp' => array('#\[url(=(.*))?\](.*)\[/url\]#iUe' => "\$this->validate_url('\$2', '\$3')")), - 'img' => array('bbcode_id' => 4, 'regexp' => array('#\[img\](.*)\[/img\]#iUe' => "\$this->bbcode_img('\$1')")), - 'size' => array('bbcode_id' => 5, 'regexp' => array('#\[size=([\-\+]?\d+)\](.*?)\[/size\]#ise' => "\$this->bbcode_size('\$1', '\$2')")), - 'color' => array('bbcode_id' => 6, 'regexp' => array('!\[color=(#[0-9a-f]{6}|[a-z\-]+)\](.*?)\[/color\]!ise' => "\$this->bbcode_color('\$1', '\$2')")), - 'u' => array('bbcode_id' => 7, 'regexp' => array('#\[u\](.*?)\[/u\]#ise' => "\$this->bbcode_underline('\$1')")), - 'list' => array('bbcode_id' => 9, 'regexp' => array('#\[list(?:=(?:[a-z0-9]|disc|circle|square))?].*\[/list]#ise' => "\$this->bbcode_parse_list('\$0')")), - 'email' => array('bbcode_id' => 10, 'regexp' => array('#\[email=?(.*?)?\](.*?)\[/email\]#ise' => "\$this->validate_email('\$1', '\$2')")), - 'flash' => array('bbcode_id' => 11, 'regexp' => array('#\[flash=([0-9]+),([0-9]+)\](.*?)\[/flash\]#ie' => "\$this->bbcode_flash('\$1', '\$2', '\$3')")) - ); - - // Zero the parsed items array - $this->parsed_items = array(); - - foreach ($this->bbcodes as $tag => $bbcode_data) - { - $this->parsed_items[$tag] = 0; - } - - if (!is_array($rowset)) - { - $rowset = array(); - - $sql = 'SELECT * - FROM ' . BBCODES_TABLE; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $rowset[] = $row; - } - phpbb::$db->sql_freeresult($result); - } - - foreach ($rowset as $row) - { - $this->bbcodes[$row['bbcode_tag']] = array( - 'bbcode_id' => (int) $row['bbcode_id'], - 'regexp' => array($row['first_pass_match'] => str_replace('$uid', $this->bbcode_uid, $row['first_pass_replace'])) - ); - } - } - - /** - * Making some pre-checks for bbcodes as well as increasing the number of parsed items - */ - function check_bbcode($bbcode, &$in) - { - // when using the /e modifier, preg_replace slashes double-quotes but does not - // seem to slash anything else - $in = str_replace("\r\n", "\n", str_replace('\"', '"', $in)); - - // Trimming here to make sure no empty bbcodes are parsed accidently - if (trim($in) == '') - { - return false; - } - - $this->parsed_items[$bbcode]++; - - return true; - } - - /** - * Transform some characters in valid bbcodes - */ - function bbcode_specialchars($text) - { - $str_from = array('<', '>', '[', ']', '.', ':'); - $str_to = array('<', '>', '[', ']', '.', ':'); - - return str_replace($str_from, $str_to, $text); - } - - /** - * Parse size tag - */ - function bbcode_size($stx, $in) - { - if (!$this->check_bbcode('size', $in)) - { - return $in; - } - - if (phpbb::$config['max_' . $this->mode . '_font_size'] && phpbb::$config['max_' . $this->mode . '_font_size'] < $stx) - { - $this->warn_msg[] = sprintf(phpbb::$user->lang['MAX_FONT_SIZE_EXCEEDED'], phpbb::$config['max_' . $this->mode . '_font_size']); - - return '[size=' . $stx . ']' . $in . '[/size]'; - } - - // Do not allow size=0 - if ($stx <= 0) - { - return '[size=' . $stx . ']' . $in . '[/size]'; - } - - return '[size=' . $stx . ':' . $this->bbcode_uid . ']' . $in . '[/size:' . $this->bbcode_uid . ']'; - } - - /** - * Parse color tag - */ - function bbcode_color($stx, $in) - { - if (!$this->check_bbcode('color', $in)) - { - return $in; - } - - return '[color=' . $stx . ':' . $this->bbcode_uid . ']' . $in . '[/color:' . $this->bbcode_uid . ']'; - } - - /** - * Parse u tag - */ - function bbcode_underline($in) - { - if (!$this->check_bbcode('u', $in)) - { - return $in; - } - - return '[u:' . $this->bbcode_uid . ']' . $in . '[/u:' . $this->bbcode_uid . ']'; - } - - /** - * Parse b tag - */ - function bbcode_strong($in) - { - if (!$this->check_bbcode('b', $in)) - { - return $in; - } - - return '[b:' . $this->bbcode_uid . ']' . $in . '[/b:' . $this->bbcode_uid . ']'; - } - - /** - * Parse i tag - */ - function bbcode_italic($in) - { - if (!$this->check_bbcode('i', $in)) - { - return $in; - } - - return '[i:' . $this->bbcode_uid . ']' . $in . '[/i:' . $this->bbcode_uid . ']'; - } - - /** - * Parse img tag - */ - function bbcode_img($in) - { - if (!$this->check_bbcode('img', $in)) - { - return $in; - } - - $in = trim($in); - $error = false; - - $in = str_replace(' ', '%20', $in); - - // Checking urls - if (!preg_match('#^' . get_preg_expression('url') . '$#i', $in) && !preg_match('#^' . get_preg_expression('www_url') . '$#i', $in)) - { - return '[img]' . $in . '[/img]'; - } - - // Try to cope with a common user error... not specifying a protocol but only a subdomain - if (!preg_match('#^[a-z0-9]+://#i', $in)) - { - $in = 'http://' . $in; - } - - if (phpbb::$config['max_' . $this->mode . '_img_height'] || phpbb::$config['max_' . $this->mode . '_img_width']) - { - $stats = @getimagesize($in); - - if ($stats === false) - { - $error = true; - $this->warn_msg[] = phpbb::$user->lang['UNABLE_GET_IMAGE_SIZE']; - } - else - { - if (phpbb::$config['max_' . $this->mode . '_img_height'] && phpbb::$config['max_' . $this->mode . '_img_height'] < $stats[1]) - { - $error = true; - $this->warn_msg[] = sprintf(phpbb::$user->lang['MAX_IMG_HEIGHT_EXCEEDED'], phpbb::$config['max_' . $this->mode . '_img_height']); - } - - if (phpbb::$config['max_' . $this->mode . '_img_width'] && phpbb::$config['max_' . $this->mode . '_img_width'] < $stats[0]) - { - $error = true; - $this->warn_msg[] = sprintf(phpbb::$user->lang['MAX_IMG_WIDTH_EXCEEDED'], phpbb::$config['max_' . $this->mode . '_img_width']); - } - } - } - - if ($error || $this->path_in_domain($in)) - { - return '[img]' . $in . '[/img]'; - } - - return '[img:' . $this->bbcode_uid . ']' . $this->bbcode_specialchars($in) . '[/img:' . $this->bbcode_uid . ']'; - } - - /** - * Parse flash tag - */ - function bbcode_flash($width, $height, $in) - { - if (!$this->check_bbcode('flash', $in)) - { - return $in; - } - - $in = trim($in); - $error = false; - - // Do not allow 0-sizes generally being entered - if ($width <= 0 || $height <= 0) - { - return '[flash=' . $width . ',' . $height . ']' . $in . '[/flash]'; - } - - // Apply the same size checks on flash files as on images - if (phpbb::$config['max_' . $this->mode . '_img_height'] || phpbb::$config['max_' . $this->mode . '_img_width']) - { - if (phpbb::$config['max_' . $this->mode . '_img_height'] && phpbb::$config['max_' . $this->mode . '_img_height'] < $height) - { - $error = true; - $this->warn_msg[] = sprintf(phpbb::$user->lang['MAX_FLASH_HEIGHT_EXCEEDED'], phpbb::$config['max_' . $this->mode . '_img_height']); - } - - if (phpbb::$config['max_' . $this->mode . '_img_width'] && phpbb::$config['max_' . $this->mode . '_img_width'] < $width) - { - $error = true; - $this->warn_msg[] = sprintf(phpbb::$user->lang['MAX_FLASH_WIDTH_EXCEEDED'], phpbb::$config['max_' . $this->mode . '_img_width']); - } - } - - if ($error || $this->path_in_domain($in)) - { - return '[flash=' . $width . ',' . $height . ']' . $in . '[/flash]'; - } - - return '[flash=' . $width . ',' . $height . ':' . $this->bbcode_uid . ']' . $this->bbcode_specialchars($in) . '[/flash:' . $this->bbcode_uid . ']'; - } - - /** - * Parse inline attachments [ia] - */ - function bbcode_attachment($stx, $in) - { - if (!$this->check_bbcode('attachment', $in)) - { - return $in; - } - - return '[attachment=' . $stx . ':' . $this->bbcode_uid . ']<!-- ia' . $stx . ' -->' . trim($in) . '<!-- ia' . $stx . ' -->[/attachment:' . $this->bbcode_uid . ']'; - } - - /** - * Parse code text from code tag - * @access private - */ - function bbcode_parse_code($stx, &$code) - { - switch (strtolower($stx)) - { - case 'php': - - $remove_tags = false; - - $str_from = array('<', '>', '[', ']', '.', ':', ':'); - $str_to = array('<', '>', '[', ']', '.', ':', ':'); - $code = str_replace($str_from, $str_to, $code); - - if (!preg_match('/\<\?.*?\?\>/is', $code)) - { - $remove_tags = true; - $code = "<?php $code ?>"; - } - - $conf = array('highlight.bg', 'highlight.comment', 'highlight.default', 'highlight.html', 'highlight.keyword', 'highlight.string'); - foreach ($conf as $ini_var) - { - @ini_set($ini_var, str_replace('highlight.', 'syntax', $ini_var)); - } - - // Because highlight_string is specialcharing the text (but we already did this before), we have to reverse this in order to get correct results - $code = htmlspecialchars_decode($code); - $code = highlight_string($code, true); - - $str_from = array('<span style="color: ', '<font color="syntax', '</font>', '<code>', '</code>','[', ']', '.', ':'); - $str_to = array('<span class="', '<span class="syntax', '</span>', '', '', '[', ']', '.', ':'); - - if ($remove_tags) - { - $str_from[] = '<span class="syntaxdefault"><?php </span>'; - $str_to[] = ''; - $str_from[] = '<span class="syntaxdefault"><?php '; - $str_to[] = '<span class="syntaxdefault">'; - } - - $code = str_replace($str_from, $str_to, $code); - $code = preg_replace('#^(<span class="[a-z_]+">)\n?(.*?)\n?(</span>)$#is', '$1$2$3', $code); - - if ($remove_tags) - { - $code = preg_replace('#(<span class="[a-z]+">)?\?>(</span>)#', '$1 $2', $code); - } - - $code = preg_replace('#^<span class="[a-z]+"><span class="([a-z]+)">(.*)</span></span>#s', '<span class="$1">$2</span>', $code); - $code = preg_replace('#(?:\s++| )*+</span>$#u', '</span>', $code); - - // remove newline at the end - if (!empty($code) && substr($code, -1) == "\n") - { - $code = substr($code, 0, -1); - } - - return "[code=$stx:" . $this->bbcode_uid . ']' . $code . '[/code:' . $this->bbcode_uid . ']'; - break; - - default: - return '[code:' . $this->bbcode_uid . ']' . $this->bbcode_specialchars($code) . '[/code:' . $this->bbcode_uid . ']'; - break; - } - } - - /** - * Parse code tag - * Expects the argument to start right after the opening [code] tag and to end with [/code] - */ - function bbcode_code($stx, $in) - { - if (!$this->check_bbcode('code', $in)) - { - return $in; - } - - // We remove the hardcoded elements from the code block here because it is not used in code blocks - // Having it here saves us one preg_replace per message containing [code] blocks - // Additionally, magic url parsing should go after parsing bbcodes, but for safety those are stripped out too... - $htm_match = get_preg_expression('bbcode_htm'); - unset($htm_match[4], $htm_match[5]); - $htm_replace = array('\1', '\1', '\2', '\1'); - - $out = $code_block = ''; - $open = 1; - - while ($in) - { - // Determine position and tag length of next code block - preg_match('#(.*?)(\[code(?:=([a-z]+))?\])(.+)#is', $in, $buffer); - $pos = (isset($buffer[1])) ? strlen($buffer[1]) : false; - $tag_length = (isset($buffer[2])) ? strlen($buffer[2]) : false; - - // Determine position of ending code tag - $pos2 = stripos($in, '[/code]'); - - // Which is the next block, ending code or code block - if ($pos !== false && $pos < $pos2) - { - // Open new block - if (!$open) - { - $out .= substr($in, 0, $pos); - $in = substr($in, $pos); - $stx = (isset($buffer[3])) ? $buffer[3] : ''; - $code_block = ''; - } - else - { - // Already opened block, just append to the current block - $code_block .= substr($in, 0, $pos) . ((isset($buffer[2])) ? $buffer[2] : ''); - $in = substr($in, $pos); - } - - $in = substr($in, $tag_length); - $open++; - } - else - { - // Close the block - if ($open == 1) - { - $code_block .= substr($in, 0, $pos2); - $code_block = preg_replace($htm_match, $htm_replace, $code_block); - - // Parse this code block - $out .= $this->bbcode_parse_code($stx, $code_block); - $code_block = ''; - $open--; - } - else if ($open) - { - // Close one open tag... add to the current code block - $code_block .= substr($in, 0, $pos2 + 7); - $open--; - } - else - { - // end code without opening code... will be always outside code block - $out .= substr($in, 0, $pos2 + 7); - } - - $in = substr($in, $pos2 + 7); - } - } - - // if now $code_block has contents we need to parse the remaining code while removing the last closing tag to match up. - if ($code_block) - { - $code_block = substr($code_block, 0, -7); - $code_block = preg_replace($htm_match, $htm_replace, $code_block); - - $out .= $this->bbcode_parse_code($stx, $code_block); - } - - return $out; - } - - /** - * Parse list bbcode - * Expects the argument to start with a tag - */ - function bbcode_parse_list($in) - { - if (!$this->check_bbcode('list', $in)) - { - return $in; - } - - // $tok holds characters to stop at. Since the string starts with a '[' we'll get everything up to the first ']' which should be the opening [list] tag - $tok = ']'; - $out = '['; - - // First character is [ - $in = substr($in, 1); - $list_end_tags = $item_end_tags = array(); - - do - { - $pos = strlen($in); - - for ($i = 0, $tok_len = strlen($tok); $i < $tok_len; ++$i) - { - $tmp_pos = strpos($in, $tok[$i]); - - if ($tmp_pos !== false && $tmp_pos < $pos) - { - $pos = $tmp_pos; - } - } - - $buffer = substr($in, 0, $pos); - $tok = $in[$pos]; - - $in = substr($in, $pos + 1); - - if ($tok == ']') - { - // if $tok is ']' the buffer holds a tag - if (strtolower($buffer) == '/list' && sizeof($list_end_tags)) - { - // valid [/list] tag, check nesting so that we don't hit false positives - if (sizeof($item_end_tags) && sizeof($item_end_tags) >= sizeof($list_end_tags)) - { - // current li tag has not been closed - $out = preg_replace('/\n?\[$/', '[', $out) . array_pop($item_end_tags) . ']['; - } - - $out .= array_pop($list_end_tags) . ']'; - $tok = '['; - } - else if (preg_match('#^list(=[0-9a-z]+)?$#i', $buffer, $m)) - { - // sub-list, add a closing tag - if (empty($m[1]) || preg_match('/^=(?:disc|square|circle)$/i', $m[1])) - { - array_push($list_end_tags, '/list:u:' . $this->bbcode_uid); - } - else - { - array_push($list_end_tags, '/list:o:' . $this->bbcode_uid); - } - $out .= 'list' . substr($buffer, 4) . ':' . $this->bbcode_uid . ']'; - $tok = '['; - } - else - { - if (($buffer == '*' || substr($buffer, -2) == '[*') && sizeof($list_end_tags)) - { - // the buffer holds a bullet tag and we have a [list] tag open - if (sizeof($item_end_tags) >= sizeof($list_end_tags)) - { - if (substr($buffer, -2) == '[*') - { - $out .= substr($buffer, 0, -2) . '['; - } - // current li tag has not been closed - if (preg_match('/\n\[$/', $out, $m)) - { - $out = preg_replace('/\n\[$/', '[', $out); - $buffer = array_pop($item_end_tags) . "]\n[*:" . $this->bbcode_uid; - } - else - { - $buffer = array_pop($item_end_tags) . '][*:' . $this->bbcode_uid; - } - } - else - { - $buffer = '*:' . $this->bbcode_uid; - } - - $item_end_tags[] = '/*:m:' . $this->bbcode_uid; - } - else if ($buffer == '/*') - { - array_pop($item_end_tags); - $buffer = '/*:' . $this->bbcode_uid; - } - - $out .= $buffer . $tok; - $tok = '[]'; - } - } - else - { - // Not within a tag, just add buffer to the return string - $out .= $buffer . $tok; - $tok = ($tok == '[') ? ']' : '[]'; - } - } - while ($in); - - // do we have some tags open? close them now - if (sizeof($item_end_tags)) - { - $out .= '[' . implode('][', $item_end_tags) . ']'; - } - if (sizeof($list_end_tags)) - { - $out .= '[' . implode('][', $list_end_tags) . ']'; - } - - return $out; - } - - /** - * Parse quote bbcode - * Expects the argument to start with a tag - */ - function bbcode_quote($in) - { - /** - * If you change this code, make sure the cases described within the following reports are still working: - * #3572 - [quote="[test]test"]test [ test[/quote] - (correct: parsed) - * #14667 - [quote]test[/quote] test ] and [ test [quote]test[/quote] (correct: parsed) - * #14770 - [quote="["]test[/quote] (correct: parsed) - * [quote="[i]test[/i]"]test[/quote] (correct: parsed) - * [quote="[quote]test[/quote]"]test[/quote] (correct: parsed - Username displayed as [quote]test[/quote]) - * #20735 - [quote]test[/[/b]quote] test [/quote][/quote] test - (correct: quoted: "test[/[/b]quote] test" / non-quoted: "[/quote] test" - also failed if layout distorted) - * #40565 - [quote="a"]a[/quote][quote="a]a[/quote] (correct: first quote tag parsed, second quote tag unparsed) - */ - - $in = str_replace("\r\n", "\n", str_replace('\"', '"', trim($in))); - - if (!$in) - { - return ''; - } - - // To let the parser not catch tokens within quote_username quotes we encode them before we start this... - $in = preg_replace('#quote="(.*?)"\]#ie', "'quote="' . str_replace(array('[', ']', '\\\"'), array('[', ']', '\"'), '\$1') . '"]'", $in); - - $tok = ']'; - $out = '['; - - $in = substr($in, 1); - $close_tags = $error_ary = array(); - $buffer = ''; - - do - { - $pos = strlen($in); - for ($i = 0, $tok_len = strlen($tok); $i < $tok_len; ++$i) - { - $tmp_pos = strpos($in, $tok[$i]); - if ($tmp_pos !== false && $tmp_pos < $pos) - { - $pos = $tmp_pos; - } - } - - $buffer .= substr($in, 0, $pos); - $tok = $in[$pos]; - $in = substr($in, $pos + 1); - - if ($tok == ']') - { - if (strtolower($buffer) == '/quote' && sizeof($close_tags) && substr($out, -1, 1) == '[') - { - // we have found a closing tag - $out .= array_pop($close_tags) . ']'; - $tok = '['; - $buffer = ''; - - /* Add space at the end of the closing tag if not happened before to allow following urls/smilies to be parsed correctly - * Do not try to think for the user. :/ Do not parse urls/smilies if there is no space - is the same as with other bbcodes too. - * Also, we won't have any spaces within $in anyway, only adding up spaces -> #10982 - if (!$in || $in[0] !== ' ') - { - $out .= ' '; - }*/ - } - else if (preg_match('#^quote(?:="(.*?)")?$#is', $buffer, $m) && substr($out, -1, 1) == '[') - { - $this->parsed_items['quote']++; - - // the buffer holds a valid opening tag - if (phpbb::$config['max_quote_depth'] && sizeof($close_tags) >= phpbb::$config['max_quote_depth']) - { - // there are too many nested quotes - $error_ary['quote_depth'] = sprintf(phpbb::$user->lang['QUOTE_DEPTH_EXCEEDED'], phpbb::$config['max_quote_depth']); - - $out .= $buffer . $tok; - $tok = '[]'; - $buffer = ''; - - continue; - } - - array_push($close_tags, '/quote:' . $this->bbcode_uid); - - if (isset($m[1]) && $m[1]) - { - $username = str_replace(array('[', ']'), array('[', ']'), $m[1]); - $username = preg_replace('#\[(?!b|i|u|color|url|email|/b|/i|/u|/color|/url|/email)#iU', '[$1', $username); - - $end_tags = array(); - $error = false; - - preg_match_all('#\[((?:/)?(?:[a-z]+))#i', $username, $tags); - foreach ($tags[1] as $tag) - { - if ($tag[0] != '/') - { - $end_tags[] = '/' . $tag; - } - else - { - $end_tag = array_pop($end_tags); - $error = ($end_tag != $tag) ? true : false; - } - } - - if ($error) - { - $username = $m[1]; - } - - $out .= 'quote="' . $username . '":' . $this->bbcode_uid . ']'; - } - else - { - $out .= 'quote:' . $this->bbcode_uid . ']'; - } - - $tok = '['; - $buffer = ''; - } - else if (preg_match('#^quote="(.*?)#is', $buffer, $m)) - { - // the buffer holds an invalid opening tag - $buffer .= ']'; - } - else - { - $out .= $buffer . $tok; - $tok = '[]'; - $buffer = ''; - } - } - else - { -/** -* Old quote code working fine, but having errors listed in bug #3572 -* -* $out .= $buffer . $tok; -* $tok = ($tok == '[') ? ']' : '[]'; -* $buffer = ''; -*/ - - $out .= $buffer . $tok; - - if ($tok == '[') - { - // Search the text for the next tok... if an ending quote comes first, then change tok to [] - $pos1 = stripos($in, '[/quote'); - // If the token ] comes first, we change it to ] - $pos2 = strpos($in, ']'); - // If the token [ comes first, we change it to [ - $pos3 = strpos($in, '['); - - if ($pos1 !== false && ($pos2 === false || $pos1 < $pos2) && ($pos3 === false || $pos1 < $pos3)) - { - $tok = '[]'; - } - else if ($pos3 !== false && ($pos2 === false || $pos3 < $pos2)) - { - $tok = '['; - } - else - { - $tok = ']'; - } - } - else - { - $tok = '[]'; - } - $buffer = ''; - } - } - while ($in); - - $out .= $buffer; - - if (sizeof($close_tags)) - { - $out .= '[' . implode('][', $close_tags) . ']'; - } - - foreach ($error_ary as $error_msg) - { - $this->warn_msg[] = $error_msg; - } - - return $out; - } - - /** - * Validate email - */ - function validate_email($var1, $var2) - { - $var1 = str_replace("\r\n", "\n", str_replace('\"', '"', trim($var1))); - $var2 = str_replace("\r\n", "\n", str_replace('\"', '"', trim($var2))); - - $txt = $var2; - $email = ($var1) ? $var1 : $var2; - - $validated = true; - - if (!preg_match('/^' . get_preg_expression('email') . '$/i', $email)) - { - $validated = false; - } - - if (!$validated) - { - return '[email' . (($var1) ? "=$var1" : '') . ']' . $var2 . '[/email]'; - } - - $this->parsed_items['email']++; - - if ($var1) - { - $retval = '[email=' . $this->bbcode_specialchars($email) . ':' . $this->bbcode_uid . ']' . $txt . '[/email:' . $this->bbcode_uid . ']'; - } - else - { - $retval = '[email:' . $this->bbcode_uid . ']' . $this->bbcode_specialchars($email) . '[/email:' . $this->bbcode_uid . ']'; - } - - return $retval; - } - - /** - * Validate url - * - * @param string $var1 optional url parameter for url bbcode: [url(=$var1)]$var2[/url] - * @param string $var2 url bbcode content: [url(=$var1)]$var2[/url] - */ - function validate_url($var1, $var2) - { - $var1 = str_replace("\r\n", "\n", str_replace('\"', '"', trim($var1))); - $var2 = str_replace("\r\n", "\n", str_replace('\"', '"', trim($var2))); - - $url = ($var1) ? $var1 : $var2; - - if ($var1 && !$var2) - { - $var2 = $var1; - } - - if (!$url) - { - return '[url' . (($var1) ? '=' . $var1 : '') . ']' . $var2 . '[/url]'; - } - - $valid = false; - - $url = str_replace(' ', '%20', $url); - - // Checking urls - if (preg_match('#^' . get_preg_expression('url') . '$#i', $url) || - preg_match('#^' . get_preg_expression('www_url') . '$#i', $url) || - preg_match('#^' . preg_quote(generate_board_url(), '#') . get_preg_expression('relative_url') . '$#i', $url)) - { - $valid = true; - } - - if ($valid) - { - $this->parsed_items['url']++; - - // if there is no scheme, then add http schema - if (!preg_match('#^[a-z][a-z\d+\-.]*:/{2}#i', $url)) - { - $url = 'http://' . $url; - } - - // Is this a link to somewhere inside this board? If so then remove the session id from the url - if (strpos($url, generate_board_url()) !== false && strpos($url, 'sid=') !== false) - { - $url = preg_replace('/(&|\?)sid=[0-9a-f]{32}&/', '\1', $url); - $url = preg_replace('/(&|\?)sid=[0-9a-f]{32}$/', '', $url); - $url = append_sid($url); - } - - return ($var1) ? '[url=' . $this->bbcode_specialchars($url) . ':' . $this->bbcode_uid . ']' . $var2 . '[/url:' . $this->bbcode_uid . ']' : '[url:' . $this->bbcode_uid . ']' . $this->bbcode_specialchars($url) . '[/url:' . $this->bbcode_uid . ']'; - } - - return '[url' . (($var1) ? '=' . $var1 : '') . ']' . $var2 . '[/url]'; - } - - /** - * Check if url is pointing to this domain/script_path/php-file - * - * @param string $url the url to check - * @return true if the url is pointing to this domain/script_path/php-file, false if not - * - * @access private - */ - function path_in_domain($url) - { - if (phpbb::$config['force_server_vars']) - { - $check_path = phpbb::$config['script_path']; - } - else - { - $check_path = (phpbb::$user->page['root_script_path'] != '/') ? substr(phpbb::$user->page['root_script_path'], 0, -1) : '/'; - } - - // Is the user trying to link to a php file in this domain and script path? - if (strpos($url, '.' . PHP_EXT) !== false && strpos($url, $check_path) !== false) - { - $server_name = phpbb::$user->system['host']; - - // Forcing server vars is the only way to specify/override the protocol - if (phpbb::$config['force_server_vars'] || !$server_name) - { - $server_name = phpbb::$config['server_name']; - } - - // Check again in correct order... - $pos_ext = strpos($url, '.' . PHP_EXT); - $pos_path = strpos($url, $check_path); - $pos_domain = strpos($url, $server_name); - - if ($pos_domain !== false && $pos_path >= $pos_domain && $pos_ext >= $pos_path) - { - // Ok, actually we allow linking to some files (this may be able to be extended in some way later...) - if (strpos($url, '/' . $check_path . '/download/file.' . PHP_EXT) !== 0) - { - return false; - } - - return true; - } - } - - return false; - } -} - -/** -* Main message parser for posting, pm, etc. takes raw message -* and parses it for attachments, bbcode and smilies -* @package phpBB3 -*/ -class parse_message extends bbcode_firstpass -{ - var $attachment_data = array(); - var $filename_data = array(); - - // Helps ironing out user error - var $message_status = ''; - - var $allow_img_bbcode = true; - var $allow_flash_bbcode = true; - var $allow_quote_bbcode = true; - var $allow_url_bbcode = true; - - var $mode; - - /** - * Init - give message here or manually - */ - function parse_message($message = '') - { - // Init BBCode UID - $this->bbcode_uid = substr(base_convert(unique_id(), 16, 36), 0, BBCODE_UID_LEN); - $this->message = $message; - } - - /** - * Parse Message - */ - function parse($allow_bbcode, $allow_magic_url, $allow_smilies, $allow_img_bbcode = true, $allow_flash_bbcode = true, $allow_quote_bbcode = true, $allow_url_bbcode = true, $update_this_message = true, $mode = 'post') - { - $mode = ($mode != 'post') ? 'sig' : 'post'; - - $this->mode = $mode; - - $this->allow_img_bbcode = $allow_img_bbcode; - $this->allow_flash_bbcode = $allow_flash_bbcode; - $this->allow_quote_bbcode = $allow_quote_bbcode; - $this->allow_url_bbcode = $allow_url_bbcode; - - // If false, then $this->message won't be altered, the text will be returned instead. - if (!$update_this_message) - { - $tmp_message = $this->message; - $return_message = &$this->message; - } - - if ($this->message_status == 'display') - { - $this->decode_message(); - } - - // Do some general 'cleanup' first before processing message, - // e.g. remove excessive newlines(?), smilies(?) - $match = array('#(script|about|applet|activex|chrome):#i'); - $replace = array("\\1:"); - $this->message = preg_replace($match, $replace, trim($this->message)); - - // Message length check. 0 disables this check completely. - if (phpbb::$config['max_' . $mode . '_chars'] > 0) - { - $msg_len = ($mode == 'post') ? utf8_strlen($this->message) : utf8_strlen(preg_replace('#\[\/?[a-z\*\+\-]+(=[\S]+)?\]#ius', ' ', $this->message)); - - if ((!$msg_len && $mode !== 'sig') || phpbb::$config['max_' . $mode . '_chars'] && $msg_len > phpbb::$config['max_' . $mode . '_chars']) - { - $this->warn_msg[] = (!$msg_len) ? phpbb::$user->lang['TOO_FEW_CHARS'] : sprintf(phpbb::$user->lang['TOO_MANY_CHARS_' . strtoupper($mode)], $msg_len, phpbb::$config['max_' . $mode . '_chars']); - return (!$update_this_message) ? $return_message : $this->warn_msg; - } - } - - // Prepare BBcode (just prepares some tags for better parsing) - if ($allow_bbcode && strpos($this->message, '[') !== false) - { - $this->bbcode_init(); - $disallow = array('img', 'flash', 'quote', 'url'); - foreach ($disallow as $bool) - { - if (!${'allow_' . $bool . '_bbcode'}) - { - $this->bbcodes[$bool]['disabled'] = true; - } - } - - $this->prepare_bbcodes(); - } - - // Parse smilies - if ($allow_smilies) - { - $this->smilies(phpbb::$config['max_' . $mode . '_smilies']); - } - - $num_urls = 0; - - // Parse BBCode - if ($allow_bbcode && strpos($this->message, '[') !== false) - { - $this->parse_bbcode(); - $num_urls += $this->parsed_items['url']; - } - - // Parse URL's - if ($allow_magic_url) - { - $this->magic_url(generate_board_url()); - - if (phpbb::$config['max_' . $mode . '_urls']) - { - $num_urls += preg_match_all('#\<!-- ([lmwe]) --\>.*?\<!-- \1 --\>#', $this->message, $matches); - } - } - - // Check for "empty" message. We do not check here for maximum length, because bbcode, smilies, etc. can add to the length. - // The maximum length check happened before any parsings. - if ($mode !== 'sig' && utf8_clean_string($this->message) === '') - { - $this->warn_msg[] = $user->lang['TOO_FEW_CHARS']; - return (!$update_this_message) ? $return_message : $this->warn_msg; - } - - // Check number of links - if (phpbb::$config['max_' . $mode . '_urls'] && $num_urls > phpbb::$config['max_' . $mode . '_urls']) - { - $this->warn_msg[] = sprintf(phpbb::$user->lang['TOO_MANY_URLS'], phpbb::$config['max_' . $mode . '_urls']); - return (!$update_this_message) ? $return_message : $this->warn_msg; - } - - if (!$update_this_message) - { - unset($this->message); - $this->message = $tmp_message; - return $return_message; - } - - $this->message_status = 'parsed'; - return false; - } - - /** - * Formatting text for display - */ - function format_display($allow_bbcode, $allow_magic_url, $allow_smilies, $update_this_message = true) - { - // If false, then the parsed message get returned but internal message not processed. - if (!$update_this_message) - { - $tmp_message = $this->message; - $return_message = &$this->message; - } - - if ($this->message_status == 'plain') - { - // Force updating message - of course. - $this->parse($allow_bbcode, $allow_magic_url, $allow_smilies, $this->allow_img_bbcode, $this->allow_flash_bbcode, $this->allow_quote_bbcode, $this->allow_url_bbcode, true); - } - - // Replace naughty words such as farty pants - $this->message = censor_text($this->message); - - // Parse BBcode - if ($allow_bbcode) - { - $this->bbcode_cache_init(); - - // We are giving those parameters to be able to use the bbcode class on its own - $this->bbcode_second_pass($this->message, $this->bbcode_uid); - } - - $this->message = bbcode_nl2br($this->message); - $this->message = smiley_text($this->message, !$allow_smilies); - - if (!$update_this_message) - { - unset($this->message); - $this->message = $tmp_message; - return $return_message; - } - - $this->message_status = 'display'; - return false; - } - - /** - * Decode message to be placed back into form box - */ - function decode_message($custom_bbcode_uid = '', $update_this_message = true) - { - // If false, then the parsed message get returned but internal message not processed. - if (!$update_this_message) - { - $tmp_message = $this->message; - $return_message = &$this->message; - } - - ($custom_bbcode_uid) ? decode_message($this->message, $custom_bbcode_uid) : decode_message($this->message, $this->bbcode_uid); - - if (!$update_this_message) - { - unset($this->message); - $this->message = $tmp_message; - return $return_message; - } - - $this->message_status = 'plain'; - return false; - } - - /** - * Replace magic urls of form http://xxx.xxx., www.xxx. and xxx@xxx.xxx. - * Cuts down displayed size of link if over 50 chars, turns absolute links - * into relative versions when the server/script path matches the link - */ - function magic_url($server_url) - { - // We use the global make_clickable function - $this->message = make_clickable($this->message, $server_url); - } - - /** - * Parse Smilies - */ - function smilies($max_smilies = 0) - { - static $match; - static $replace; - - // See if the static arrays have already been filled on an earlier invocation - if (!is_array($match)) - { - $match = $replace = array(); - - // NOTE: obtain_* function? chaching the table contents? - - // For now setting the ttl to 10 minutes - $sql = 'SELECT * - FROM ' . SMILIES_TABLE . ' - ORDER BY ' . phpbb::$db->sql_function('length_varchar', 'code') . ' DESC'; - $result = phpbb::$db->sql_query($sql, 600); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if (empty($row['code'])) - { - continue; - } - - // (assertion) - $match[] = '(?<=^|[\n .])' . preg_quote($row['code'], '#') . '(?![^<>]*>)'; - $replace[] = '<!-- s' . $row['code'] . ' --><img src="{SMILIES_PATH}/' . $row['smiley_url'] . '" alt="' . $row['code'] . '" title="' . $row['emotion'] . '" /><!-- s' . $row['code'] . ' -->'; - } - phpbb::$db->sql_freeresult($result); - } - - if (sizeof($match)) - { - if ($max_smilies) - { - $num_matches = preg_match_all('#' . implode('|', $match) . '#', $this->message, $matches); - unset($matches); - - if ($num_matches !== false && $num_matches > $max_smilies) - { - $this->warn_msg[] = sprintf(phpbb::$user->lang['TOO_MANY_SMILIES'], $max_smilies); - return; - } - } - - // Make sure the delimiter # is added in front and at the end of every element within $match - $this->message = trim(preg_replace(explode(chr(0), '#' . implode('#' . chr(0) . '#', $match) . '#'), $replace, $this->message)); - } - } - - /** - * Parse Attachments - */ - function parse_attachments($form_name, $mode, $forum_id, $submit, $preview, $refresh, $is_message = false) - { - $error = array(); - - $num_attachments = sizeof($this->attachment_data); - $this->filename_data['filecomment'] = utf8_normalize_nfc(request_var('filecomment', '', true)); - $upload_file = (isset($_FILES[$form_name]) && $_FILES[$form_name]['name'] != 'none' && trim($_FILES[$form_name]['name'])) ? true : false; - - $add_file = phpbb_request::is_set_post('add_file'); - $delete_file = phpbb_request::is_set_post('delete_file'); - - // First of all adjust comments if changed - $actual_comment_list = utf8_normalize_nfc(request_var('comment_list', array(''), true)); - - foreach ($actual_comment_list as $comment_key => $comment) - { - if (!isset($this->attachment_data[$comment_key])) - { - continue; - } - - if ($this->attachment_data[$comment_key]['attach_comment'] != $actual_comment_list[$comment_key]) - { - $this->attachment_data[$comment_key]['attach_comment'] = $actual_comment_list[$comment_key]; - } - } - - $cfg = array(); - $cfg['max_attachments'] = ($is_message) ? phpbb::$config['max_attachments_pm'] : phpbb::$config['max_attachments']; - $forum_id = ($is_message) ? 0 : $forum_id; - - if ($submit && in_array($mode, array('post', 'reply', 'quote', 'edit')) && $upload_file) - { - if ($num_attachments < $cfg['max_attachments'] || phpbb::$acl->acl_get('a_') || phpbb::$acl->acl_get('m_', $forum_id)) - { - $filedata = upload_attachment($form_name, $forum_id, false, '', $is_message); - $error = $filedata['error']; - - if ($filedata['post_attach'] && !sizeof($error)) - { - $sql_ary = array( - 'physical_filename' => $filedata['physical_filename'], - 'attach_comment' => $this->filename_data['filecomment'], - 'real_filename' => $filedata['real_filename'], - 'extension' => $filedata['extension'], - 'mimetype' => $filedata['mimetype'], - 'filesize' => $filedata['filesize'], - 'filetime' => $filedata['filetime'], - 'thumbnail' => $filedata['thumbnail'], - 'is_orphan' => 1, - 'in_message' => ($is_message) ? 1 : 0, - 'poster_id' => phpbb::$user->data['user_id'], - ); - - phpbb::$db->sql_query('INSERT INTO ' . ATTACHMENTS_TABLE . ' ' . phpbb::$db->sql_build_array('INSERT', $sql_ary)); - - $new_entry = array( - 'attach_id' => phpbb::$db->sql_nextid(), - 'is_orphan' => 1, - 'real_filename' => $filedata['real_filename'], - 'attach_comment'=> $this->filename_data['filecomment'], - ); - - $this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data); - $this->message = preg_replace('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#e', "'[attachment='.(\\1 + 1).']\\2[/attachment]'", $this->message); - - $this->filename_data['filecomment'] = ''; - - // This Variable is set to false here, because Attachments are entered into the - // Database in two modes, one if the id_list is 0 and the second one if post_attach is true - // Since post_attach is automatically switched to true if an Attachment got added to the filesystem, - // but we are assigning an id of 0 here, we have to reset the post_attach variable to false. - // - // This is very relevant, because it could happen that the post got not submitted, but we do not - // know this circumstance here. We could be at the posting page or we could be redirected to the entered - // post. :) - $filedata['post_attach'] = false; - } - } - else - { - $error[] = sprintf(phpbb::$user->lang['TOO_MANY_ATTACHMENTS'], $cfg['max_attachments']); - } - } - - if ($preview || $refresh || sizeof($error)) - { - // Perform actions on temporary attachments - if ($delete_file) - { - include_once(PHPBB_ROOT_PATH . 'includes/functions_admin.' . PHP_EXT); - - $index = array_keys(request_var('delete_file', array(0 => 0))); - $index = (!empty($index)) ? $index[0] : false; - - if ($index !== false && !empty($this->attachment_data[$index])) - { - // delete selected attachment - if ($this->attachment_data[$index]['is_orphan']) - { - $sql = 'SELECT attach_id, physical_filename, thumbnail - FROM ' . ATTACHMENTS_TABLE . ' - WHERE attach_id = ' . (int) $this->attachment_data[$index]['attach_id'] . ' - AND is_orphan = 1 - AND poster_id = ' . phpbb::$user->data['user_id']; - $result = phpbb::$db->sql_query($sql); - $row = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - if ($row) - { - phpbb_unlink($row['physical_filename'], 'file'); - - if ($row['thumbnail']) - { - phpbb_unlink($row['physical_filename'], 'thumbnail'); - } - - phpbb::$db->sql_query('DELETE FROM ' . ATTACHMENTS_TABLE . ' WHERE attach_id = ' . (int) $this->attachment_data[$index]['attach_id']); - } - } - else - { - delete_attachments('attach', array(intval($this->attachment_data[$index]['attach_id']))); - } - - unset($this->attachment_data[$index]); - $this->message = preg_replace('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#e', "(\\1 == \$index) ? '' : ((\\1 > \$index) ? '[attachment=' . (\\1 - 1) . ']\\2[/attachment]' : '\\0')", $this->message); - - // Reindex Array - $this->attachment_data = array_values($this->attachment_data); - } - } - else if (($add_file || $preview) && $upload_file) - { - if ($num_attachments < $cfg['max_attachments'] || phpbb::$acl->acl_gets('m_', 'a_', $forum_id)) - { - $filedata = upload_attachment($form_name, $forum_id, false, '', $is_message); - $error = array_merge($error, $filedata['error']); - - if (!sizeof($error)) - { - $sql_ary = array( - 'physical_filename' => $filedata['physical_filename'], - 'attach_comment' => $this->filename_data['filecomment'], - 'real_filename' => $filedata['real_filename'], - 'extension' => $filedata['extension'], - 'mimetype' => $filedata['mimetype'], - 'filesize' => $filedata['filesize'], - 'filetime' => $filedata['filetime'], - 'thumbnail' => $filedata['thumbnail'], - 'is_orphan' => 1, - 'in_message' => ($is_message) ? 1 : 0, - 'poster_id' => phpbb::$user->data['user_id'], - ); - - phpbb::$db->sql_query('INSERT INTO ' . ATTACHMENTS_TABLE . ' ' . phpbb::$db->sql_build_array('INSERT', $sql_ary)); - - $new_entry = array( - 'attach_id' => phpbb::$db->sql_nextid(), - 'is_orphan' => 1, - 'real_filename' => $filedata['real_filename'], - 'attach_comment'=> $this->filename_data['filecomment'], - ); - - $this->attachment_data = array_merge(array(0 => $new_entry), $this->attachment_data); - $this->message = preg_replace('#\[attachment=([0-9]+)\](.*?)\[\/attachment\]#e', "'[attachment='.(\\1 + 1).']\\2[/attachment]'", $this->message); - $this->filename_data['filecomment'] = ''; - } - } - else - { - $error[] = sprintf(phpbb::$user->lang['TOO_MANY_ATTACHMENTS'], $cfg['max_attachments']); - } - } - } - - foreach ($error as $error_msg) - { - $this->warn_msg[] = $error_msg; - } - } - - /** - * Get Attachment Data - */ - function get_submitted_attachment_data($check_user_id = false) - { - $this->filename_data['filecomment'] = utf8_normalize_nfc(request_var('filecomment', '', true)); - $attachment_data = phpbb_request::variable('attachment_data', array(0 => array('' => '')), true, phpbb_request::POST); - $this->attachment_data = array(); - - $check_user_id = ($check_user_id === false) ? phpbb::$user->data['user_id'] : $check_user_id; - - if (!sizeof($attachment_data)) - { - return; - } - - $not_orphan = $orphan = array(); - - foreach ($attachment_data as $pos => $var_ary) - { - if ($var_ary['is_orphan']) - { - $orphan[(int) $var_ary['attach_id']] = $pos; - } - else - { - $not_orphan[(int) $var_ary['attach_id']] = $pos; - } - } - - // Regenerate already posted attachments - if (sizeof($not_orphan)) - { - // Get the attachment data, based on the poster id... - $sql = 'SELECT attach_id, is_orphan, real_filename, attach_comment - FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('attach_id', array_keys($not_orphan)) . ' - AND poster_id = ' . $check_user_id; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $pos = $not_orphan[(int) $row['attach_id']]; - $this->attachment_data[$pos] = $row; - $this->attachment_data[$pos]['attach_comment'] = utf8_normalize_nfc($attachment_data[$pos]['attach_comment']); - - unset($not_orphan[(int) $row['attach_id']]); - } - phpbb::$db->sql_freeresult($result); - } - - if (sizeof($not_orphan)) - { - trigger_error('NO_ACCESS_ATTACHMENT', E_USER_ERROR); - } - - // Regenerate newly uploaded attachments - if (sizeof($orphan)) - { - $sql = 'SELECT attach_id, is_orphan, real_filename, attach_comment - FROM ' . ATTACHMENTS_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('attach_id', array_keys($orphan)) . ' - AND poster_id = ' . phpbb::$user->data['user_id'] . ' - AND is_orphan = 1'; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $pos = $orphan[(int) $row['attach_id']]; - $this->attachment_data[$pos] = $row; - $this->attachment_data[$pos]['attach_comment'] = utf8_normalize_nfc($attachment_data[$pos]['attach_comment']); - - unset($orphan[(int) $row['attach_id']]); - } - phpbb::$db->sql_freeresult($result); - } - - if (sizeof($orphan)) - { - trigger_error('NO_ACCESS_ATTACHMENT', E_USER_ERROR); - } - - ksort($this->attachment_data); - } - - /** - * Parse Poll - */ - function parse_poll(&$poll) - { - $poll_max_options = $poll['poll_max_options']; - - // Parse Poll Option text ;) - $tmp_message = $this->message; - $this->message = $poll['poll_option_text']; - $bbcode_bitfield = $this->bbcode_bitfield; - - $poll['poll_option_text'] = $this->parse($poll['enable_bbcode'], (phpbb::$config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, phpbb::$config['allow_post_links'], false); - - $bbcode_bitfield = base64_encode(base64_decode($bbcode_bitfield) | base64_decode($this->bbcode_bitfield)); - $this->message = $tmp_message; - - // Parse Poll Title - $tmp_message = $this->message; - $this->message = $poll['poll_title']; - $this->bbcode_bitfield = $bbcode_bitfield; - - $poll['poll_options'] = explode("\n", trim($poll['poll_option_text'])); - $poll['poll_options_size'] = sizeof($poll['poll_options']); - - if (!$poll['poll_title'] && $poll['poll_options_size']) - { - $this->warn_msg[] = phpbb::$user->lang['NO_POLL_TITLE']; - } - else - { - if (utf8_strlen(preg_replace('#\[\/?[a-z\*\+\-]+(=[\S]+)?\]#ius', ' ', $this->message)) > 100) - { - $this->warn_msg[] = phpbb::$user->lang['POLL_TITLE_TOO_LONG']; - } - $poll['poll_title'] = $this->parse($poll['enable_bbcode'], (phpbb::$config['allow_post_links']) ? $poll['enable_urls'] : false, $poll['enable_smilies'], $poll['img_status'], false, false, phpbb::$config['allow_post_links'], false); - if (strlen($poll['poll_title']) > 255) - { - $this->warn_msg[] = phpbb::$user->lang['POLL_TITLE_COMP_TOO_LONG']; - } - } - - $this->bbcode_bitfield = base64_encode(base64_decode($bbcode_bitfield) | base64_decode($this->bbcode_bitfield)); - $this->message = $tmp_message; - unset($tmp_message); - - if (sizeof($poll['poll_options']) == 1) - { - $this->warn_msg[] = phpbb::$user->lang['TOO_FEW_POLL_OPTIONS']; - } - else if ($poll['poll_options_size'] > (int) phpbb::$config['max_poll_options']) - { - $this->warn_msg[] = phpbb::$user->lang['TOO_MANY_POLL_OPTIONS']; - } - else if ($poll_max_options > $poll['poll_options_size']) - { - $this->warn_msg[] = phpbb::$user->lang['TOO_MANY_USER_OPTIONS']; - } - - $poll['poll_max_options'] = ($poll['poll_max_options'] < 1) ? 1 : (($poll['poll_max_options'] > phpbb::$config['max_poll_options']) ? phpbb::$config['max_poll_options'] : $poll['poll_max_options']); - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/search/fulltext_mysql.php b/phpBB/includes/search/fulltext_mysql.php deleted file mode 100644 index 8c4b8f3c7d..0000000000 --- a/phpBB/includes/search/fulltext_mysql.php +++ /dev/null @@ -1,767 +0,0 @@ -<?php -/** -* -* @package search -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* @ignore -*/ -include_once(PHPBB_ROOT_PATH . 'includes/search/search.' . PHP_EXT); - -/** -* fulltext_mysql -* Fulltext search for MySQL -* @package search -*/ -class fulltext_mysql extends search_backend -{ - private $stats = array(); - public $word_length = array(); - private $split_words = array(); - public $search_query; - public $common_words = array(); - - function __construct(&$error) - { - $this->word_length = array('min' => phpbb::$config['fulltext_mysql_min_word_len'], 'max' => phpbb::$config['fulltext_mysql_max_word_len']); - - $error = false; - } - - /** - * Checks for correct MySQL version and stores min/max word length in the config - */ - public function init() - { - $result = phpbb::$db->sql_query('SHOW TABLE STATUS LIKE \'' . POSTS_TABLE . '\''); - $info = phpbb::$db->sql_fetchrow($result); - phpbb::$db->sql_freeresult($result); - - $engine = ''; - if (isset($info['Engine'])) - { - $engine = $info['Engine']; - } - else if (isset($info['Type'])) - { - $engine = $info['Type']; - } - - if ($engine != 'MyISAM') - { - return phpbb::$user->lang['FULLTEXT_MYSQL_NOT_MYISAM']; - } - - $sql = 'SHOW VARIABLES - LIKE \'ft\_%\''; - $result = phpbb::$db->sql_query($sql); - - $mysql_info = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $mysql_info[$row['Variable_name']] = $row['Value']; - } - phpbb::$db->sql_freeresult($result); - - set_config('fulltext_mysql_max_word_len', $mysql_info['ft_max_word_len']); - set_config('fulltext_mysql_min_word_len', $mysql_info['ft_min_word_len']); - - return false; - } - - /** - * Splits keywords entered by a user into an array of words stored in $this->split_words - * Stores the tidied search query in $this->search_query - * - * @param string &$keywords Contains the keyword as entered by the user - * @param string $terms is either 'all' or 'any' - * @return bool false if no valid keywords were found and otherwise true - */ - public function split_keywords(&$keywords, $terms) - { - if ($terms == 'all') - { - $match = array('#\sand\s#iu', '#\sor\s#iu', '#\snot\s#iu', '#\+#', '#-#', '#\|#'); - $replace = array(' +', ' |', ' -', ' +', ' -', ' |'); - - $keywords = preg_replace($match, $replace, $keywords); - } - - // Filter out as above - $split_keywords = preg_replace("#[\n\r\t]+#", ' ', trim(htmlspecialchars_decode($keywords))); - - // Split words - $split_keywords = preg_replace('#([^\p{L}\p{N}\'*"()])#u', '$1$1', str_replace('\'\'', '\' \'', trim($split_keywords))); - - $matches = array(); - preg_match_all('#(?:[^\p{L}\p{N}*"()]|^)([+\-|]?(?:[\p{L}\p{N}*"()]+\'?)*[\p{L}\p{N}*"()])(?:[^\p{L}\p{N}*"()]|$)#u', $split_keywords, $matches); - $this->split_words = $matches[1]; - - // We limit the number of allowed keywords to minimize load on the database - if (phpbb::$config['max_num_search_keywords'] && sizeof($this->split_words) > phpbb::$config['max_num_search_keywords']) - { - trigger_error(phpbb::$user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', phpbb::$config['max_num_search_keywords'], sizeof($this->split_words))); - } - - // to allow phrase search, we need to concatenate quoted words - $tmp_split_words = array(); - $phrase = ''; - foreach ($this->split_words as $word) - { - if ($phrase) - { - $phrase .= ' ' . $word; - if (strpos($word, '"') !== false && substr_count($word, '"') % 2 == 1) - { - $tmp_split_words[] = $phrase; - $phrase = ''; - } - } - else if (strpos($word, '"') !== false && substr_count($word, '"') % 2 == 1) - { - $phrase = $word; - } - else - { - $tmp_split_words[] = $word . ' '; - } - } - if ($phrase) - { - $tmp_split_words[] = $phrase; - } - - $this->split_words = $tmp_split_words; - - unset($tmp_split_words); - unset($phrase); - - foreach ($this->split_words as $i => $word) - { - $clean_word = preg_replace('#^[+\-|"]#', '', $word); - - // check word length - $clean_len = utf8_strlen(str_replace('*', '', $clean_word)); - if (($clean_len < phpbb::$config['fulltext_mysql_min_word_len']) || ($clean_len > phpbb::$config['fulltext_mysql_max_word_len'])) - { - $this->common_words[] = $word; - unset($this->split_words[$i]); - } - } - - if ($terms == 'any') - { - $this->search_query = ''; - foreach ($this->split_words as $word) - { - if ((strpos($word, '+') === 0) || (strpos($word, '-') === 0) || (strpos($word, '|') === 0)) - { - $word = substr($word, 1); - } - $this->search_query .= $word . ' '; - } - } - else - { - $this->search_query = ''; - foreach ($this->split_words as $word) - { - if ((strpos($word, '+') === 0) || (strpos($word, '-') === 0)) - { - $this->search_query .= $word . ' '; - } - else if (strpos($word, '|') === 0) - { - $this->search_query .= substr($word, 1) . ' '; - } - else - { - $this->search_query .= '+' . $word . ' '; - } - } - } - - $this->search_query = utf8_htmlspecialchars($this->search_query); - - if ($this->search_query) - { - $this->split_words = array_values($this->split_words); - sort($this->split_words); - return true; - } - return false; - } - - /** - * Turns text into an array of words - */ - private function split_message($text) - { - // Split words - $text = preg_replace('#([^\p{L}\p{N}\'*])#u', '$1$1', str_replace('\'\'', '\' \'', trim($text))); - - $matches = array(); - preg_match_all('#(?:[^\p{L}\p{N}*]|^)([+\-|]?(?:[\p{L}\p{N}*]+\'?)*[\p{L}\p{N}*])(?:[^\p{L}\p{N}*]|$)#u', $text, $matches); - $text = $matches[1]; - - // remove too short or too long words - $text = array_values($text); - for ($i = 0, $n = sizeof($text); $i < $n; $i++) - { - $text[$i] = trim($text[$i]); - if (utf8_strlen($text[$i]) < phpbb::$config['fulltext_mysql_min_word_len'] || utf8_strlen($text[$i]) > phpbb::$config['fulltext_mysql_max_word_len']) - { - unset($text[$i]); - } - } - - return array_values($text); - } - - /** - * Performs a search on keywords depending on display specific params. You have to run split_keywords() first. - * - * @param string $type contains either posts or topics depending on what should be searched for - * @param string &$fields contains either titleonly (topic titles should be searched), msgonly (only message bodies should be searched), firstpost (only subject and body of the first post should be searched) or all (all post bodies and subjects should be searched) - * @param string &$terms is either 'all' (use query as entered, words without prefix should default to "have to be in field") or 'any' (ignore search query parts and just return all posts that contain any of the specified words) - * @param array &$sort_by_sql contains SQL code for the ORDER BY part of a query - * @param string &$sort_key is the key of $sort_by_sql for the selected sorting - * @param string &$sort_dir is either a or d representing ASC and DESC - * @param string &$sort_days specifies the maximum amount of days a post may be old - * @param array &$ex_fid_ary specifies an array of forum ids which should not be searched - * @param array &$m_approve_fid_ary specifies an array of forum ids in which the searcher is allowed to view unapproved posts - * @param int &$topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched - * @param array &$author_ary an array of author ids if the author should be ignored during the search the array is empty - * @param array &$id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered - * @param int $start indicates the first index of the page - * @param int $per_page number of ids each page is supposed to contain - * @return boolean|int total number of results - * - * @access public - */ - public function keyword_search($type, &$fields, &$terms, &$sort_by_sql, &$sort_key, &$sort_dir, &$sort_days, &$ex_fid_ary, &$m_approve_fid_ary, &$topic_id, &$author_ary, &$id_ary, $start, $per_page) - { - // No keywords? No posts. - if (!$this->search_query) - { - return false; - } - - // generate a search_key from all the options to identify the results - $search_key = md5(implode('#', array( - implode(', ', $this->split_words), - $type, - $fields, - $terms, - $sort_days, - $sort_key, - $topic_id, - implode(',', $ex_fid_ary), - implode(',', $m_approve_fid_ary), - implode(',', $author_ary) - ))); - - // try reading the results from cache - $result_count = 0; - if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == self::SEARCH_RESULT_IN_CACHE) - { - return $result_count; - } - - $id_ary = array(); - - $join_topic = ($type == 'posts') ? false : true; - - // Build sql strings for sorting - $sql_sort = $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC'); - $sql_sort_table = $sql_sort_join = ''; - - switch ($sql_sort[0]) - { - case 'u': - $sql_sort_table = USERS_TABLE . ' u, '; - $sql_sort_join = ($type == 'posts') ? ' AND u.user_id = p.poster_id ' : ' AND u.user_id = t.topic_poster '; - break; - - case 't': - $join_topic = true; - break; - - case 'f': - $sql_sort_table = FORUMS_TABLE . ' f, '; - $sql_sort_join = ' AND f.forum_id = p.forum_id '; - break; - } - - // Build some display specific sql strings - switch ($fields) - { - case 'titleonly': - $sql_match = 'p.post_subject'; - $sql_match_where = ' AND p.post_id = t.topic_first_post_id'; - $join_topic = true; - break; - - case 'msgonly': - $sql_match = 'p.post_text'; - $sql_match_where = ''; - break; - - case 'firstpost': - $sql_match = 'p.post_subject, p.post_text'; - $sql_match_where = ' AND p.post_id = t.topic_first_post_id'; - $join_topic = true; - break; - - default: - $sql_match = 'p.post_subject, p.post_text'; - $sql_match_where = ''; - break; - } - - if (!sizeof($m_approve_fid_ary)) - { - $m_approve_fid_sql = ' AND p.post_approved = 1'; - } - else if ($m_approve_fid_ary === array(-1)) - { - $m_approve_fid_sql = ''; - } - else - { - $m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . phpbb::$db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')'; - } - - $sql_select = (!$result_count) ? 'SQL_CALC_FOUND_ROWS ' : ''; - $sql_select = ($type == 'posts') ? $sql_select . 'p.post_id' : 'DISTINCT ' . $sql_select . 't.topic_id'; - $sql_from = ($join_topic) ? TOPICS_TABLE . ' t, ' : ''; - $field = ($type == 'posts') ? 'post_id' : 'topic_id'; - $sql_author = (sizeof($author_ary) == 1) ? ' = ' . $author_ary[0] : 'IN (' . implode(', ', $author_ary) . ')'; - - $sql_where_options = $sql_sort_join; - $sql_where_options .= ($topic_id) ? ' AND p.topic_id = ' . $topic_id : ''; - $sql_where_options .= ($join_topic) ? ' AND t.topic_id = p.topic_id' : ''; - $sql_where_options .= (sizeof($ex_fid_ary)) ? ' AND ' . phpbb::$db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; - $sql_where_options .= $m_approve_fid_sql; - $sql_where_options .= (sizeof($author_ary)) ? ' AND p.poster_id ' . $sql_author : ''; - $sql_where_options .= ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : ''; - $sql_where_options .= $sql_match_where; - - $sql = "SELECT $sql_select - FROM $sql_from$sql_sort_table" . POSTS_TABLE . " p - WHERE MATCH ($sql_match) AGAINST ('" . phpbb::$db->sql_escape(htmlspecialchars_decode($this->search_query)) . "' IN BOOLEAN MODE) - $sql_where_options - ORDER BY $sql_sort"; - $result = phpbb::$db->sql_query_limit($sql, phpbb::$config['search_block_size'], $start); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $id_ary[] = $row[$field]; - } - phpbb::$db->sql_freeresult($result); - - $id_ary = array_unique($id_ary); - - if (!sizeof($id_ary)) - { - return false; - } - - // if the total result count is not cached yet, retrieve it from the db - if (!$result_count) - { - $sql = 'SELECT FOUND_ROWS() as result_count'; - $result = phpbb::$db->sql_query($sql); - $result_count = (int) phpbb::$db->sql_fetchfield('result_count'); - phpbb::$db->sql_freeresult($result); - - if (!$result_count) - { - return false; - } - } - - // store the ids, from start on then delete anything that isn't on the current page because we only need ids for one page - $this->save_ids($search_key, implode(' ', $this->split_words), $author_ary, $result_count, $id_ary, $start, $sort_dir); - $id_ary = array_slice($id_ary, 0, (int) $per_page); - - return $result_count; - } - - /** - * Performs a search on an author's posts without caring about message contents. Depends on display specific params - * - * @param array &$id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered - * @param int $start indicates the first index of the page - * @param int $per_page number of ids each page is supposed to contain - * @return total number of results - */ - public function author_search($type, $firstpost_only, &$sort_by_sql, &$sort_key, &$sort_dir, &$sort_days, &$ex_fid_ary, &$m_approve_fid_ary, &$topic_id, &$author_ary, &$id_ary, $start, $per_page) - { - // No author? No posts. - if (!sizeof($author_ary)) - { - return 0; - } - - // generate a search_key from all the options to identify the results - $search_key = md5(implode('#', array( - '', - $type, - ($firstpost_only) ? 'firstpost' : '', - '', - '', - $sort_days, - $sort_key, - $topic_id, - implode(',', $ex_fid_ary), - implode(',', $m_approve_fid_ary), - implode(',', $author_ary) - ))); - - // try reading the results from cache - $result_count = 0; - if ($this->obtain_ids($search_key, $result_count, $id_ary, $start, $per_page, $sort_dir) == self::SEARCH_RESULT_IN_CACHE) - { - return $result_count; - } - - $id_ary = array(); - - // Create some display specific sql strings - $sql_author = phpbb::$db->sql_in_set('p.poster_id', $author_ary); - $sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . phpbb::$db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; - $sql_topic_id = ($topic_id) ? ' AND p.topic_id = ' . (int) $topic_id : ''; - $sql_time = ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : ''; - $sql_firstpost = ($firstpost_only) ? ' AND p.post_id = t.topic_first_post_id' : ''; - - // Build sql strings for sorting - $sql_sort = $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC'); - $sql_sort_table = $sql_sort_join = ''; - switch ($sql_sort[0]) - { - case 'u': - $sql_sort_table = USERS_TABLE . ' u, '; - $sql_sort_join = ($type == 'posts') ? ' AND u.user_id = p.poster_id ' : ' AND u.user_id = t.topic_poster '; - break; - - case 't': - $sql_sort_table = ($type == 'posts' && !$firstpost_only) ? TOPICS_TABLE . ' t, ' : ''; - $sql_sort_join = ($type == 'posts' && !$firstpost_only) ? ' AND t.topic_id = p.topic_id ' : ''; - break; - - case 'f': - $sql_sort_table = FORUMS_TABLE . ' f, '; - $sql_sort_join = ' AND f.forum_id = p.forum_id '; - break; - } - - if (!sizeof($m_approve_fid_ary)) - { - $m_approve_fid_sql = ' AND p.post_approved = 1'; - } - else if ($m_approve_fid_ary == array(-1)) - { - $m_approve_fid_sql = ''; - } - else - { - $m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . phpbb::$db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')'; - } - - // If the cache was completely empty count the results - $calc_results = ($result_count) ? '' : 'SQL_CALC_FOUND_ROWS '; - - // Build the query for really selecting the post_ids - if ($type == 'posts') - { - $sql = "SELECT {$calc_results}p.post_id - FROM " . $sql_sort_table . POSTS_TABLE . ' p' . (($firstpost_only) ? ', ' . TOPICS_TABLE . ' t ' : ' ') . " - WHERE $sql_author - $sql_topic_id - $sql_firstpost - $m_approve_fid_sql - $sql_fora - $sql_sort_join - $sql_time - ORDER BY $sql_sort"; - $field = 'post_id'; - } - else - { - $sql = "SELECT {$calc_results}t.topic_id - FROM " . $sql_sort_table . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p - WHERE $sql_author - $sql_topic_id - $sql_firstpost - $m_approve_fid_sql - $sql_fora - AND t.topic_id = p.topic_id - $sql_sort_join - $sql_time - GROUP BY t.topic_id - ORDER BY $sql_sort"; - $field = 'topic_id'; - } - - // Only read one block of posts from the db and then cache it - $result = phpbb::$db->sql_query_limit($sql, phpbb::$config['search_block_size'], $start); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $id_ary[] = $row[$field]; - } - phpbb::$db->sql_freeresult($result); - - // retrieve the total result count if needed - if (!$result_count) - { - $sql = 'SELECT FOUND_ROWS() as result_count'; - $result = phpbb::$db->sql_query($sql); - $result_count = (int) phpbb::$db->sql_fetchfield('result_count'); - phpbb::$db->sql_freeresult($result); - - if (!$result_count) - { - return false; - } - } - - if (sizeof($id_ary)) - { - $this->save_ids($search_key, '', $author_ary, $result_count, $id_ary, $start, $sort_dir); - $id_ary = array_slice($id_ary, 0, $per_page); - - return $result_count; - } - return false; - } - - /** - * Destroys cached search results, that contained one of the new words in a post so the results won't be outdated. - * - * @param string $mode contains the post mode: edit, post, reply, quote ... - */ - public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id) - { - // Split old and new post/subject to obtain array of words - $split_text = $this->split_message($message); - $split_title = ($subject) ? $this->split_message($subject) : array(); - - $words = array_unique(array_merge($split_text, $split_title)); - - unset($split_text); - unset($split_title); - - // destroy cached search results containing any of the words removed or added - $this->destroy_cache($words, array($poster_id)); - - unset($words); - } - - /** - * Destroy cached results, that might be outdated after deleting a post - */ - public function index_remove($post_ids, $author_ids, $forum_ids) - { - $this->destroy_cache(array(), $author_ids); - } - - /** - * Destroy old cache entries - */ - public function tidy() - { - // destroy too old cached search results - $this->destroy_cache(array()); - - set_config('search_last_gc', time(), true); - } - - /** - * Create fulltext index - */ - public function create_index($acp_module, $u_action) - { - // Make sure we can actually use MySQL with fulltext indexes - if ($error = $this->init()) - { - return $error; - } - - if (empty($this->stats)) - { - $this->get_stats(); - } - - $alter = array(); - - if (!isset($this->stats['post_subject'])) - { - //$alter[] = 'MODIFY post_subject varchar(100) COLLATE utf8_unicode_ci DEFAULT \'\' NOT NULL'; - $alter[] = 'ADD FULLTEXT (post_subject)'; - } - - if (!isset($this->stats['post_text'])) - { - $alter[] = 'MODIFY post_text mediumtext COLLATE utf8_unicode_ci NOT NULL'; - $alter[] = 'ADD FULLTEXT (post_text)'; - } - - if (!isset($this->stats['post_content'])) - { - $alter[] = 'ADD FULLTEXT post_content (post_subject, post_text)'; - } - - if (sizeof($alter)) - { - phpbb::$db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' ' . implode(', ', $alter)); - } - - phpbb::$db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); - - return false; - } - - /** - * Drop fulltext index - */ - public function delete_index($acp_module, $u_action) - { - // Make sure we can actually use MySQL with fulltext indexes - if ($error = $this->init()) - { - return $error; - } - - if (empty($this->stats)) - { - $this->get_stats(); - } - - $alter = array(); - - if (isset($this->stats['post_subject'])) - { - $alter[] = 'DROP INDEX post_subject'; - } - - if (isset($this->stats['post_text'])) - { - $alter[] = 'DROP INDEX post_text'; - } - - if (isset($this->stats['post_content'])) - { - $alter[] = 'DROP INDEX post_content'; - } - - if (sizeof($alter)) - { - phpbb::$db->sql_query('ALTER TABLE ' . POSTS_TABLE . ' ' . implode(', ', $alter)); - } - - phpbb::$db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); - - return false; - } - - /** - * Returns true if both FULLTEXT indexes exist - */ - public function index_created() - { - if (empty($this->stats)) - { - $this->get_stats(); - } - - return (isset($this->stats['post_text']) && isset($this->stats['post_subject']) && isset($this->stats['post_content'])) ? true : false; - } - - /** - * Returns an associative array containing information about the indexes - */ - public function index_stats() - { - if (empty($this->stats)) - { - $this->get_stats(); - } - - return array( - phpbb::$user->lang['FULLTEXT_MYSQL_TOTAL_POSTS'] => ($this->index_created()) ? $this->stats['total_posts'] : 0, - ); - } - - private function get_stats() - { - if (phpbb::$db->dbms_type !== 'mysql') - { - $this->stats = array(); - return; - } - - $sql = 'SHOW INDEX - FROM ' . POSTS_TABLE; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - // deal with older MySQL versions which didn't use Index_type - $index_type = (isset($row['Index_type'])) ? $row['Index_type'] : $row['Comment']; - - if ($index_type == 'FULLTEXT') - { - if ($row['Key_name'] == 'post_text') - { - $this->stats['post_text'] = $row; - } - else if ($row['Key_name'] == 'post_subject') - { - $this->stats['post_subject'] = $row; - } - else if ($row['Key_name'] == 'post_content') - { - $this->stats['post_content'] = $row; - } - } - } - phpbb::$db->sql_freeresult($result); - - $sql = 'SELECT COUNT(post_id) as total_posts - FROM ' . POSTS_TABLE; - $result = phpbb::$db->sql_query($sql); - $this->stats['total_posts'] = (int) phpbb::$db->sql_fetchfield('total_posts'); - phpbb::$db->sql_freeresult($result); - } - - /** - * Display nothing, we force UTF-8 support in all versions of PHP - */ - function acp() - { - $tpl = ''; - - // These are fields required in the config table - return array( - 'tpl' => $tpl, - 'config' => array() - ); - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/search/fulltext_native.php b/phpBB/includes/search/fulltext_native.php deleted file mode 100644 index a2cb8936b5..0000000000 --- a/phpBB/includes/search/fulltext_native.php +++ /dev/null @@ -1,1667 +0,0 @@ -<?php -/** -* -* @package search -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* @ignore -*/ -include_once(PHPBB_ROOT_PATH . 'includes/search/search.' . PHP_EXT); - -/** -* fulltext_native -* phpBB's own db driven fulltext search, version 2 -* @package search -*/ -class fulltext_native extends search_backend -{ - private $stats = array(); - public $word_length = array(); - public $search_query; - public $common_words = array(); - - private $must_contain_ids = array(); - private $must_not_contain_ids = array(); - private $must_exclude_one_ids = array(); - - /** - * Initialises the fulltext_native search backend with min/max word length and makes sure the UTF-8 normalizer is loaded. - * - * @param boolean|string &$error is passed by reference and should either be set to false on success or an error message on failure. - * - * @access public - */ - function __construct(&$error) - { - $this->word_length = array('min' => phpbb::$config['fulltext_native_min_chars'], 'max' => phpbb::$config['fulltext_native_max_chars']); - - /** - * Load the UTF tools - */ - if (!class_exists('utf_normalizer')) - { - include(PHPBB_ROOT_PATH . 'includes/utf/utf_normalizer.' . PHP_EXT); - } - - - $error = false; - } - - /** - * This function fills $this->search_query with the cleaned user search query. - * - * If $terms is 'any' then the words will be extracted from the search query - * and combined with | inside brackets. They will afterwards be treated like - * an standard search query. - * - * Then it analyses the query and fills the internal arrays $must_not_contain_ids, - * $must_contain_ids and $must_exclude_one_ids which are later used by keyword_search(). - * - * @param string $keywords contains the search query string as entered by the user - * @param string $terms is either 'all' (use search query as entered, default words to 'must be contained in post') - * or 'any' (find all posts containing at least one of the given words) - * @return boolean false if no valid keywords were found and otherwise true - * - * @access public - */ - public function split_keywords($keywords, $terms) - { - $keywords = trim($this->cleanup($keywords, '+-|()*')); - - // allow word|word|word without brackets - if ((strpos($keywords, ' ') === false) && (strpos($keywords, '|') !== false) && (strpos($keywords, '(') === false)) - { - $keywords = '(' . $keywords . ')'; - } - - $open_bracket = $space = false; - for ($i = 0, $n = strlen($keywords); $i < $n; $i++) - { - if ($open_bracket !== false) - { - switch ($keywords[$i]) - { - case ')': - if ($open_bracket + 1 == $i) - { - $keywords[$i - 1] = '|'; - $keywords[$i] = '|'; - } - $open_bracket = false; - break; - case '(': - $keywords[$i] = '|'; - break; - case '+': - case '-': - case ' ': - $keywords[$i] = '|'; - break; - } - } - else - { - switch ($keywords[$i]) - { - case ')': - $keywords[$i] = ' '; - break; - case '(': - $open_bracket = $i; - $space = false; - break; - case '|': - $keywords[$i] = ' '; - break; - case '-': - case '+': - $space = $keywords[$i]; - break; - case ' ': - if ($space !== false) - { - $keywords[$i] = $space; - } - break; - default: - $space = false; - } - } - } - - if ($open_bracket) - { - $keywords .= ')'; - } - - $match = array( - '# +#', - '#\|\|+#', - '#(\+|\-)(?:\+|\-)+#', - '#\(\|#', - '#\|\)#', - ); - $replace = array( - ' ', - '|', - '$1', - '(', - ')', - ); - - $keywords = preg_replace($match, $replace, $keywords); - $num_keywords = sizeof(explode(' ', $keywords)); - - // We limit the number of allowed keywords to minimize load on the database - if (phpbb::$config['max_num_search_keywords'] && $num_keywords > phpbb::$config['max_num_search_keywords']) - { - trigger_error(phpbb::$user->lang('MAX_NUM_SEARCH_KEYWORDS_REFINE', phpbb::$config['max_num_search_keywords'], $num_keywords)); - } - - // $keywords input format: each word separated by a space, words in a bracket are not separated - - // the user wants to search for any word, convert the search query - if ($terms == 'any') - { - $words = array(); - - preg_match_all('#([^\\s+\\-|()]+)(?:$|[\\s+\\-|()])#u', $keywords, $words); - if (sizeof($words[1])) - { - $keywords = '(' . implode('|', $words[1]) . ')'; - } - } - - // set the search_query which is shown to the user - $this->search_query = $keywords; - - $exact_words = array(); - preg_match_all('#([^\\s+\\-|*()]+)(?:$|[\\s+\\-|()])#u', $keywords, $exact_words); - $exact_words = $exact_words[1]; - - $common_ids = $words = array(); - - if (sizeof($exact_words)) - { - $sql = 'SELECT word_id, word_text, word_common - FROM ' . SEARCH_WORDLIST_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('word_text', $exact_words); - $result = phpbb::$db->sql_query($sql); - - // store an array of words and ids, remove common words - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($row['word_common']) - { - $this->common_words[] = $row['word_text']; - $common_ids[$row['word_text']] = (int) $row['word_id']; - continue; - } - - $words[$row['word_text']] = (int) $row['word_id']; - } - phpbb::$db->sql_freeresult($result); - } - unset($exact_words); - - // now analyse the search query, first split it using the spaces - $query = explode(' ', $keywords); - - $this->must_contain_ids = array(); - $this->must_not_contain_ids = array(); - $this->must_exclude_one_ids = array(); - - $mode = ''; - $ignore_no_id = true; - - foreach ($query as $word) - { - if (empty($word)) - { - continue; - } - - // words which should not be included - if ($word[0] == '-') - { - $word = substr($word, 1); - - // a group of which at least one may not be in the resulting posts - if ($word[0] == '(') - { - $word = array_unique(explode('|', substr($word, 1, -1))); - $mode = 'must_exclude_one'; - } - // one word which should not be in the resulting posts - else - { - $mode = 'must_not_contain'; - } - $ignore_no_id = true; - } - // words which have to be included - else - { - // no prefix is the same as a +prefix - if ($word[0] == '+') - { - $word = substr($word, 1); - } - - // a group of words of which at least one word should be in every resulting post - if ($word[0] == '(') - { - $word = array_unique(explode('|', substr($word, 1, -1))); - } - $ignore_no_id = false; - $mode = 'must_contain'; - } - - if (empty($word)) - { - continue; - } - - // if this is an array of words then retrieve an id for each - if (is_array($word)) - { - $non_common_words = array(); - $id_words = array(); - foreach ($word as $i => $word_part) - { - if (strpos($word_part, '*') !== false) - { - $id_words[] = '\'' . phpbb::$db->sql_escape(str_replace('*', '%', $word_part)) . '\''; - $non_common_words[] = $word_part; - } - else if (isset($words[$word_part])) - { - $id_words[] = $words[$word_part]; - $non_common_words[] = $word_part; - } - else - { - $len = utf8_strlen($word_part); - if ($len < $this->word_length['min'] || $len > $this->word_length['max']) - { - $this->common_words[] = $word_part; - } - } - } - if (sizeof($id_words)) - { - sort($id_words); - if (sizeof($id_words) > 1) - { - $this->{$mode . '_ids'}[] = $id_words; - } - else - { - $mode = ($mode == 'must_exclude_one') ? 'must_not_contain' : $mode; - $this->{$mode . '_ids'}[] = $id_words[0]; - } - } - // throw an error if we shall not ignore unexistant words - else if (!$ignore_no_id && sizeof($non_common_words)) - { - trigger_error(phpbb::$user->lang('WORDS_IN_NO_POST', implode(', ', $non_common_words))); - } - unset($non_common_words); - } - // else we only need one id - else if (($wildcard = strpos($word, '*') !== false) || isset($words[$word])) - { - if ($wildcard) - { - $len = utf8_strlen(str_replace('*', '', $word)); - if ($len >= $this->word_length['min'] && $len <= $this->word_length['max']) - { - $this->{$mode . '_ids'}[] = '\'' . phpbb::$db->sql_escape(str_replace('*', '%', $word)) . '\''; - } - else - { - $this->common_words[] = $word; - } - } - else - { - $this->{$mode . '_ids'}[] = $words[$word]; - } - } - // throw an error if we shall not ignore unexistant words - else if (!$ignore_no_id) - { - if (!isset($common_ids[$word])) - { - $len = utf8_strlen($word); - if ($len >= $this->word_length['min'] && $len <= $this->word_length['max']) - { - trigger_error(phpbb::$db->lang('WORD_IN_NO_POST', $word)); - } - else - { - $this->common_words[] = $word; - } - } - } - else - { - $len = utf8_strlen($word); - if ($len < $this->word_length['min'] || $len > $this->word_length['max']) - { - $this->common_words[] = $word; - } - } - } - - // we can't search for negatives only - if (!sizeof($this->must_contain_ids)) - { - return false; - } - - sort($this->must_contain_ids); - sort($this->must_not_contain_ids); - sort($this->must_exclude_one_ids); - - if (!empty($this->search_query)) - { - return true; - } - return false; - } - - /** - * Performs a search on keywords depending on display specific params. You have to run split_keywords() first. - * - * @param string $type contains either posts or topics depending on what should be searched for - * @param string &$fields contains either titleonly (topic titles should be searched), msgonly (only message bodies should be searched), firstpost (only subject and body of the first post should be searched) or all (all post bodies and subjects should be searched) - * @param string &$terms is either 'all' (use query as entered, words without prefix should default to "have to be in field") or 'any' (ignore search query parts and just return all posts that contain any of the specified words) - * @param array &$sort_by_sql contains SQL code for the ORDER BY part of a query - * @param string &$sort_key is the key of $sort_by_sql for the selected sorting - * @param string &$sort_dir is either a or d representing ASC and DESC - * @param string &$sort_days specifies the maximum amount of days a post may be old - * @param array &$ex_fid_ary specifies an array of forum ids which should not be searched - * @param array &$m_approve_fid_ary specifies an array of forum ids in which the searcher is allowed to view unapproved posts - * @param int &$topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched - * @param array &$author_ary an array of author ids if the author should be ignored during the search the array is empty - * @param array &$id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered - * @param int $start indicates the first index of the page - * @param int $per_page number of ids each page is supposed to contain - * @return boolean|int total number of results - * - * @access public - */ - public function keyword_search($type, &$fields, &$terms, &$sort_by_sql, &$sort_key, &$sort_dir, &$sort_days, &$ex_fid_ary, &$m_approve_fid_ary, &$topic_id, &$author_ary, &$id_ary, $start, $per_page) - { - // No keywords? No posts. - if (empty($this->search_query)) - { - return false; - } - - // generate a search_key from all the options to identify the results - $search_key = md5(implode('#', array( - serialize($this->must_contain_ids), - serialize($this->must_not_contain_ids), - serialize($this->must_exclude_one_ids), - $type, - $fields, - $terms, - $sort_days, - $sort_key, - $topic_id, - implode(',', $ex_fid_ary), - implode(',', $m_approve_fid_ary), - implode(',', $author_ary) - ))); - - // try reading the results from cache - $total_results = 0; - if ($this->obtain_ids($search_key, $total_results, $id_ary, $start, $per_page, $sort_dir) == self::SEARCH_RESULT_IN_CACHE) - { - return $total_results; - } - - $id_ary = array(); - - $sql_where = array(); - $group_by = false; - $m_num = 0; - $w_num = 0; - - $sql_array = array( - 'SELECT' => ($type == 'posts') ? 'p.post_id' : 'p.topic_id', - 'FROM' => array( - SEARCH_WORDMATCH_TABLE => array(), - SEARCH_WORDLIST_TABLE => array(), - ), - 'LEFT_JOIN' => array(array( - 'FROM' => array(POSTS_TABLE => 'p'), - 'ON' => 'm0.post_id = p.post_id', - )), - ); - - $title_match = ''; - $group_by = true; - // Build some display specific sql strings - switch ($fields) - { - case 'titleonly': - $title_match = 'title_match = 1'; - $group_by = false; - // no break - case 'firstpost': - $sql_array['FROM'][TOPICS_TABLE] = 't'; - $sql_where[] = 'p.post_id = t.topic_first_post_id'; - break; - - case 'msgonly': - $title_match = 'title_match = 0'; - $group_by = false; - break; - } - - if ($type == 'topics') - { - if (!isset($sql_array['FROM'][TOPICS_TABLE])) - { - $sql_array['FROM'][TOPICS_TABLE] = 't'; - $sql_where[] = 'p.topic_id = t.topic_id'; - } - $group_by = true; - } - - /** - * @todo Add a query optimizer (handle stuff like "+(4|3) +4") - */ - - foreach ($this->must_contain_ids as $subquery) - { - if (is_array($subquery)) - { - $group_by = true; - - $word_id_sql = array(); - $word_ids = array(); - foreach ($subquery as $id) - { - if (is_string($id)) - { - $sql_array['LEFT_JOIN'][] = array( - 'FROM' => array(SEARCH_WORDLIST_TABLE => 'w' . $w_num), - 'ON' => "w$w_num.word_text LIKE $id" - ); - $word_ids[] = "w$w_num.word_id"; - - $w_num++; - } - else - { - $word_ids[] = $id; - } - } - - $sql_where[] = phpbb::$db->sql_in_set("m$m_num.word_id", $word_ids); - - unset($word_id_sql); - unset($word_ids); - } - else if (is_string($subquery)) - { - $sql_array['FROM'][SEARCH_WORDLIST_TABLE][] = 'w' . $w_num; - - $sql_where[] = "w$w_num.word_text LIKE $subquery"; - $sql_where[] = "m$m_num.word_id = w$w_num.word_id"; - - $group_by = true; - $w_num++; - } - else - { - $sql_where[] = "m$m_num.word_id = $subquery"; - } - - $sql_array['FROM'][SEARCH_WORDMATCH_TABLE][] = 'm' . $m_num; - - if ($title_match) - { - $sql_where[] = "m$m_num.$title_match"; - } - - if ($m_num != 0) - { - $sql_where[] = "m$m_num.post_id = m0.post_id"; - } - $m_num++; - } - - foreach ($this->must_not_contain_ids as $key => $subquery) - { - if (is_string($subquery)) - { - $sql_array['LEFT_JOIN'][] = array( - 'FROM' => array(SEARCH_WORDLIST_TABLE => 'w' . $w_num), - 'ON' => "w$w_num.word_text LIKE $subquery" - ); - - $this->must_not_contain_ids[$key] = "w$w_num.word_id"; - - $group_by = true; - $w_num++; - } - } - - if (sizeof($this->must_not_contain_ids)) - { - $sql_array['LEFT_JOIN'][] = array( - 'FROM' => array(SEARCH_WORDMATCH_TABLE => 'm' . $m_num), - 'ON' => phpbb::$db->sql_in_set("m$m_num.word_id", $this->must_not_contain_ids) . (($title_match) ? " AND m$m_num.$title_match" : '') . " AND m$m_num.post_id = m0.post_id" - ); - - $sql_where[] = "m$m_num.word_id IS NULL"; - $m_num++; - } - - foreach ($this->must_exclude_one_ids as $ids) - { - $is_null_joins = array(); - foreach ($ids as $id) - { - if (is_string($id)) - { - $sql_array['LEFT_JOIN'][] = array( - 'FROM' => array(SEARCH_WORDLIST_TABLE => 'w' . $w_num), - 'ON' => "w$w_num.word_text LIKE $id" - ); - $id = "w$w_num.word_id"; - - $group_by = true; - $w_num++; - } - - $sql_array['LEFT_JOIN'][] = array( - 'FROM' => array(SEARCH_WORDMATCH_TABLE => 'm' . $m_num), - 'ON' => "m$m_num.word_id = $id AND m$m_num.post_id = m0.post_id" . (($title_match) ? " AND m$m_num.$title_match" : '') - ); - $is_null_joins[] = "m$m_num.word_id IS NULL"; - - $m_num++; - } - $sql_where[] = '(' . implode(' OR ', $is_null_joins) . ')'; - } - - if (!sizeof($m_approve_fid_ary)) - { - $sql_where[] = 'p.post_approved = 1'; - } - else if ($m_approve_fid_ary !== array(-1)) - { - $sql_where[] = '(p.post_approved = 1 OR ' . phpbb::$db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')'; - } - - if ($topic_id) - { - $sql_where[] = 'p.topic_id = ' . $topic_id; - } - - if (sizeof($author_ary)) - { - $sql_where[] = phpbb::$db->sql_in_set('p.poster_id', $author_ary); - } - - if (sizeof($ex_fid_ary)) - { - $sql_where[] = phpbb::$db->sql_in_set('p.forum_id', $ex_fid_ary, true); - } - - if ($sort_days) - { - $sql_where[] = 'p.post_time >= ' . (time() - ($sort_days * 86400)); - } - - $sql_array['WHERE'] = implode(' AND ', $sql_where); - - $is_mysql = false; - // if the total result count is not cached yet, retrieve it from the db - if (!$total_results) - { - $sql = ''; - $sql_array_count = $sql_array; - - if (phpbb::$db->dbms_type === 'mysql') - { - $sql_array_copy = $sql_array; - - // $sql_array['SELECT'] = 'SQL_CALC_FOUND_ROWS ' . $sql_array['SELECT']; - $sql_array_copy['SELECT'] = 'SQL_CALC_FOUND_ROWS p.post_id '; - - $is_mysql = true; - } - else - { - if (!phpbb::$db->count_distinct) - { - $sql_array_count['SELECT'] = ($type == 'posts') ? 'DISTINCT p.post_id' : 'DISTINCT p.topic_id'; - $sql = 'SELECT COUNT(' . (($type == 'posts') ? 'post_id' : 'topic_id') . ') as total_results - FROM (' . phpbb::$db->sql_build_query('SELECT', $sql_array_count) . ')'; - } - - $sql_array_count['SELECT'] = ($type == 'posts') ? 'COUNT(DISTINCT p.post_id) AS total_results' : 'COUNT(DISTINCT p.topic_id) AS total_results'; - $sql = (!$sql) ? phpbb::$db->sql_build_query('SELECT', $sql_array_count) : $sql; - - $result = phpbb::$db->sql_query($sql); - $total_results = (int) phpbb::$db->sql_fetchfield('total_results'); - phpbb::$db->sql_freeresult($result); - - if (!$total_results) - { - return false; - } - } - - unset($sql_array_count, $sql); - } - - // Build sql strings for sorting - $sql_sort = $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC'); - - switch ($sql_sort[0]) - { - case 'u': - $sql_array['FROM'][USERS_TABLE] = 'u'; - $sql_where[] = 'u.user_id = p.poster_id '; - break; - - case 't': - if (!isset($sql_array['FROM'][TOPICS_TABLE])) - { - $sql_array['FROM'][TOPICS_TABLE] = 't'; - $sql_where[] = 'p.topic_id = t.topic_id'; - } - break; - - case 'f': - $sql_array['FROM'][FORUMS_TABLE] = 'f'; - $sql_where[] = 'f.forum_id = p.forum_id'; - break; - } - - $sql_array['WHERE'] = implode(' AND ', $sql_where); - $sql_array['GROUP_BY'] = ($group_by) ? (($type == 'posts') ? 'p.post_id' : 'p.topic_id') . ', ' . $sort_by_sql[$sort_key] : ''; - $sql_array['ORDER_BY'] = $sql_sort; - - unset($sql_where, $sql_sort, $group_by); - - $sql = phpbb::$db->sql_build_query('SELECT', $sql_array); - $result = phpbb::$db->sql_query_limit($sql, phpbb::$config['search_block_size'], $start); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $id_ary[] = $row[(($type == 'posts') ? 'post_id' : 'topic_id')]; - } - phpbb::$db->sql_freeresult($result); - - if (!sizeof($id_ary)) - { - return false; - } - - // if we use mysql and the total result count is not cached yet, retrieve it from the db - if (!$total_results && $is_mysql && !empty($sql_array_copy)) - { - $sql = phpbb::$db->sql_build_query('SELECT', $sql_array_copy); - unset($sql_array_copy); - - phpbb::$db->sql_query($sql); - phpbb::$db->sql_freeresult($result); - - $sql = 'SELECT FOUND_ROWS() as total_results'; - $result = phpbb::$db->sql_query($sql); - $total_results = (int) phpbb::$db->sql_fetchfield('total_results'); - phpbb::$db->sql_freeresult($result); - - if (!$total_results) - { - return false; - } - } - - // store the ids, from start on then delete anything that isn't on the current page because we only need ids for one page - $this->save_ids($search_key, $this->search_query, $author_ary, $total_results, $id_ary, $start, $sort_dir); - $id_ary = array_slice($id_ary, 0, (int) $per_page); - - return $total_results; - } - - /** - * Performs a search on an author's posts without caring about message contents. Depends on display specific params - * - * @param string $type contains either posts or topics depending on what should be searched for - * @param boolean $firstpost_only if true, only topic starting posts will be considered - * @param array &$sort_by_sql contains SQL code for the ORDER BY part of a query - * @param string &$sort_key is the key of $sort_by_sql for the selected sorting - * @param string &$sort_dir is either a or d representing ASC and DESC - * @param string &$sort_days specifies the maximum amount of days a post may be old - * @param array &$ex_fid_ary specifies an array of forum ids which should not be searched - * @param array &$m_approve_fid_ary specifies an array of forum ids in which the searcher is allowed to view unapproved posts - * @param int &$topic_id is set to 0 or a topic id, if it is not 0 then only posts in this topic should be searched - * @param array &$author_ary an array of author ids - * @param array &$id_ary passed by reference, to be filled with ids for the page specified by $start and $per_page, should be ordered - * @param int $start indicates the first index of the page - * @param int $per_page number of ids each page is supposed to contain - * @return boolean|int total number of results - * - * @access public - */ - public function author_search($type, $firstpost_only, &$sort_by_sql, &$sort_key, &$sort_dir, &$sort_days, &$ex_fid_ary, &$m_approve_fid_ary, &$topic_id, &$author_ary, &$id_ary, $start, $per_page) - { - // No author? No posts. - if (!sizeof($author_ary)) - { - return 0; - } - - // generate a search_key from all the options to identify the results - $search_key = md5(implode('#', array( - '', - $type, - ($firstpost_only) ? 'firstpost' : '', - '', - '', - $sort_days, - $sort_key, - $topic_id, - implode(',', $ex_fid_ary), - implode(',', $m_approve_fid_ary), - implode(',', $author_ary) - ))); - - // try reading the results from cache - $total_results = 0; - if ($this->obtain_ids($search_key, $total_results, $id_ary, $start, $per_page, $sort_dir) == self::SEARCH_RESULT_IN_CACHE) - { - return $total_results; - } - - $id_ary = array(); - - // Create some display specific sql strings - $sql_author = phpbb::$db->sql_in_set('p.poster_id', $author_ary); - $sql_fora = (sizeof($ex_fid_ary)) ? ' AND ' . phpbb::$db->sql_in_set('p.forum_id', $ex_fid_ary, true) : ''; - $sql_time = ($sort_days) ? ' AND p.post_time >= ' . (time() - ($sort_days * 86400)) : ''; - $sql_topic_id = ($topic_id) ? ' AND p.topic_id = ' . (int) $topic_id : ''; - $sql_firstpost = ($firstpost_only) ? ' AND p.post_id = t.topic_first_post_id' : ''; - - // Build sql strings for sorting - $sql_sort = $sort_by_sql[$sort_key] . (($sort_dir == 'a') ? ' ASC' : ' DESC'); - $sql_sort_table = $sql_sort_join = ''; - switch ($sql_sort[0]) - { - case 'u': - $sql_sort_table = USERS_TABLE . ' u, '; - $sql_sort_join = ' AND u.user_id = p.poster_id '; - break; - - case 't': - $sql_sort_table = ($type == 'posts' && !$firstpost_only) ? TOPICS_TABLE . ' t, ' : ''; - $sql_sort_join = ($type == 'posts' && !$firstpost_only) ? ' AND t.topic_id = p.topic_id ' : ''; - break; - - case 'f': - $sql_sort_table = FORUMS_TABLE . ' f, '; - $sql_sort_join = ' AND f.forum_id = p.forum_id '; - break; - } - - if (!sizeof($m_approve_fid_ary)) - { - $m_approve_fid_sql = ' AND p.post_approved = 1'; - } - else if ($m_approve_fid_ary == array(-1)) - { - $m_approve_fid_sql = ''; - } - else - { - $m_approve_fid_sql = ' AND (p.post_approved = 1 OR ' . phpbb::$db->sql_in_set('p.forum_id', $m_approve_fid_ary, true) . ')'; - } - - $select = ($type == 'posts') ? 'p.post_id' : 't.topic_id'; - $is_mysql = false; - - // If the cache was completely empty count the results - if (!$total_results) - { - if (phpbb::$db->dbms_type === 'mysql') - { -// $select = 'SQL_CALC_FOUND_ROWS ' . $select; - $is_mysql = true; - } - else - { - if ($type == 'posts') - { - $sql = 'SELECT COUNT(p.post_id) as total_results - FROM ' . POSTS_TABLE . ' p' . (($firstpost_only) ? ', ' . TOPICS_TABLE . ' t ' : ' ') . " - WHERE $sql_author - $sql_topic_id - $sql_firstpost - $m_approve_fid_sql - $sql_fora - $sql_time"; - } - else - { - if (phpbb::$db->count_distinct) - { - $sql = 'SELECT COUNT(DISTINCT t.topic_id) as total_results'; - } - else - { - $sql = 'SELECT COUNT(topic_id) as total_results - FROM (SELECT DISTINCT t.topic_id'; - } - - $sql .= ' FROM ' . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p - WHERE $sql_author - $sql_topic_id - $sql_firstpost - $m_approve_fid_sql - $sql_fora - AND t.topic_id = p.topic_id - $sql_time" . ((phpbb::$db->count_distinct) ? '' : ')'); - } - $result = phpbb::$db->sql_query($sql); - - $total_results = (int) phpbb::$db->sql_fetchfield('total_results'); - phpbb::$db->sql_freeresult($result); - - if (!$total_results) - { - return false; - } - } - } - - // Build the query for really selecting the post_ids - if ($type == 'posts') - { - $sql = "SELECT $select - FROM " . $sql_sort_table . POSTS_TABLE . ' p' . (($firstpost_only) ? ', ' . TOPICS_TABLE . ' t' : '') . " - WHERE $sql_author - $sql_topic_id - $sql_firstpost - $m_approve_fid_sql - $sql_fora - $sql_sort_join - $sql_time - ORDER BY $sql_sort"; - $field = 'post_id'; - } - else - { - $sql = "SELECT $select - FROM " . $sql_sort_table . TOPICS_TABLE . ' t, ' . POSTS_TABLE . " p - WHERE $sql_author - $sql_topic_id - $sql_firstpost - $m_approve_fid_sql - $sql_fora - AND t.topic_id = p.topic_id - $sql_sort_join - $sql_time - GROUP BY t.topic_id, " . $sort_by_sql[$sort_key] . ' - ORDER BY ' . $sql_sort; - $field = 'topic_id'; - } - - // Only read one block of posts from the db and then cache it - $result = phpbb::$db->sql_query_limit($sql, phpbb::$config['search_block_size'], $start); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $id_ary[] = $row[$field]; - } - phpbb::$db->sql_freeresult($result); - - if (!$total_results && $is_mysql) - { - // Count rows for the executed queries. Replace $select within $sql with SQL_CALC_FOUND_ROWS, and run it. - $sql = str_replace('SELECT ' . $select, 'SELECT DISTINCT SQL_CALC_FOUND_ROWS p.post_id', $sql); - - phpbb::$db->sql_query($sql); - phpbb::$db->sql_freeresult($result); - - $sql = 'SELECT FOUND_ROWS() as total_results'; - $result = phpbb::$db->sql_query($sql); - $total_results = (int) phpbb::$db->sql_fetchfield('total_results'); - phpbb::$db->sql_freeresult($result); - - if (!$total_results) - { - return false; - } - } - - if (sizeof($id_ary)) - { - $this->save_ids($search_key, '', $author_ary, $total_results, $id_ary, $start, $sort_dir); - $id_ary = array_slice($id_ary, 0, $per_page); - - return $total_results; - } - return false; - } - - /** - * Split a text into words of a given length - * - * The text is converted to UTF-8, cleaned up, and split. Then, words that - * conform to the defined length range are returned in an array. - * - * NOTE: duplicates are NOT removed from the return array - * - * @param string $text Text to split, encoded in UTF-8 - * @return array Array of UTF-8 words - * - * @access private - */ - private function split_message($text) - { - $match = $words = array(); - - /** - * Taken from the original code - */ - // Do not index code - $match[] = '#\[code(?:=.*?)?(\:?[0-9a-z]{5,})\].*?\[\/code(\:?[0-9a-z]{5,})\]#is'; - // BBcode - $match[] = '#\[\/?[a-z0-9\*\+\-]+(?:=.*?)?(?::[a-z])?(\:?[0-9a-z]{5,})\]#'; - - $min = $this->word_length['min']; - $max = $this->word_length['max']; - - $isset_min = $min - 1; - - /** - * Clean up the string, remove HTML tags, remove BBCodes - */ - $word = strtok($this->cleanup(preg_replace($match, ' ', strip_tags($text)), -1), ' '); - - while (strlen($word)) - { - if (strlen($word) > 255 || strlen($word) <= $isset_min) - { - /** - * Words longer than 255 bytes are ignored. This will have to be - * changed whenever we change the length of search_wordlist.word_text - * - * Words shorter than $isset_min bytes are ignored, too - */ - $word = strtok(' '); - continue; - } - - $len = utf8_strlen($word); - - /** - * Test whether the word is too short to be indexed. - * - * Note that this limit does NOT apply to CJK and Hangul - */ - if ($len < $min) - { - /** - * Note: this could be optimized. If the codepoint is lower than Hangul's range - * we know that it will also be lower than CJK ranges - */ - if ((strncmp($word, utf_normalizer::UTF8_HANGUL_FIRST, 3) < 0 || strncmp($word, utf_normalizer::UTF8_HANGUL_LAST, 3) > 0) - && (strncmp($word, utf_normalizer::UTF8_CJK_FIRST, 3) < 0 || strncmp($word, utf_normalizer::UTF8_CJK_LAST, 3) > 0) - && (strncmp($word, utf_normalizer::UTF8_CJK_B_FIRST, 4) < 0 || strncmp($word, utf_normalizer::UTF8_CJK_B_LAST, 4) > 0)) - { - $word = strtok(' '); - continue; - } - } - - $words[] = $word; - $word = strtok(' '); - } - - return $words; - } - - /** - * Updates wordlist and wordmatch tables when a message is posted or changed - * - * @param string $mode Contains the post mode: edit, post, reply, quote - * @param int $post_id The id of the post which is modified/created - * @param string &$message New or updated post content - * @param string &$subject New or updated post subject - * @param int $poster_id Post author's user id - * @param int $forum_id The id of the forum in which the post is located - * - * @access public - */ - public function index($mode, $post_id, &$message, &$subject, $poster_id, $forum_id) - { - if (!phpbb::$config['fulltext_native_load_upd']) - { - /** - * The search indexer is disabled, return - */ - return; - } - - // Split old and new post/subject to obtain array of 'words' - $split_text = $this->split_message($message); - $split_title = $this->split_message($subject); - - $cur_words = array('post' => array(), 'title' => array()); - - $words = array(); - if ($mode == 'edit') - { - $words['add']['post'] = array(); - $words['add']['title'] = array(); - $words['del']['post'] = array(); - $words['del']['title'] = array(); - - $sql = 'SELECT w.word_id, w.word_text, m.title_match - FROM ' . SEARCH_WORDLIST_TABLE . ' w, ' . SEARCH_WORDMATCH_TABLE . " m - WHERE m.post_id = $post_id - AND w.word_id = m.word_id"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $which = ($row['title_match']) ? 'title' : 'post'; - $cur_words[$which][$row['word_text']] = $row['word_id']; - } - phpbb::$db->sql_freeresult($result); - - $words['add']['post'] = array_diff($split_text, array_keys($cur_words['post'])); - $words['add']['title'] = array_diff($split_title, array_keys($cur_words['title'])); - $words['del']['post'] = array_diff(array_keys($cur_words['post']), $split_text); - $words['del']['title'] = array_diff(array_keys($cur_words['title']), $split_title); - } - else - { - $words['add']['post'] = $split_text; - $words['add']['title'] = $split_title; - $words['del']['post'] = array(); - $words['del']['title'] = array(); - } - unset($split_text); - unset($split_title); - - // Get unique words from the above arrays - $unique_add_words = array_unique(array_merge($words['add']['post'], $words['add']['title'])); - - // We now have unique arrays of all words to be added and removed and - // individual arrays of added and removed words for text and title. What - // we need to do now is add the new words (if they don't already exist) - // and then add (or remove) matches between the words and this post - if (sizeof($unique_add_words)) - { - $sql = 'SELECT word_id, word_text - FROM ' . SEARCH_WORDLIST_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('word_text', $unique_add_words); - $result = phpbb::$db->sql_query($sql); - - $word_ids = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $word_ids[$row['word_text']] = $row['word_id']; - } - phpbb::$db->sql_freeresult($result); - $new_words = array_diff($unique_add_words, array_keys($word_ids)); - - phpbb::$db->sql_transaction('begin'); - if (sizeof($new_words)) - { - $sql_ary = array(); - - foreach ($new_words as $word) - { - $sql_ary[] = array('word_text' => (string) $word, 'word_count' => 0); - } - phpbb::$db->sql_return_on_error(true); - phpbb::$db->sql_multi_insert(SEARCH_WORDLIST_TABLE, $sql_ary); - phpbb::$db->sql_return_on_error(false); - } - unset($new_words, $sql_ary); - } - else - { - phpbb::$db->sql_transaction('begin'); - } - - // now update the search match table, remove links to removed words and add links to new words - foreach ($words['del'] as $word_in => $word_ary) - { - $title_match = ($word_in == 'title') ? 1 : 0; - - if (sizeof($word_ary)) - { - $sql_in = array(); - foreach ($word_ary as $word) - { - $sql_in[] = $cur_words[$word_in][$word]; - } - - $sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('word_id', $sql_in) . ' - AND post_id = ' . intval($post_id) . " - AND title_match = $title_match"; - phpbb::$db->sql_query($sql); - - $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . ' - SET word_count = word_count - 1 - WHERE ' . phpbb::$db->sql_in_set('word_id', $sql_in) . ' - AND word_count > 0'; - phpbb::$db->sql_query($sql); - - unset($sql_in); - } - } - - phpbb::$db->sql_return_on_error(true); - foreach ($words['add'] as $word_in => $word_ary) - { - $title_match = ($word_in == 'title') ? 1 : 0; - - if (sizeof($word_ary)) - { - $sql = 'INSERT INTO ' . SEARCH_WORDMATCH_TABLE . ' (post_id, word_id, title_match) - SELECT ' . (int) $post_id . ', word_id, ' . (int) $title_match . ' - FROM ' . SEARCH_WORDLIST_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('word_text', $word_ary); - phpbb::$db->sql_query($sql); - - $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . ' - SET word_count = word_count + 1 - WHERE ' . phpbb::$db->sql_in_set('word_text', $word_ary); - phpbb::$db->sql_query($sql); - } - } - phpbb::$db->sql_return_on_error(false); - - phpbb::$db->sql_transaction('commit'); - - // destroy cached search results containing any of the words removed or added - $this->destroy_cache(array_unique(array_merge($words['add']['post'], $words['add']['title'], $words['del']['post'], $words['del']['title'])), array($poster_id)); - - unset($unique_add_words); - unset($words); - unset($cur_words); - } - - /** - * Removes entries from the wordmatch table for the specified post_ids - */ - public function index_remove($post_ids, $author_ids, $forum_ids) - { - if (sizeof($post_ids)) - { - $sql = 'SELECT w.word_id, w.word_text, m.title_match - FROM ' . SEARCH_WORDMATCH_TABLE . ' m, ' . SEARCH_WORDLIST_TABLE . ' w - WHERE ' . phpbb::$db->sql_in_set('m.post_id', $post_ids) . ' - AND w.word_id = m.word_id'; - $result = phpbb::$db->sql_query($sql); - - $message_word_ids = $title_word_ids = $word_texts = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - if ($row['title_match']) - { - $title_word_ids[] = $row['word_id']; - } - else - { - $message_word_ids[] = $row['word_id']; - } - $word_texts[] = $row['word_text']; - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($title_word_ids)) - { - $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . ' - SET word_count = word_count - 1 - WHERE ' . phpbb::$db->sql_in_set('word_id', $title_word_ids) . ' - AND word_count > 0'; - phpbb::$db->sql_query($sql); - } - - if (sizeof($message_word_ids)) - { - $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . ' - SET word_count = word_count - 1 - WHERE ' . phpbb::$db->sql_in_set('word_id', $message_word_ids) . ' - AND word_count > 0'; - phpbb::$db->sql_query($sql); - } - - unset($title_word_ids); - unset($message_word_ids); - - $sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('post_id', $post_ids); - phpbb::$db->sql_query($sql); - } - - $this->destroy_cache(array_unique($word_texts), $author_ids); - } - - /** - * Tidy up indexes: Tag 'common words' and remove - * words no longer referenced in the match table - */ - public function tidy() - { - // Is the fulltext indexer disabled? If yes then we need not - // carry on ... it's okay ... I know when I'm not wanted boo hoo - if (!phpbb::$config['fulltext_native_load_upd']) - { - set_config('search_last_gc', time(), true); - return; - } - - $destroy_cache_words = array(); - - // Remove common words - if (phpbb::$config['num_posts'] >= 100 && phpbb::$config['fulltext_native_common_thres']) - { - $common_threshold = ((double) phpbb::$config['fulltext_native_common_thres']) / 100.0; - // First, get the IDs of common words - $sql = 'SELECT word_id, word_text - FROM ' . SEARCH_WORDLIST_TABLE . ' - WHERE word_count > ' . floor(phpbb::$config['num_posts'] * $common_threshold) . ' - OR word_common = 1'; - $result = phpbb::$db->sql_query($sql); - - $sql_in = array(); - while ($row = phpbb::$db->sql_fetchrow($result)) - { - $sql_in[] = $row['word_id']; - $destroy_cache_words[] = $row['word_text']; - } - phpbb::$db->sql_freeresult($result); - - if (sizeof($sql_in)) - { - // Flag the words - $sql = 'UPDATE ' . SEARCH_WORDLIST_TABLE . ' - SET word_common = 1 - WHERE ' . phpbb::$db->sql_in_set('word_id', $sql_in); - phpbb::$db->sql_query($sql); - - // by setting search_last_gc to the new time here we make sure that if a user reloads because the - // following query takes too long, he won't run into it again - set_config('search_last_gc', time(), true); - - // Delete the matches - $sql = 'DELETE FROM ' . SEARCH_WORDMATCH_TABLE . ' - WHERE ' . phpbb::$db->sql_in_set('word_id', $sql_in); - phpbb::$db->sql_query($sql); - } - unset($sql_in); - } - - if (sizeof($destroy_cache_words)) - { - // destroy cached search results containing any of the words that are now common or were removed - $this->destroy_cache(array_unique($destroy_cache_words)); - } - - set_config('search_last_gc', time(), true); - } - - /** - * Deletes all words from the index - */ - public function delete_index($acp_module, $u_action) - { - if (phpbb::$db->features['truncate']) - { - phpbb::$db->sql_query('TRUNCATE TABLE ' . SEARCH_WORDLIST_TABLE); - phpbb::$db->sql_query('TRUNCATE TABLE ' . SEARCH_WORDMATCH_TABLE); - phpbb::$db->sql_query('TRUNCATE TABLE ' . SEARCH_RESULTS_TABLE); - } - else - { - phpbb::$db->sql_query('DELETE FROM ' . SEARCH_WORDLIST_TABLE); - phpbb::$db->sql_query('DELETE FROM ' . SEARCH_WORDMATCH_TABLE); - phpbb::$db->sql_query('DELETE FROM ' . SEARCH_RESULTS_TABLE); - } - } - - /** - * Returns true if both FULLTEXT indexes exist - */ - public function index_created() - { - if (!sizeof($this->stats)) - { - $this->get_stats(); - } - - return ($this->stats['total_words'] && $this->stats['total_matches']) ? true : false; - } - - /** - * Returns an associative array containing information about the indexes - */ - public function index_stats() - { - if (!sizeof($this->stats)) - { - $this->get_stats(); - } - - return array( - phpbb::$db->lang['TOTAL_WORDS'] => $this->stats['total_words'], - phpbb::$db->lang['TOTAL_MATCHES'] => $this->stats['total_matches'], - ); - } - - private function get_stats() - { - $sql = 'SELECT COUNT(*) as total_words - FROM ' . SEARCH_WORDLIST_TABLE; - $result = phpbb::$db->sql_query($sql); - $this->stats['total_words'] = (int) phpbb::$db->sql_fetchfield('total_words'); - phpbb::$db->sql_freeresult($result); - - $sql = 'SELECT COUNT(*) as total_matches - FROM ' . SEARCH_WORDMATCH_TABLE; - $result = phpbb::$db->sql_query($sql); - $this->stats['total_matches'] = (int) phpbb::$db->sql_fetchfield('total_matches'); - phpbb::$db->sql_freeresult($result); - } - - /** - * Clean up a text to remove non-alphanumeric characters - * - * This method receives a UTF-8 string, normalizes and validates it, replaces all - * non-alphanumeric characters with strings then returns the result. - * - * Any number of "allowed chars" can be passed as a UTF-8 string in NFC. - * - * @param string $text Text to split, in UTF-8 (not normalized or sanitized) - * @param string $allowed_chars String of special chars to allow - * @return string Cleaned up text, only alphanumeric chars are left - * - * @todo normalizer::cleanup being able to be used? - */ - private function cleanup($text, $allowed_chars = null) - { - static $conv = array(), $conv_loaded = array(); - $words = $allow = array(); - - $utf_len_mask = array( - "\xC0" => 2, - "\xD0" => 2, - "\xE0" => 3, - "\xF0" => 4 - ); - - /** - * Replace HTML entities and NCRs - */ - $text = htmlspecialchars_decode(utf8_decode_ncr($text), ENT_QUOTES); - - /** - * Load the UTF-8 normalizer - * - * If we use it more widely, an instance of that class should be held in a - * a global variable instead - */ - utf_normalizer::nfc($text); - - /** - * The first thing we do is: - * - * - convert ASCII-7 letters to lowercase - * - remove the ASCII-7 non-alpha characters - * - remove the bytes that should not appear in a valid UTF-8 string: 0xC0, - * 0xC1 and 0xF5-0xFF - * - * @todo in theory, the third one is already taken care of during normalization and those chars should have been replaced by Unicode replacement chars - */ - $sb_match = "ISTCPAMELRDOJBNHFGVWUQKYXZ\r\n\t!\"#$%&'()*+,-./:;<=>?@[\\]^_`{|}~\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F\xC0\xC1\xF5\xF6\xF7\xF8\xF9\xFA\xFB\xFC\xFD\xFE\xFF"; - $sb_replace = 'istcpamelrdojbnhfgvwuqkyxz '; - - /** - * This is the list of legal ASCII chars, it is automatically extended - * with ASCII chars from $allowed_chars - */ - $legal_ascii = ' eaisntroludcpmghbfvq10xy2j9kw354867z'; - - /** - * Prepare an array containing the extra chars to allow - */ - if (isset($allowed_chars[0])) - { - $pos = 0; - $len = strlen($allowed_chars); - do - { - $c = $allowed_chars[$pos]; - - if ($c < "\x80") - { - /** - * ASCII char - */ - $sb_pos = strpos($sb_match, $c); - if (is_int($sb_pos)) - { - /** - * Remove the char from $sb_match and its corresponding - * replacement in $sb_replace - */ - $sb_match = substr($sb_match, 0, $sb_pos) . substr($sb_match, $sb_pos + 1); - $sb_replace = substr($sb_replace, 0, $sb_pos) . substr($sb_replace, $sb_pos + 1); - $legal_ascii .= $c; - } - - ++$pos; - } - else - { - /** - * UTF-8 char - */ - $utf_len = $utf_len_mask[$c & "\xF0"]; - $allow[substr($allowed_chars, $pos, $utf_len)] = 1; - $pos += $utf_len; - } - } - while ($pos < $len); - } - - $text = strtr($text, $sb_match, $sb_replace); - $ret = ''; - - $pos = 0; - $len = strlen($text); - - do - { - /** - * Do all consecutive ASCII chars at once - */ - if ($spn = strspn($text, $legal_ascii, $pos)) - { - $ret .= substr($text, $pos, $spn); - $pos += $spn; - } - - if ($pos >= $len) - { - return $ret; - } - - /** - * Capture the UTF char - */ - $utf_len = $utf_len_mask[$text[$pos] & "\xF0"]; - $utf_char = substr($text, $pos, $utf_len); - $pos += $utf_len; - - if (($utf_char >= UTF8_HANGUL_FIRST && $utf_char <= UTF8_HANGUL_LAST) - || ($utf_char >= UTF8_CJK_FIRST && $utf_char <= UTF8_CJK_LAST) - || ($utf_char >= UTF8_CJK_B_FIRST && $utf_char <= UTF8_CJK_B_LAST)) - { - /** - * All characters within these ranges are valid - * - * We separate them with a space in order to index each character - * individually - */ - $ret .= ' ' . $utf_char . ' '; - continue; - } - - if (isset($allow[$utf_char])) - { - /** - * The char is explicitly allowed - */ - $ret .= $utf_char; - continue; - } - - if (isset($conv[$utf_char])) - { - /** - * The char is mapped to something, maybe to itself actually - */ - $ret .= $conv[$utf_char]; - continue; - } - - /** - * The char isn't mapped, but did we load its conversion table? - * - * The search indexer table is split into blocks. The block number of - * each char is equal to its codepoint right-shifted for 11 bits. It - * means that out of the 11, 16 or 21 meaningful bits of a 2-, 3- or - * 4- byte sequence we only keep the leftmost 0, 5 or 10 bits. Thus, - * all UTF chars encoded in 2 bytes are in the same first block. - */ - if (isset($utf_char[2])) - { - if (isset($utf_char[3])) - { - /** - * 1111 0nnn 10nn nnnn 10nx xxxx 10xx xxxx - * 0000 0111 0011 1111 0010 0000 - */ - $idx = ((ord($utf_char[0]) & 0x07) << 7) | ((ord($utf_char[1]) & 0x3F) << 1) | ((ord($utf_char[2]) & 0x20) >> 5); - } - else - { - /** - * 1110 nnnn 10nx xxxx 10xx xxxx - * 0000 0111 0010 0000 - */ - $idx = ((ord($utf_char[0]) & 0x07) << 1) | ((ord($utf_char[1]) & 0x20) >> 5); - } - } - else - { - /** - * 110x xxxx 10xx xxxx - * 0000 0000 0000 0000 - */ - $idx = 0; - } - - /** - * Check if the required conv table has been loaded already - */ - if (!isset($conv_loaded[$idx])) - { - $conv_loaded[$idx] = 1; - $file = PHPBB_ROOT_PATH . 'includes/utf/data/search_indexer_' . $idx . '.' . PHP_EXT; - - if (file_exists($file)) - { - $conv += include($file); - } - } - - if (isset($conv[$utf_char])) - { - $ret .= $conv[$utf_char]; - } - else - { - /** - * We add an entry to the conversion table so that we - * don't have to convert to codepoint and perform the checks - * that are above this block - */ - $conv[$utf_char] = ' '; - $ret .= ' '; - } - } - while (1); - - return $ret; - } - - /** - * Returns a list of options for the ACP to display - */ - public function acp() - { - /** - * if we need any options, copied from fulltext_native for now, will have to be adjusted or removed - */ - - $tpl = ' - <dl> - <dt><label for="fulltext_native_load_upd">' . phpbb::$db->lang['YES_SEARCH_UPDATE'] . ':</label><br /><span>' . phpbb::$db->lang['YES_SEARCH_UPDATE_EXPLAIN'] . '</span></dt> - <dd><label><input type="radio" id="fulltext_native_load_upd" name="config[fulltext_native_load_upd]" value="1"' . ((phpbb::$config['fulltext_native_load_upd']) ? ' checked="checked"' : '') . ' class="radio" /> ' . phpbb::$db->lang['YES'] . '</label><label><input type="radio" name="config[fulltext_native_load_upd]" value="0"' . ((!phpbb::$config['fulltext_native_load_upd']) ? ' checked="checked"' : '') . ' class="radio" /> ' . phpbb::$db->lang['NO'] . '</label></dd> - </dl> - <dl> - <dt><label for="fulltext_native_min_chars">' . phpbb::$db->lang['MIN_SEARCH_CHARS'] . ':</label><br /><span>' . phpbb::$db->lang['MIN_SEARCH_CHARS_EXPLAIN'] . '</span></dt> - <dd><input id="fulltext_native_min_chars" type="text" size="3" maxlength="3" name="config[fulltext_native_min_chars]" value="' . (int) phpbb::$config['fulltext_native_min_chars'] . '" /></dd> - </dl> - <dl> - <dt><label for="fulltext_native_max_chars">' . phpbb::$db->lang['MAX_SEARCH_CHARS'] . ':</label><br /><span>' . phpbb::$db->lang['MAX_SEARCH_CHARS_EXPLAIN'] . '</span></dt> - <dd><input id="fulltext_native_max_chars" type="text" size="3" maxlength="3" name="config[fulltext_native_max_chars]" value="' . (int) phpbb::$config['fulltext_native_max_chars'] . '" /></dd> - </dl> - <dl> - <dt><label for="fulltext_native_common_thres">' . phpbb::$db->lang['COMMON_WORD_THRESHOLD'] . ':</label><br /><span>' . phpbb::$db->lang['COMMON_WORD_THRESHOLD_EXPLAIN'] . '</span></dt> - <dd><input id="fulltext_native_common_thres" type="text" size="3" maxlength="3" name="config[fulltext_native_common_thres]" value="' . (int) phpbb::$config['fulltext_native_common_thres'] . '" /> %</dd> - </dl> - '; - - // These are fields required in the config table - return array( - 'tpl' => $tpl, - 'config' => array('fulltext_native_load_upd' => 'bool', 'fulltext_native_min_chars' => 'integer:0:255', 'fulltext_native_max_chars' => 'integer:0:255', 'fulltext_native_common_thres' => 'double:0:100') - ); - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/search/search.php b/phpBB/includes/search/search.php deleted file mode 100644 index 89d5935258..0000000000 --- a/phpBB/includes/search/search.php +++ /dev/null @@ -1,307 +0,0 @@ -<?php -/** -* -* @package search -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -* @ignore -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -/** -* search_backend -* optional base class for search plugins providing simple caching based on ACM -* and functions to retrieve ignore_words and synonyms -* @package search -*/ -class search_backend -{ - const SEARCH_RESULT_NOT_IN_CACHE = 0; - const SEARCH_RESULT_IN_CACHE = 1; - const SEARCH_RESULT_INCOMPLETE = 2; - - public $ignore_words = array(); - public $match_synonym = array(); - public $replace_synonym = array(); - - function __construct(&$error) - { - // This class cannot be used as a search plugin - $error = true; - } - - /** - * Retrieves a language dependend list of words that should be ignored by the search - */ - public function get_ignore_words() - { - if (!sizeof($this->ignore_words)) - { - $words = array(); - - if (file_exists(phpbb::$user->lang_path . phpbb::$user->lang_name . '/search_ignore_words.' . PHP_EXT)) - { - // include the file containing ignore words - include(phpbb::$user->lang_path . phpbb::$user->lang_name . '/search_ignore_words.' . PHP_EXT); - } - - $this->ignore_words = $words; - unset($words); - } - } - - /** - * Stores a list of synonyms that should be replaced in $this->match_synonym and $this->replace_synonym and caches them - */ - public function get_synonyms() - { - if (!sizeof($this->match_synonym)) - { - $synonyms = array(); - - if (file_exists(phpbb::$user->lang_path . phpbb::$user->lang_name . '/search_synonyms.' . PHP_EXT)) - { - // include the file containing synonyms - include(phpbb::$user->lang_path . phpbb::$user->lang_name . '/search_synonyms.' . PHP_EXT); - } - - $this->match_synonym = array_keys($synonyms); - $this->replace_synonym = array_values($synonyms); - - unset($synonyms); - } - } - - /** - * Retrieves cached search results - * - * @param int &$result_count will contain the number of all results for the search (not only for the current page) - * @param array &$id_ary is filled with the ids belonging to the requested page that are stored in the cache - * - * @return int SEARCH_RESULT_NOT_IN_CACHE or SEARCH_RESULT_IN_CACHE or SEARCH_RESULT_INCOMPLETE - */ - protected function obtain_ids($search_key, &$result_count, &$id_ary, $start, $per_page, $sort_dir) - { - if (!($stored_ids = phpbb::$acm->get('search_results_' . $search_key))) - { - // no search results cached for this search_key - return self::SEARCH_RESULT_NOT_IN_CACHE; - } - else - { - $result_count = $stored_ids[-1]; - $reverse_ids = ($stored_ids[-2] != $sort_dir) ? true : false; - $complete = true; - - // change the start to the actual end of the current request if the sort direction differs - // from the dirction in the cache and reverse the ids later - if ($reverse_ids) - { - $start = $result_count - $start - $per_page; - - // the user requested a page past the last index - if ($start < 0) - { - return self::SEARCH_RESULT_NOT_IN_CACHE; - } - } - - for ($i = $start, $n = $start + $per_page; ($i < $n) && ($i < $result_count); $i++) - { - if (!isset($stored_ids[$i])) - { - $complete = false; - } - else - { - $id_ary[] = $stored_ids[$i]; - } - } - unset($stored_ids); - - if ($reverse_ids) - { - $id_ary = array_reverse($id_ary); - } - - if (!$complete) - { - return self::SEARCH_RESULT_INCOMPLETE; - } - return self::SEARCH_RESULT_IN_CACHE; - } - } - - /** - * Caches post/topic ids - * - * @param array &$id_ary contains a list of post or topic ids that shall be cached, the first element - * must have the absolute index $start in the result set. - */ - protected function save_ids($search_key, $keywords, $author_ary, $result_count, &$id_ary, $start, $sort_dir) - { - $length = min(sizeof($id_ary), phpbb::$config['search_block_size']); - - // nothing to cache so exit - if (!$length) - { - return; - } - - $store_ids = array_slice($id_ary, 0, $length); - - // create a new resultset if there is none for this search_key yet - // or add the ids to the existing resultset - if (!($store = phpbb::$acm->get('search_results_' . $search_key))) - { - // add the current keywords to the recent searches in the cache which are listed on the search page - if (!empty($keywords) || sizeof($author_ary)) - { - $sql = 'SELECT search_time - FROM ' . SEARCH_RESULTS_TABLE . ' - WHERE search_key = \'' . phpbb::$db->sql_escape($search_key) . '\''; - $result = phpbb::$db->sql_query($sql); - - if (!phpbb::$db->sql_fetchrow($result)) - { - $sql_ary = array( - 'search_key' => $search_key, - 'search_time' => time(), - 'search_keywords' => $keywords, - 'search_authors' => ' ' . implode(' ', $author_ary) . ' ' - ); - - $sql = 'INSERT INTO ' . SEARCH_RESULTS_TABLE . ' ' . phpbb::$db->sql_build_array('INSERT', $sql_ary); - phpbb::$db->sql_query($sql); - } - phpbb::$db->sql_freeresult($result); - } - - $sql = 'UPDATE ' . USERS_TABLE . ' - SET user_last_search = ' . time() . ' - WHERE user_id = ' . phpbb::$user->data['user_id']; - phpbb::$db->sql_query($sql); - - $store = array(-1 => $result_count, -2 => $sort_dir); - $id_range = range($start, $start + $length - 1); - } - else - { - // we use one set of results for both sort directions so we have to calculate the indizes - // for the reversed array and we also have to reverse the ids themselves - if ($store[-2] != $sort_dir) - { - $store_ids = array_reverse($store_ids); - $id_range = range($store[-1] - $start - $length, $store[-1] - $start - 1); - } - else - { - $id_range = range($start, $start + $length - 1); - } - } - - $store_ids = array_combine($id_range, $store_ids); - - // append the ids - if (is_array($store_ids)) - { - $store += $store_ids; - - // if the cache is too big - if (sizeof($store) - 2 > 20 * phpbb::$config['search_block_size']) - { - // remove everything in front of two blocks in front of the current start index - for ($i = 0, $n = $id_range[0] - 2 * phpbb::$config['search_block_size']; $i < $n; $i++) - { - if (isset($store[$i])) - { - unset($store[$i]); - } - } - - // remove everything after two blocks after the current stop index - end($id_range); - for ($i = $store[-1] - 1, $n = current($id_range) + 2 * phpbb::$config['search_block_size']; $i > $n; $i--) - { - if (isset($store[$i])) - { - unset($store[$i]); - } - } - } - phpbb::$acm->put('search_results_' . $search_key, $store, phpbb::$config['search_store_results']); - - $sql = 'UPDATE ' . SEARCH_RESULTS_TABLE . ' - SET search_time = ' . time() . ' - WHERE search_key = \'' . phpbb::$db->sql_escape($search_key) . '\''; - phpbb::$db->sql_query($sql); - } - - unset($store); - unset($store_ids); - unset($id_range); - } - - /** - * Removes old entries from the search results table and removes searches with keywords that contain a word in $words. - */ - public function destroy_cache($words, $authors = false) - { - // clear all searches that searched for the specified words - if (sizeof($words)) - { - $sql_where = ''; - foreach ($words as $word) - { - $sql_where .= " OR search_keywords " . phpbb::$db->sql_like_expression(phpbb::$db->any_char . $word . phpbb::$db->any_char); - } - - $sql = 'SELECT search_key - FROM ' . SEARCH_RESULTS_TABLE . " - WHERE search_keywords LIKE '%*%' $sql_where"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - phpbb::$acm->destroy('search_results_' . $row['search_key']); - } - phpbb::$db->sql_freeresult($result); - } - - // clear all searches that searched for the specified authors - if (is_array($authors) && sizeof($authors)) - { - $sql_where = ''; - foreach ($authors as $author) - { - $sql_where .= (($sql_where) ? ' OR ' : '') . 'search_authors LIKE \'% ' . (int) $author . ' %\''; - } - - $sql = 'SELECT search_key - FROM ' . SEARCH_RESULTS_TABLE . " - WHERE $sql_where"; - $result = phpbb::$db->sql_query($sql); - - while ($row = phpbb::$db->sql_fetchrow($result)) - { - phpbb::$acm->destroy('search_results_' . $row['search_key']); - } - phpbb::$db->sql_freeresult($result); - } - - $sql = 'DELETE - FROM ' . SEARCH_RESULTS_TABLE . ' - WHERE search_time < ' . (time() - phpbb::$config['search_store_results']); - phpbb::$db->sql_query($sql); - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/utf/data/case_fold_c.php b/phpBB/includes/utf/data/case_fold_c.php deleted file mode 100644 index 00de1ba349..0000000000 --- a/phpBB/includes/utf/data/case_fold_c.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('A'=>'a','B'=>'b','C'=>'c','D'=>'d','E'=>'e','F'=>'f','G'=>'g','H'=>'h','I'=>'i','J'=>'j','K'=>'k','L'=>'l','M'=>'m','N'=>'n','O'=>'o','P'=>'p','Q'=>'q','R'=>'r','S'=>'s','T'=>'t','U'=>'u','V'=>'v','W'=>'w','X'=>'x','Y'=>'y','Z'=>'z','µ'=>'μ','À'=>'à ','Ã'=>'á','Â'=>'â','Ã'=>'ã','Ä'=>'ä','Ã…'=>'Ã¥','Æ'=>'æ','Ç'=>'ç','È'=>'è','É'=>'é','Ê'=>'ê','Ë'=>'ë','ÃŒ'=>'ì','Ã'=>'Ã','ÃŽ'=>'î','Ã'=>'ï','Ã'=>'ð','Ñ'=>'ñ','Ã’'=>'ò','Ó'=>'ó','Ô'=>'ô','Õ'=>'õ','Ö'=>'ö','Ø'=>'ø','Ù'=>'ù','Ú'=>'ú','Û'=>'û','Ü'=>'ü','Ã'=>'ý','Þ'=>'þ','Ä€'=>'Ä','Ä‚'=>'ă','Ä„'=>'Ä…','Ć'=>'ć','Ĉ'=>'ĉ','ÄŠ'=>'Ä‹','ÄŒ'=>'Ä','ÄŽ'=>'Ä','Ä'=>'Ä‘','Ä’'=>'Ä“','Ä”'=>'Ä•','Ä–'=>'Ä—','Ę'=>'Ä™','Äš'=>'Ä›','Äœ'=>'Ä','Äž'=>'ÄŸ','Ä '=>'Ä¡','Ä¢'=>'Ä£','Ĥ'=>'Ä¥','Ħ'=>'ħ','Ĩ'=>'Ä©','Ī'=>'Ä«','Ĭ'=>'Ä','Ä®'=>'į','IJ'=>'ij','Ä´'=>'ĵ','Ķ'=>'Ä·','Ĺ'=>'ĺ','Ä»'=>'ļ','Ľ'=>'ľ','Ä¿'=>'Å€','Å'=>'Å‚','Ń'=>'Å„','Å…'=>'ņ','Ň'=>'ň','ÅŠ'=>'Å‹','ÅŒ'=>'Å','ÅŽ'=>'Å','Å'=>'Å‘','Å’'=>'Å“','Å”'=>'Å•','Å–'=>'Å—','Ř'=>'Å™','Åš'=>'Å›','Åœ'=>'Å','Åž'=>'ÅŸ','Å '=>'Å¡','Å¢'=>'Å£','Ť'=>'Å¥','Ŧ'=>'ŧ','Ũ'=>'Å©','Ū'=>'Å«','Ŭ'=>'Å','Å®'=>'ů','Ű'=>'ű','Ų'=>'ų','Å´'=>'ŵ','Ŷ'=>'Å·','Ÿ'=>'ÿ','Ź'=>'ź','Å»'=>'ż','Ž'=>'ž','Å¿'=>'s','Æ'=>'É“','Æ‚'=>'ƃ','Æ„'=>'Æ…','Ɔ'=>'É”','Ƈ'=>'ƈ','Ɖ'=>'É–','ÆŠ'=>'É—','Æ‹'=>'ÆŒ','ÆŽ'=>'Ç','Æ'=>'É™','Æ'=>'É›','Æ‘'=>'Æ’','Æ“'=>'É ','Æ”'=>'É£','Æ–'=>'É©','Æ—'=>'ɨ','Ƙ'=>'Æ™','Æœ'=>'ɯ','Æ'=>'ɲ','ÆŸ'=>'ɵ','Æ '=>'Æ¡','Æ¢'=>'Æ£','Ƥ'=>'Æ¥','Ʀ'=>'Ê€','Ƨ'=>'ƨ','Æ©'=>'ʃ','Ƭ'=>'Æ','Æ®'=>'ʈ','Ư'=>'ư','Ʊ'=>'ÊŠ','Ʋ'=>'Ê‹','Ƴ'=>'Æ´','Ƶ'=>'ƶ','Æ·'=>'Ê’','Ƹ'=>'ƹ','Ƽ'=>'ƽ','Ç„'=>'dž','Ç…'=>'dž','LJ'=>'lj','Lj'=>'lj','ÇŠ'=>'ÇŒ','Ç‹'=>'ÇŒ','Ç'=>'ÇŽ','Ç'=>'Ç','Ç‘'=>'Ç’','Ç“'=>'Ç”','Ç•'=>'Ç–','Ç—'=>'ǘ','Ç™'=>'Çš','Ç›'=>'Çœ','Çž'=>'ÇŸ','Ç '=>'Ç¡','Ç¢'=>'Ç£','Ǥ'=>'Ç¥','Ǧ'=>'ǧ','Ǩ'=>'Ç©','Ǫ'=>'Ç«','Ǭ'=>'Ç','Ç®'=>'ǯ','DZ'=>'dz','Dz'=>'dz','Ç´'=>'ǵ','Ƕ'=>'Æ•','Ç·'=>'Æ¿','Ǹ'=>'ǹ','Ǻ'=>'Ç»','Ǽ'=>'ǽ','Ǿ'=>'Ç¿','È€'=>'È','È‚'=>'ȃ','È„'=>'È…','Ȇ'=>'ȇ','Ȉ'=>'ȉ','ÈŠ'=>'È‹','ÈŒ'=>'È','ÈŽ'=>'È','È'=>'È‘','È’'=>'È“','È”'=>'È•','È–'=>'È—','Ș'=>'È™','Èš'=>'È›','Èœ'=>'È','Èž'=>'ÈŸ','È '=>'Æž','È¢'=>'È£','Ȥ'=>'È¥','Ȧ'=>'ȧ','Ȩ'=>'È©','Ȫ'=>'È«','Ȭ'=>'È','È®'=>'ȯ','Ȱ'=>'ȱ','Ȳ'=>'ȳ','Ⱥ'=>'â±¥','È»'=>'ȼ','Ƚ'=>'Æš','Ⱦ'=>'ⱦ','É'=>'É‚','Ƀ'=>'Æ€','É„'=>'ʉ','É…'=>'ÊŒ','Ɇ'=>'ɇ','Ɉ'=>'ɉ','ÉŠ'=>'É‹','ÉŒ'=>'É','ÉŽ'=>'É','Í…'=>'ι','Ά'=>'ά','Έ'=>'Î','Ή'=>'ή','Ί'=>'ί','ÎŒ'=>'ÏŒ','ÎŽ'=>'Ï','Î'=>'ÏŽ','Α'=>'α','Î’'=>'β','Γ'=>'γ','Δ'=>'δ','Ε'=>'ε','Ζ'=>'ζ','Η'=>'η','Θ'=>'θ','Ι'=>'ι','Κ'=>'κ','Λ'=>'λ','Μ'=>'μ','Î'=>'ν','Ξ'=>'ξ','Ο'=>'ο','Î '=>'Ï€','Ρ'=>'Ï','Σ'=>'σ','Τ'=>'Ï„','Î¥'=>'Ï…','Φ'=>'φ','Χ'=>'χ','Ψ'=>'ψ','Ω'=>'ω','Ϊ'=>'ÏŠ','Ϋ'=>'Ï‹','Ï‚'=>'σ','Ï'=>'β','Ï‘'=>'θ','Ï•'=>'φ','Ï–'=>'Ï€','Ϙ'=>'Ï™','Ïš'=>'Ï›','Ïœ'=>'Ï','Ïž'=>'ÏŸ','Ï '=>'Ï¡','Ï¢'=>'Ï£','Ϥ'=>'Ï¥','Ϧ'=>'ϧ','Ϩ'=>'Ï©','Ϫ'=>'Ï«','Ϭ'=>'Ï','Ï®'=>'ϯ','ϰ'=>'κ','ϱ'=>'Ï','Ï´'=>'θ','ϵ'=>'ε','Ï·'=>'ϸ','Ϲ'=>'ϲ','Ϻ'=>'Ï»','Ͻ'=>'Í»','Ͼ'=>'ͼ','Ï¿'=>'ͽ','Ѐ'=>'Ñ','Ð'=>'Ñ‘','Ђ'=>'Ñ’','Ѓ'=>'Ñ“','Є'=>'Ñ”','Ð…'=>'Ñ•','І'=>'Ñ–','Ї'=>'Ñ—','Ј'=>'ј','Љ'=>'Ñ™','Њ'=>'Ñš','Ћ'=>'Ñ›','ÐŒ'=>'Ñœ','Ð'=>'Ñ','ÐŽ'=>'Ñž','Ð'=>'ÑŸ','Ð'=>'а','Б'=>'б','Ð’'=>'в','Г'=>'г','Д'=>'д','Е'=>'е','Ж'=>'ж','З'=>'з','И'=>'и','Й'=>'й','К'=>'к','Л'=>'л','М'=>'м','Ð'=>'н','О'=>'о','П'=>'п','Ð '=>'Ñ€','С'=>'Ñ','Т'=>'Ñ‚','У'=>'у','Ф'=>'Ñ„','Ð¥'=>'Ñ…','Ц'=>'ц','Ч'=>'ч','Ш'=>'ш','Щ'=>'щ','Ъ'=>'ÑŠ','Ы'=>'Ñ‹','Ь'=>'ÑŒ','Ð'=>'Ñ','Ю'=>'ÑŽ','Я'=>'Ñ','Ñ '=>'Ñ¡','Ñ¢'=>'Ñ£','Ѥ'=>'Ñ¥','Ѧ'=>'ѧ','Ѩ'=>'Ñ©','Ѫ'=>'Ñ«','Ѭ'=>'Ñ','Ñ®'=>'ѯ','Ѱ'=>'ѱ','Ѳ'=>'ѳ','Ñ´'=>'ѵ','Ѷ'=>'Ñ·','Ѹ'=>'ѹ','Ѻ'=>'Ñ»','Ѽ'=>'ѽ','Ѿ'=>'Ñ¿','Ò€'=>'Ò','ÒŠ'=>'Ò‹','ÒŒ'=>'Ò','ÒŽ'=>'Ò','Ò'=>'Ò‘','Ò’'=>'Ò“','Ò”'=>'Ò•','Ò–'=>'Ò—','Ò˜'=>'Ò™','Òš'=>'Ò›','Òœ'=>'Ò','Òž'=>'ÒŸ','Ò '=>'Ò¡','Ò¢'=>'Ò£','Ò¤'=>'Ò¥','Ò¦'=>'Ò§','Ò¨'=>'Ò©','Òª'=>'Ò«','Ò¬'=>'Ò','Ò®'=>'Ò¯','Ò°'=>'Ò±','Ò²'=>'Ò³','Ò´'=>'Òµ','Ò¶'=>'Ò·','Ò¸'=>'Ò¹','Òº'=>'Ò»','Ò¼'=>'Ò½','Ò¾'=>'Ò¿','Ó€'=>'Ó','Ó'=>'Ó‚','Óƒ'=>'Ó„','Ó…'=>'Ó†','Ó‡'=>'Óˆ','Ó‰'=>'ÓŠ','Ó‹'=>'ÓŒ','Ó'=>'ÓŽ','Ó'=>'Ó‘','Ó’'=>'Ó“','Ó”'=>'Ó•','Ó–'=>'Ó—','Ó˜'=>'Ó™','Óš'=>'Ó›','Óœ'=>'Ó','Óž'=>'ÓŸ','Ó '=>'Ó¡','Ó¢'=>'Ó£','Ó¤'=>'Ó¥','Ó¦'=>'Ó§','Ó¨'=>'Ó©','Óª'=>'Ó«','Ó¬'=>'Ó','Ó®'=>'Ó¯','Ó°'=>'Ó±','Ó²'=>'Ó³','Ó´'=>'Óµ','Ó¶'=>'Ó·','Ó¸'=>'Ó¹','Óº'=>'Ó»','Ó¼'=>'Ó½','Ó¾'=>'Ó¿','Ô€'=>'Ô','Ô‚'=>'Ôƒ','Ô„'=>'Ô…','Ô†'=>'Ô‡','Ôˆ'=>'Ô‰','ÔŠ'=>'Ô‹','ÔŒ'=>'Ô','ÔŽ'=>'Ô','Ô'=>'Ô‘','Ô’'=>'Ô“','Ô±'=>'Õ¡','Ô²'=>'Õ¢','Ô³'=>'Õ£','Ô´'=>'Õ¤','Ôµ'=>'Õ¥','Ô¶'=>'Õ¦','Ô·'=>'Õ§','Ô¸'=>'Õ¨','Ô¹'=>'Õ©','Ôº'=>'Õª','Ô»'=>'Õ«','Ô¼'=>'Õ¬','Ô½'=>'Õ','Ô¾'=>'Õ®','Ô¿'=>'Õ¯','Õ€'=>'Õ°','Õ'=>'Õ±','Õ‚'=>'Õ²','Õƒ'=>'Õ³','Õ„'=>'Õ´','Õ…'=>'Õµ','Õ†'=>'Õ¶','Õ‡'=>'Õ·','Õˆ'=>'Õ¸','Õ‰'=>'Õ¹','ÕŠ'=>'Õº','Õ‹'=>'Õ»','ÕŒ'=>'Õ¼','Õ'=>'Õ½','ÕŽ'=>'Õ¾','Õ'=>'Õ¿','Õ'=>'Ö€','Õ‘'=>'Ö','Õ’'=>'Ö‚','Õ“'=>'Öƒ','Õ”'=>'Ö„','Õ•'=>'Ö…','Õ–'=>'Ö†','á‚ '=>'â´€','á‚¡'=>'â´','á‚¢'=>'â´‚','á‚£'=>'â´ƒ','Ⴄ'=>'â´„','á‚¥'=>'â´…','Ⴆ'=>'â´†','á‚§'=>'â´‡','Ⴈ'=>'â´ˆ','á‚©'=>'â´‰','Ⴊ'=>'â´Š','á‚«'=>'â´‹','Ⴌ'=>'â´Œ','á‚'=>'â´','á‚®'=>'â´Ž','Ⴏ'=>'â´','á‚°'=>'â´','Ⴑ'=>'â´‘','Ⴒ'=>'â´’','Ⴓ'=>'â´“','á‚´'=>'â´”','Ⴕ'=>'â´•','á‚¶'=>'â´–','á‚·'=>'â´—','Ⴘ'=>'â´˜','Ⴙ'=>'â´™','Ⴚ'=>'â´š','á‚»'=>'â´›','Ⴜ'=>'â´œ','Ⴝ'=>'â´','Ⴞ'=>'â´ž','á‚¿'=>'â´Ÿ','Ⴠ'=>'â´ ','áƒ'=>'â´¡','Ⴢ'=>'â´¢','Ⴣ'=>'â´£','Ⴤ'=>'â´¤','Ⴥ'=>'â´¥','Ḁ'=>'á¸','Ḃ'=>'ḃ','Ḅ'=>'ḅ','Ḇ'=>'ḇ','Ḉ'=>'ḉ','Ḋ'=>'ḋ','Ḍ'=>'á¸','Ḏ'=>'á¸','á¸'=>'ḑ','Ḓ'=>'ḓ','Ḕ'=>'ḕ','Ḗ'=>'ḗ','Ḙ'=>'ḙ','Ḛ'=>'ḛ','Ḝ'=>'á¸','Ḟ'=>'ḟ','Ḡ'=>'ḡ','Ḣ'=>'ḣ','Ḥ'=>'ḥ','Ḧ'=>'ḧ','Ḩ'=>'ḩ','Ḫ'=>'ḫ','Ḭ'=>'á¸','Ḯ'=>'ḯ','Ḱ'=>'ḱ','Ḳ'=>'ḳ','Ḵ'=>'ḵ','Ḷ'=>'ḷ','Ḹ'=>'ḹ','Ḻ'=>'ḻ','Ḽ'=>'ḽ','Ḿ'=>'ḿ','á¹€'=>'á¹','Ṃ'=>'ṃ','Ṅ'=>'á¹…','Ṇ'=>'ṇ','Ṉ'=>'ṉ','Ṋ'=>'ṋ','Ṍ'=>'á¹','Ṏ'=>'á¹','á¹'=>'ṑ','á¹’'=>'ṓ','á¹”'=>'ṕ','á¹–'=>'á¹—','Ṙ'=>'á¹™','Ṛ'=>'á¹›','Ṝ'=>'á¹','Ṟ'=>'ṟ','á¹ '=>'ṡ','á¹¢'=>'á¹£','Ṥ'=>'á¹¥','Ṧ'=>'á¹§','Ṩ'=>'ṩ','Ṫ'=>'ṫ','Ṭ'=>'á¹','á¹®'=>'ṯ','á¹°'=>'á¹±','á¹²'=>'á¹³','á¹´'=>'á¹µ','á¹¶'=>'á¹·','Ṹ'=>'á¹¹','Ṻ'=>'á¹»','á¹¼'=>'á¹½','á¹¾'=>'ṿ','Ẁ'=>'áº','Ẃ'=>'ẃ','Ẅ'=>'ẅ','Ẇ'=>'ẇ','Ẉ'=>'ẉ','Ẋ'=>'ẋ','Ẍ'=>'áº','Ẏ'=>'áº','áº'=>'ẑ','Ẓ'=>'ẓ','Ẕ'=>'ẕ','ẛ'=>'ṡ','Ạ'=>'ạ','Ả'=>'ả','Ấ'=>'ấ','Ầ'=>'ầ','Ẩ'=>'ẩ','Ẫ'=>'ẫ','Ậ'=>'áº','Ắ'=>'ắ','Ằ'=>'ằ','Ẳ'=>'ẳ','Ẵ'=>'ẵ','Ặ'=>'ặ','Ẹ'=>'ẹ','Ẻ'=>'ẻ','Ẽ'=>'ẽ','Ế'=>'ế','Ề'=>'á»','Ể'=>'ể','Ễ'=>'á»…','Ệ'=>'ệ','Ỉ'=>'ỉ','Ị'=>'ị','Ọ'=>'á»','Ỏ'=>'á»','á»'=>'ố','á»’'=>'ồ','á»”'=>'ổ','á»–'=>'á»—','Ộ'=>'á»™','Ớ'=>'á»›','Ờ'=>'á»','Ở'=>'ở','á» '=>'ỡ','Ợ'=>'ợ','Ụ'=>'ụ','Ủ'=>'á»§','Ứ'=>'ứ','Ừ'=>'ừ','Ử'=>'á»','á»®'=>'ữ','á»°'=>'á»±','Ỳ'=>'ỳ','á»´'=>'ỵ','á»¶'=>'á»·','Ỹ'=>'ỹ','Ἀ'=>'á¼€','Ἁ'=>'á¼','Ἂ'=>'ἂ','Ἃ'=>'ἃ','Ἄ'=>'ἄ','á¼'=>'á¼…','Ἆ'=>'ἆ','á¼'=>'ἇ','Ἐ'=>'á¼','á¼™'=>'ἑ','Ἒ'=>'á¼’','á¼›'=>'ἓ','Ἔ'=>'á¼”','á¼'=>'ἕ','Ἠ'=>'á¼ ','Ἡ'=>'ἡ','Ἢ'=>'á¼¢','Ἣ'=>'á¼£','Ἤ'=>'ἤ','á¼'=>'á¼¥','á¼®'=>'ἦ','Ἧ'=>'á¼§','Ἰ'=>'á¼°','á¼¹'=>'á¼±','Ἲ'=>'á¼²','á¼»'=>'á¼³','á¼¼'=>'á¼´','á¼½'=>'á¼µ','á¼¾'=>'á¼¶','Ἷ'=>'á¼·','Ὀ'=>'á½€','Ὁ'=>'á½','Ὂ'=>'ὂ','Ὃ'=>'ὃ','Ὄ'=>'ὄ','á½'=>'á½…','á½™'=>'ὑ','á½›'=>'ὓ','á½'=>'ὕ','Ὗ'=>'á½—','Ὠ'=>'á½ ','Ὡ'=>'ὡ','Ὢ'=>'á½¢','Ὣ'=>'á½£','Ὤ'=>'ὤ','á½'=>'á½¥','á½®'=>'ὦ','Ὧ'=>'á½§','Ᾰ'=>'á¾°','á¾¹'=>'á¾±','Ὰ'=>'á½°','á¾»'=>'á½±','á¾¾'=>'ι','Ὲ'=>'á½²','Έ'=>'á½³','Ὴ'=>'á½´','á¿‹'=>'á½µ','Ῐ'=>'á¿','á¿™'=>'á¿‘','Ὶ'=>'á½¶','á¿›'=>'á½·','Ῠ'=>'á¿ ','á¿©'=>'á¿¡','Ὺ'=>'ὺ','á¿«'=>'á½»','Ῥ'=>'á¿¥','Ὸ'=>'ὸ','Ό'=>'á½¹','Ὼ'=>'á½¼','á¿»'=>'á½½','Ω'=>'ω','K'=>'k','â„«'=>'Ã¥','Ⅎ'=>'â…Ž','â… '=>'â…°','â…¡'=>'â…±','â…¢'=>'â…²','â…£'=>'â…³','â…¤'=>'â…´','â…¥'=>'â…µ','â…¦'=>'â…¶','â…§'=>'â…·','â…¨'=>'â…¸','â…©'=>'â…¹','â…ª'=>'â…º','â…«'=>'â…»','â…¬'=>'â…¼','â…'=>'â…½','â…®'=>'â…¾','â…¯'=>'â…¿','Ↄ'=>'ↄ','â’¶'=>'â“','â’·'=>'â“‘','â’¸'=>'â“’','â’¹'=>'â““','â’º'=>'â“”','â’»'=>'â“•','â’¼'=>'â“–','â’½'=>'â“—','â’¾'=>'ⓘ','â’¿'=>'â“™','â“€'=>'ⓚ','â“'=>'â“›','â“‚'=>'ⓜ','Ⓝ'=>'â“','â“„'=>'ⓞ','â“…'=>'ⓟ','Ⓠ'=>'â“ ','Ⓡ'=>'â“¡','Ⓢ'=>'â“¢','Ⓣ'=>'â“£','Ⓤ'=>'ⓤ','â“‹'=>'â“¥','Ⓦ'=>'ⓦ','â“'=>'â“§','Ⓨ'=>'ⓨ','â“'=>'â“©','â°€'=>'â°°','â°'=>'â°±','â°‚'=>'â°²','â°ƒ'=>'â°³','â°„'=>'â°´','â°…'=>'â°µ','â°†'=>'â°¶','â°‡'=>'â°·','â°ˆ'=>'â°¸','â°‰'=>'â°¹','â°Š'=>'â°º','â°‹'=>'â°»','â°Œ'=>'â°¼','â°'=>'â°½','â°Ž'=>'â°¾','â°'=>'â°¿','â°'=>'â±€','â°‘'=>'â±','â°’'=>'ⱂ','â°“'=>'ⱃ','â°”'=>'ⱄ','â°•'=>'â±…','â°–'=>'ⱆ','â°—'=>'ⱇ','â°˜'=>'ⱈ','â°™'=>'ⱉ','â°š'=>'ⱊ','â°›'=>'ⱋ','â°œ'=>'ⱌ','â°'=>'â±','â°ž'=>'ⱎ','â°Ÿ'=>'â±','â° '=>'â±','â°¡'=>'ⱑ','â°¢'=>'â±’','â°£'=>'ⱓ','â°¤'=>'â±”','â°¥'=>'ⱕ','â°¦'=>'â±–','â°§'=>'â±—','â°¨'=>'ⱘ','â°©'=>'â±™','â°ª'=>'ⱚ','â°«'=>'â±›','â°¬'=>'ⱜ','â°'=>'â±','â°®'=>'ⱞ','â± '=>'ⱡ','â±¢'=>'É«','â±£'=>'áµ½','Ɽ'=>'ɽ','â±§'=>'ⱨ','Ⱪ'=>'ⱪ','Ⱬ'=>'ⱬ','â±µ'=>'â±¶','â²€'=>'â²','Ⲃ'=>'ⲃ','Ⲅ'=>'â²…','Ⲇ'=>'ⲇ','Ⲉ'=>'ⲉ','Ⲋ'=>'ⲋ','Ⲍ'=>'â²','Ⲏ'=>'â²','â²'=>'ⲑ','â²’'=>'ⲓ','â²”'=>'ⲕ','â²–'=>'â²—','Ⲙ'=>'â²™','Ⲛ'=>'â²›','Ⲝ'=>'â²','Ⲟ'=>'ⲟ','â² '=>'ⲡ','â²¢'=>'â²£','Ⲥ'=>'â²¥','Ⲧ'=>'â²§','Ⲩ'=>'ⲩ','Ⲫ'=>'ⲫ','Ⲭ'=>'â²','â²®'=>'ⲯ','â²°'=>'â²±','â²²'=>'â²³','â²´'=>'â²µ','â²¶'=>'â²·','Ⲹ'=>'â²¹','Ⲻ'=>'â²»','â²¼'=>'â²½','â²¾'=>'ⲿ','â³€'=>'â³','Ⳃ'=>'ⳃ','Ⳅ'=>'â³…','Ⳇ'=>'ⳇ','Ⳉ'=>'ⳉ','Ⳋ'=>'ⳋ','Ⳍ'=>'â³','Ⳏ'=>'â³','â³'=>'ⳑ','â³’'=>'ⳓ','â³”'=>'ⳕ','â³–'=>'â³—','Ⳙ'=>'â³™','Ⳛ'=>'â³›','Ⳝ'=>'â³','Ⳟ'=>'ⳟ','â³ '=>'ⳡ','â³¢'=>'â³£','A'=>'ï½','ï¼¢'=>'b','ï¼£'=>'c','D'=>'d','ï¼¥'=>'ï½…','F'=>'f','ï¼§'=>'g','H'=>'h','I'=>'i','J'=>'j','K'=>'k','L'=>'l','ï¼'=>'ï½','ï¼®'=>'n','O'=>'ï½','ï¼°'=>'ï½','ï¼±'=>'q','ï¼²'=>'ï½’','ï¼³'=>'s','ï¼´'=>'ï½”','ï¼µ'=>'u','ï¼¶'=>'ï½–','ï¼·'=>'ï½—','X'=>'x','ï¼¹'=>'ï½™','Z'=>'z','ð€'=>'ð¨','ð'=>'ð©','ð‚'=>'ðª','ðƒ'=>'ð«','ð„'=>'ð¬','ð…'=>'ð','ð†'=>'ð®','ð‡'=>'ð¯','ðˆ'=>'ð°','ð‰'=>'ð±','ðŠ'=>'ð²','ð‹'=>'ð³','ðŒ'=>'ð´','ð'=>'ðµ','ðŽ'=>'ð¶','ð'=>'ð·','ð'=>'ð¸','ð‘'=>'ð¹','ð’'=>'ðº','ð“'=>'ð»','ð”'=>'ð¼','ð•'=>'ð½','ð–'=>'ð¾','ð—'=>'ð¿','ð˜'=>'ð‘€','ð™'=>'ð‘','ðš'=>'ð‘‚','ð›'=>'ð‘ƒ','ðœ'=>'ð‘„','ð'=>'ð‘…','ðž'=>'ð‘†','ðŸ'=>'ð‘‡','ð '=>'ð‘ˆ','ð¡'=>'ð‘‰','ð¢'=>'ð‘Š','ð£'=>'ð‘‹','ð¤'=>'ð‘Œ','ð¥'=>'ð‘','ð¦'=>'ð‘Ž','ð§'=>'ð‘');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/case_fold_f.php b/phpBB/includes/utf/data/case_fold_f.php deleted file mode 100644 index 7e2ffb25ec..0000000000 --- a/phpBB/includes/utf/data/case_fold_f.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('ß'=>'ss','İ'=>'i̇','ʼn'=>'ʼn','ǰ'=>'jÌŒ','Î'=>'ϊÌ','ΰ'=>'ϋÌ','Ö‡'=>'Õ¥Ö‚','ẖ'=>'ẖ','ẗ'=>'ẗ','ẘ'=>'wÌŠ','ẙ'=>'yÌŠ','ẚ'=>'aʾ','á½'=>'Ï…Ì“','á½’'=>'ὒ','á½”'=>'Ï…Ì“Ì','á½–'=>'ὖ','á¾€'=>'ἀι','á¾'=>'á¼Î¹','ᾂ'=>'ἂι','ᾃ'=>'ἃι','ᾄ'=>'ἄι','á¾…'=>'ἅι','ᾆ'=>'ἆι','ᾇ'=>'ἇι','ᾈ'=>'ἀι','ᾉ'=>'á¼Î¹','ᾊ'=>'ἂι','ᾋ'=>'ἃι','ᾌ'=>'ἄι','á¾'=>'ἅι','ᾎ'=>'ἆι','á¾'=>'ἇι','á¾'=>'ἠι','ᾑ'=>'ἡι','á¾’'=>'ἢι','ᾓ'=>'ἣι','á¾”'=>'ἤι','ᾕ'=>'ἥι','á¾–'=>'ἦι','á¾—'=>'ἧι','ᾘ'=>'ἠι','á¾™'=>'ἡι','ᾚ'=>'ἢι','á¾›'=>'ἣι','ᾜ'=>'ἤι','á¾'=>'ἥι','ᾞ'=>'ἦι','ᾟ'=>'ἧι','á¾ '=>'ὠι','ᾡ'=>'ὡι','á¾¢'=>'ὢι','á¾£'=>'ὣι','ᾤ'=>'ὤι','á¾¥'=>'ὥι','ᾦ'=>'ὦι','á¾§'=>'ὧι','ᾨ'=>'ὠι','ᾩ'=>'ὡι','ᾪ'=>'ὢι','ᾫ'=>'ὣι','ᾬ'=>'ὤι','á¾'=>'ὥι','á¾®'=>'ὦι','ᾯ'=>'ὧι','á¾²'=>'ὰι','á¾³'=>'αι','á¾´'=>'άι','á¾¶'=>'ᾶ','á¾·'=>'ᾶι','á¾¼'=>'αι','á¿‚'=>'ὴι','ῃ'=>'ηι','á¿„'=>'ήι','ῆ'=>'ῆ','ῇ'=>'ῆι','ῌ'=>'ηι','á¿’'=>'ῒ','á¿“'=>'ϊÌ','á¿–'=>'ῖ','á¿—'=>'ῗ','á¿¢'=>'ῢ','á¿£'=>'ϋÌ','ῤ'=>'ÏÌ“','ῦ'=>'Ï…Í‚','á¿§'=>'ῧ','ῲ'=>'ὼι','ῳ'=>'ωι','á¿´'=>'ώι','á¿¶'=>'ῶ','á¿·'=>'ῶι','ῼ'=>'ωι','ff'=>'ff','ï¬'=>'fi','fl'=>'fl','ffi'=>'ffi','ffl'=>'ffl','ſt'=>'st','st'=>'st','ﬓ'=>'Õ´Õ¶','ﬔ'=>'Õ´Õ¥','ﬕ'=>'Õ´Õ«','ﬖ'=>'Õ¾Õ¶','ﬗ'=>'Õ´Õ');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/case_fold_s.php b/phpBB/includes/utf/data/case_fold_s.php deleted file mode 100644 index 5f09ffa1dd..0000000000 --- a/phpBB/includes/utf/data/case_fold_s.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('ᾈ'=>'á¾€','ᾉ'=>'á¾','ᾊ'=>'ᾂ','ᾋ'=>'ᾃ','ᾌ'=>'ᾄ','á¾'=>'á¾…','ᾎ'=>'ᾆ','á¾'=>'ᾇ','ᾘ'=>'á¾','á¾™'=>'ᾑ','ᾚ'=>'á¾’','á¾›'=>'ᾓ','ᾜ'=>'á¾”','á¾'=>'ᾕ','ᾞ'=>'á¾–','ᾟ'=>'á¾—','ᾨ'=>'á¾ ','ᾩ'=>'ᾡ','ᾪ'=>'á¾¢','ᾫ'=>'á¾£','ᾬ'=>'ᾤ','á¾'=>'á¾¥','á¾®'=>'ᾦ','ᾯ'=>'á¾§','á¾¼'=>'á¾³','ῌ'=>'ῃ','ῼ'=>'ῳ');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/confusables.php b/phpBB/includes/utf/data/confusables.php deleted file mode 100644 index 7564978a26..0000000000 --- a/phpBB/includes/utf/data/confusables.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('¡'=>'i','ǃ'=>'!','α'=>'a',' '=>' ','Â'=>'','Û'=>'','Ü'=>'','á †'=>'','á Ž'=>'','​'=>'','‌'=>'','â€'=>'','
'=>'','
'=>'','â '=>'','â¡'=>'','â¢'=>'','â£'=>'','âª'=>'','â«'=>'','â¬'=>'','â'=>'','â®'=>'','â¯'=>'',''=>'',''=>'',''=>'','ï¿»'=>'',''=>'','ð…³'=>'','ð…´'=>'','ð…µ'=>'','ð…¶'=>'','ð…·'=>'','ð…¸'=>'','ð…¹'=>'','ð…º'=>'','Û¬'=>'ÛŸ','̓'=>'Ì“','Ù'=>'Ì“','Öœ'=>'Ì','Í'=>'Ì','݇'=>'Ì','॔'=>'Ì','Í€'=>'Ì€','॓'=>'Ì€','ÌŒ'=>'̆','Ì‘'=>'Ì‚','Ö¯'=>'ÌŠ','ஂ'=>'ÌŠ','à¹'=>'ÌŠ','à»'=>'ÌŠ','ံ'=>'ÌŠ','ំ'=>'ÌŠ','៓'=>'ÌŠ','゚'=>'ÌŠ','゚'=>'ÌŠ','ͦ'=>'ÌŠ','Í‚'=>'̃','ׄ'=>'̇','Ö¹'=>'̇','ׂ'=>'̇','×'=>'̇','Ý'=>'̇','ं'=>'̇','ਂ'=>'̇','ં'=>'̇','à¯'=>'̇','Ì…'=>'Ì„','〬'=>'̉','̱'=>'Ì ','॒'=>'Ì ','̧'=>'Ì¡','̦'=>'Ì¡','̨'=>'Ì¢','़'=>'Ì£','়'=>'Ì£','਼'=>'Ì£','઼'=>'Ì£','଼'=>'Ì£','͇'=>'̳','̶'=>'̵','ﱞ'=>'ï¹²Ù‘','ﱟ'=>'ï¹´Ù‘','ï³²'=>'ï¹·Ù‘','ï± '=>'ï¹¶Ù‘','ï³³'=>'ï¹¹Ù‘','ﱡ'=>'ﹸّ','ï³´'=>'ï¹»Ù‘','ï±¢'=>'ﹺّ','ï±£'=>'ï¹¼Ù°','Ù´'=>'Ù”','Ý‚'=>'ܼ','౦'=>'o','೦'=>'o','゙'=>'ã‚™',' '=>' ',' '=>' ','â€'=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ','âŸ'=>' ',' '=>' ',' '=>' ',' '=>' ','`'=>'`','ï½€'=>'`','á¿€'=>'Ëœ','ï¼¾'=>'^','︿'=>'^','_'=>'_','ï¹'=>'_','﹎'=>'_','ï¹'=>'_','⌇'=>'︴','ï¼'=>'-','â€'=>'-','‑'=>'-','‒'=>'-','–'=>'-','﹘'=>'-','∼'=>'â“','ï½¥'=>'・','•'=>'・',','=>',','‚'=>',','Ù¬'=>'ØŒ','、'=>'ã€',';'=>';','ï¼›'=>';',':'=>':','Ö‰'=>':','︰'=>':','׃'=>':','â©´'=>'::=','.'=>'.','․'=>'.','Ü‚'=>'.','‥'=>'..','…'=>'...','。'=>'。','·'=>'·','‧'=>'·','∙'=>'·','â‹…'=>'·','á§'=>'·','ᔯ'=>'·4','áŒ'=>'·á','áŽ'=>'·áƒ','á'=>'·á„','á’'=>'·á…','á”'=>'·á†','á—'=>'·áŠ','á™'=>'·á‹','á·'=>'·á³','á‘€'=>'·á³','á‘‚'=>'·á´','á‘„'=>'·á¸','ᑆ'=>'·á¹','á‘—'=>'·ᑌ','á‘™'=>'·ᑎ','á‘›'=>'·á‘','á‘”'=>'·á‘','á‘'=>'·á‘','ᑟ'=>'·ᑑ','á‘¡'=>'·ᑕ','á‘£'=>'·ᑖ','á‘´'=>'·ᑫ','ᑸ'=>'·ᑮ','ᑼ'=>'·ᑰ','ᑾ'=>'·ᑲ','á’€'=>'·ᑳ','á’’'=>'·ᒉ','á’”'=>'·ᒋ','á’–'=>'·ᒌ','á’š'=>'·ᒎ','á’œ'=>'·á’','á’ž'=>'·ᒑ','á’¬'=>'·ᒣ','á’®'=>'·ᒥ','á’°'=>'·ᒦ','á’²'=>'·ᒧ','á’´'=>'·ᒨ','á’¶'=>'·L','á’¸'=>'·ᒫ','ᓉ'=>'·ᓀ','á“‹'=>'·ᓇ','á“'=>'·ᓈ','ᓜ'=>'·ᓓ','ᓞ'=>'·ᓕ','á“ '=>'·ᓖ','á“¢'=>'·ᓗ','ᓤ'=>'·ᓘ','ᓦ'=>'·ᓚ','ᓨ'=>'·ᓛ','á“¶'=>'·á“','ᓸ'=>'·ᓯ','ᓺ'=>'·ᓰ','ᓼ'=>'·ᓱ','ᓾ'=>'·ᓲ','ᔀ'=>'·ᓴ','ᔂ'=>'·ᓵ','á”—'=>'·á”','á”™'=>'·ᔑ','á”›'=>'·ᔒ','á”'=>'·ᔓ','ᔟ'=>'·ᔔ','ᔡ'=>'·ᔕ','ᔣ'=>'·ᔖ','á”±'=>'·ᔨ','ᔳ'=>'·ᔩ','ᔵ'=>'·ᔪ','á”·'=>'·ᔫ','ᔹ'=>'·á”','á”»'=>'·ᔮ','ᕎ'=>'·ᕌ','á•›'=>'·ᕚ','ᕨ'=>'·ᕧ','('=>'(','â‘´'=>'(1)','â’§'=>'(l)','⑽'=>'(10)','⑾'=>'(11)','â‘¿'=>'(12)','â’€'=>'(13)','â’'=>'(14)','â’‚'=>'(15)','â’ƒ'=>'(16)','â’„'=>'(17)','â’…'=>'(18)','â’†'=>'(19)','⑵'=>'(2)','â’‡'=>'(20)','â‘¶'=>'(3)','â‘·'=>'(4)','⑸'=>'(5)','⑹'=>'(6)','⑺'=>'(7)','â‘»'=>'(8)','⑼'=>'(9)','â’œ'=>'(a)','â’'=>'(b)','â’ž'=>'(c)','â’Ÿ'=>'(d)','â’ '=>'(e)','â’¡'=>'(f)','â’¢'=>'(g)','â’£'=>'(h)','â’¤'=>'(i)','â’¥'=>'(j)','â’¦'=>'(k)','â’¨'=>'(m)','â’©'=>'(n)','â’ª'=>'(o)','â’«'=>'(p)','â’¬'=>'(q)','â’'=>'(r)','â’®'=>'(s)','â’¯'=>'(t)','â’°'=>'(u)','â’±'=>'(v)','â’²'=>'(w)','â’³'=>'(x)','â’´'=>'(y)','â’µ'=>'(z)','㈀'=>'(á„€)','㈎'=>'(ê°€)','ãˆ'=>'(á„‚)','ãˆ'=>'(나)','㈂'=>'(ᄃ)','ãˆ'=>'(다)','㈃'=>'(á„…)','㈑'=>'(ë¼)','㈄'=>'(ᄆ)','㈒'=>'(마)','㈅'=>'(ᄇ)','㈓'=>'(ë°”)','㈆'=>'(ᄉ)','㈔'=>'(사)','㈇'=>'(á„‹)','㈕'=>'(ì•„)','ãˆ'=>'(ì˜¤ì „)','㈞'=>'(오후)','㈈'=>'(ᄌ)','㈖'=>'(ìž)','㈜'=>'(주)','㈉'=>'(ᄎ)','㈗'=>'(ì°¨)','㈊'=>'(á„)','㈘'=>'(ì¹´)','㈋'=>'(á„)','㈙'=>'(타)','㈌'=>'(á„‘)','㈚'=>'(파)','ãˆ'=>'(á„’)','㈛'=>'(하)','㈠'=>'(一)','㈦'=>'(七)','㈢'=>'(三)','㈨'=>'(ä¹)','㈡'=>'(二)','㈤'=>'(五)','㈹'=>'(代)','㈽'=>'(ä¼)','ã‰'=>'(休)','㈧'=>'(å…«)','㈥'=>'(å…)','㈸'=>'(労)','㈩'=>'(å)','㈿'=>'(å”)','㈴'=>'(å)','㈺'=>'(呼)','㈣'=>'(å››)','㈯'=>'(土)','㈻'=>'(å¦)','㈰'=>'(æ—¥)','㈪'=>'(月)','㈲'=>'(有)','ãˆ'=>'(木)','㈱'=>'(æ ª)','㈬'=>'(æ°´)','㈫'=>'(ç«)','㈵'=>'(特)','㈼'=>'(監)','㈳'=>'(社)','㈷'=>'(ç¥)','㉀'=>'(ç¥)','㉂'=>'(自)','㉃'=>'(至)','㈶'=>'(財)','㈾'=>'(資)','㈮'=>'(金)',')'=>')','ï¼»'=>'[','〔'=>'[','ï¼½'=>']','〕'=>']','ï½›'=>'{','ï½'=>'}','⦅'=>'⦅','ï½ '=>'⦆','ï½¢'=>'「','ï½£'=>'ã€','ï¼ '=>'@','*'=>'*','ï¼'=>'/','â„'=>'/','∕'=>'/','ï¼¼'=>'\\','&'=>'&','#'=>'#','ï¼…'=>'%','‶'=>'‵‵','‷'=>'‵‵‵','༌'=>'་','´'=>'ʹ','΄'=>'ʹ','´'=>'ʹ','\''=>'ʹ','''=>'ʹ','′'=>'ʹ','׳'=>'ʹ','Í´'=>'ʹ','ËŠ'=>'ʹ','"'=>'ʹʹ','"'=>'ʹʹ','″'=>'ʹʹ','〃'=>'ʹʹ','×´'=>'ʹʹ','ʺ'=>'ʹʹ','‴'=>'ʹʹʹ','â—'=>'ʹʹʹʹ','¯'=>'ˉ','ï¿£'=>'ˉ','‾'=>'ˉ','﹉'=>'ˉ','﹊'=>'ˉ','﹋'=>'ˉ','﹌'=>'ˉ','Ëš'=>'°','௵'=>'௳','ï¿©'=>'â†','ï¿«'=>'→','↑'=>'↑','↓'=>'↓','↵'=>'↲','⨡'=>'↾','ð››'=>'∂','ðœ•'=>'∂','ð'=>'∂','ðž‰'=>'∂','ðŸƒ'=>'∂','ð›'=>'∇','ð›»'=>'∇','ðœµ'=>'∇','ð¯'=>'∇','ðž©'=>'∇','+'=>'+','﬩'=>'+','‹'=>'<','<'=>'<','ï¼'=>'=','⩵'=>'==','â©¶'=>'===','›'=>'>','>'=>'>','ï¿¢'=>'¬','¦'=>'¦','〜'=>'~','~'=>'~','﹨'=>'∖','â‹€'=>'∧','â‹'=>'∨','â‹‚'=>'∩','⋃'=>'∪','∯'=>'∮∮','∰'=>'∮∮∮','≣'=>'≡','â™'=>'⊕','☉'=>'⊙','⟂'=>'⊥','â–·'=>'⊲','â¨'=>'⋈','⨽'=>'⌙','☸'=>'⎈','⎮'=>'⎥','│'=>'│','â–'=>'â–Œ','ï¿'=>'â– ','â˜'=>'â–¡','ï¿®'=>'â—‹','⦾'=>'â—Ž','〛'=>'⟧','〈'=>'⟨','〈'=>'⟨','〉'=>'⟩','〉'=>'⟩','â§™'=>'⦚','〶'=>'〒','ï½°'=>'ー','ï¿ '=>'¢','$'=>'$','ï¿¡'=>'£','ï¿¥'=>'Y̵','₩'=>'W̵','ï¼'=>'0','ðŸŽ'=>'0','ðŸ˜'=>'0','ðŸ¢'=>'0','ðŸ¬'=>'0','ðŸ¶'=>'0','০'=>'0','à¦'=>'0','௦'=>'0','á '=>'0','〇'=>'0','ðŽ'=>'0','ð‘‚'=>'0','ð‘¶'=>'0','ð’ª'=>'0','ð“ž'=>'0','ð”’'=>'0','ð•†'=>'0','ð•º'=>'0','ð–®'=>'0','ð—¢'=>'0','ð˜–'=>'0','ð™Š'=>'0','ð™¾'=>'0','ðš¶'=>'0','ð›°'=>'0','ðœª'=>'0','ð¤'=>'0','ðžž'=>'0','âµ”'=>'0','à´ '=>'0','⊖'=>'0̵','ðš¯'=>'0̵','ðš¹'=>'0̵','ð›©'=>'0̵','ð›³'=>'0̵','ðœ£'=>'0̵','ðœ'=>'0̵','ð'=>'0̵','ð§'=>'0̵','ðž—'=>'0̵','ðž¡'=>'0̵','â´±'=>'0̵','Ꮎ'=>'0̵','Û°'=>'Ù ','áœ'=>'á','ã˜'=>'0点','1'=>'1','ðŸ'=>'1','ðŸ™'=>'1','ðŸ£'=>'1','ðŸ'=>'1','ðŸ·'=>'1','â„'=>'1','â„‘'=>'1','ðˆ'=>'1','ð¼'=>'1','ð‘°'=>'1','ð“˜'=>'1','ð•€'=>'1','ð•´'=>'1','ð–¨'=>'1','ð—œ'=>'1','ð˜'=>'1','ð™„'=>'1','ð™¸'=>'1','l'=>'l','l'=>'l','â…¼'=>'1','â„“'=>'l','ð¥'=>'l','ð‘™'=>'l','ð’'=>'l','ð“'=>'l','ð“µ'=>'l','ð”©'=>'l','ð•'=>'l','ð–‘'=>'l','ð—…'=>'l','ð—¹'=>'l','ð˜'=>'l','ð™¡'=>'l','ðš•'=>'l','ðš°'=>'l','ð›ª'=>'l','ðœ¤'=>'l','ðž'=>'l','ðž˜'=>'l','â‘ '=>'➀','É'=>'lÌ¢','É«'=>'lÌ´','Æš'=>'l̵','Å‚'=>'lÌ·','Û±'=>'Ù¡','â’ˆ'=>'1.','Å€'=>'l·','á’·'=>'1·','â‘©'=>'➉','â’‘'=>'10.','ã©'=>'10æ—¥','㋉'=>'10月','ã¢'=>'10点','â’’'=>'11.','ãª'=>'11æ—¥','㋊'=>'11月','ã£'=>'11点','â’“'=>'12.','ã«'=>'12æ—¥','ã‹‹'=>'12月','ã¤'=>'12点','â’”'=>'13.','ã¬'=>'13æ—¥','ã¥'=>'13点','â’•'=>'14.','ã'=>'14æ—¥','ã¦'=>'14点','â’–'=>'15.','ã®'=>'15æ—¥','ã§'=>'15点','â’—'=>'16.','ã¯'=>'16æ—¥','ã¨'=>'16点','â’˜'=>'17.','ã°'=>'17æ—¥','ã©'=>'17点','â’™'=>'18.','ã±'=>'18æ—¥','ãª'=>'18点','â’š'=>'19.','ã²'=>'19æ—¥','ã«'=>'19点','lj'=>'lj','ã '=>'1æ—¥','ã‹€'=>'1月','ã™'=>'1点','ï¼’'=>'2','ðŸ'=>'2','ðŸš'=>'2','ðŸ¤'=>'2','ðŸ®'=>'2','ðŸ¸'=>'2','á’¿'=>'2','â‘¡'=>'âž','Û²'=>'Ù¢','â’‰'=>'2.','â’›'=>'20.','ã³'=>'20æ—¥','ã¬'=>'20点','ã´'=>'21æ—¥','ã'=>'21点','ãµ'=>'22æ—¥','ã®'=>'22点','ã¶'=>'23æ—¥','ã¯'=>'23点','ã·'=>'24æ—¥','ã°'=>'24点','ã¸'=>'25æ—¥','ã¹'=>'26æ—¥','ãº'=>'27æ—¥','ã»'=>'28æ—¥','ã¼'=>'29æ—¥','ã¡'=>'2æ—¥','ã‹'=>'2月','ãš'=>'2点','3'=>'3','ðŸ‘'=>'3','ðŸ›'=>'3','ðŸ¥'=>'3','ðŸ¯'=>'3','ðŸ¹'=>'3','â‘¢'=>'âž‚','Û³'=>'Ù£','â’Š'=>'3.','ã½'=>'30æ—¥','ã¾'=>'31æ—¥','ã¢'=>'3æ—¥','ã‹‚'=>'3月','ã›'=>'3点','ï¼”'=>'4','ðŸ’'=>'4','ðŸœ'=>'4','ðŸ¦'=>'4','ðŸ°'=>'4','ðŸº'=>'4','áŽ'=>'4','â‘£'=>'➃','â’‹'=>'4.','á”°'=>'4·','ã£'=>'4æ—¥','㋃'=>'4月','ãœ'=>'4点','5'=>'5','ðŸ“'=>'5','ðŸ'=>'5','ðŸ§'=>'5','ðŸ±'=>'5','ðŸ»'=>'5','⑤'=>'âž„','â’Œ'=>'5.','ã¤'=>'5æ—¥','ã‹„'=>'5月','ã'=>'5点','ï¼–'=>'6','ðŸ”'=>'6','ðŸž'=>'6','ðŸ¨'=>'6','ðŸ²'=>'6','ðŸ¼'=>'6','б'=>'6','â‘¥'=>'âž…','â’'=>'6.','ã¥'=>'6æ—¥','ã‹…'=>'6月','ãž'=>'6点','ï¼—'=>'7','ðŸ•'=>'7','ðŸŸ'=>'7','ðŸ©'=>'7','ðŸ³'=>'7','ðŸ½'=>'7','⑦'=>'➆','Û·'=>'Ù§','â’Ž'=>'7.','ã¦'=>'7æ—¥','㋆'=>'7月','ãŸ'=>'7点','ଃ'=>'8','৪'=>'8','੪'=>'8','8'=>'8','ðŸ–'=>'8','ðŸ '=>'8','ðŸª'=>'8','ðŸ´'=>'8','ðŸ¾'=>'8','È£'=>'8','â‘§'=>'➇','Û¸'=>'Ù¨','â’'=>'8.','ã§'=>'8æ—¥','㋇'=>'8月','ã '=>'8点','à©§'=>'9','à¨'=>'9','à§'=>'9','ï¼™'=>'9','ðŸ—'=>'9','ðŸ¡'=>'9','ðŸ«'=>'9','ðŸµ'=>'9','ðŸ¿'=>'9','⑨'=>'➈','Û¹'=>'Ù©','â’'=>'9.','ã¨'=>'9æ—¥','㋈'=>'9月','ã¡'=>'9点','ï½'=>'a','ðš'=>'a','ð‘Ž'=>'a','ð’‚'=>'a','ð’¶'=>'a','ð“ª'=>'a','ð”ž'=>'a','ð•’'=>'a','ð–†'=>'a','ð–º'=>'a','ð—®'=>'a','ð˜¢'=>'a','ð™–'=>'a','ðšŠ'=>'a','â„€'=>'a/c','â„'=>'a/s','æ'=>'ae','b'=>'b','ð›'=>'b','ð‘'=>'b','ð’ƒ'=>'b','ð’·'=>'b','ð“«'=>'b','ð”Ÿ'=>'b','ð•“'=>'b','ð–‡'=>'b','ð–»'=>'b','ð—¯'=>'b','ð˜£'=>'b','ð™—'=>'b','ðš‹'=>'b','É“'=>'bÌ”','ƃ'=>'bÌ„','Æ€'=>'b̵','c'=>'c','â…½'=>'c','ðœ'=>'c','ð‘'=>'c','ð’„'=>'c','ð’¸'=>'c','ð“¬'=>'c','ð” '=>'c','ð•”'=>'c','ð–ˆ'=>'c','ð–¼'=>'c','ð—°'=>'c','ð˜¤'=>'c','ð™˜'=>'c','ðšŒ'=>'c','ð›“'=>'c','ðœ'=>'c','ð‡'=>'c','ðž'=>'c','ðž»'=>'c','â„…'=>'c/o','℆'=>'c/u','d'=>'d','â…¾'=>'d','â…†'=>'d','ð'=>'d','ð‘‘'=>'d','ð’…'=>'d','ð’¹'=>'d','ð“'=>'d','ð”¡'=>'d','ð••'=>'d','ð–‰'=>'d','ð–½'=>'d','ð—±'=>'d','ð˜¥'=>'d','ð™™'=>'d','ðš'=>'d','É—'=>'dÌ”','ÆŒ'=>'dÌ„','É–'=>'dÌ¢','Ä‘'=>'d̵','dz'=>'dz','dž'=>'dž','ï½…'=>'e','ℯ'=>'e','â…‡'=>'e','ðž'=>'e','ð‘’'=>'e','ð’†'=>'e','ð“®'=>'e','ð”¢'=>'e','ð•–'=>'e','ð–Š'=>'e','ð–¾'=>'e','ð—²'=>'e','ð˜¦'=>'e','ð™š'=>'e','ðšŽ'=>'e','â´¹'=>'E','É™'=>'Ç','Éš'=>'ÇËž','â‹´'=>'É›','ð›†'=>'É›','ð›œ'=>'É›','ðœ€'=>'É›','ðœ–'=>'É›','ðœº'=>'É›','ð'=>'É›','ð´'=>'É›','ðžŠ'=>'É›','ðž®'=>'É›','ðŸ„'=>'É›','f'=>'f','ðŸ'=>'f','ð‘“'=>'f','ð’‡'=>'f','ð’»'=>'f','ð“¯'=>'f','ð”£'=>'f','ð•—'=>'f','ð–‹'=>'f','ð–¿'=>'f','ð—³'=>'f','ð˜§'=>'f','ð™›'=>'f','ðš'=>'f','Æ’'=>'fÌ¡','g'=>'g','ℊ'=>'g','ð '=>'g','ð‘”'=>'g','ð’ˆ'=>'g','ð“°'=>'g','ð”¤'=>'g','ð•˜'=>'g','ð–Œ'=>'g','ð—€'=>'g','ð—´'=>'g','ð˜¨'=>'g','ð™œ'=>'g','ðš'=>'g','É¡'=>'g','É '=>'gÌ”','Ç¥'=>'g̵','h'=>'h','ℎ'=>'h','ð¡'=>'h','ð’‰'=>'h','ð’½'=>'h','ð“±'=>'h','ð”¥'=>'h','ð•™'=>'h','ð–'=>'h','ð—'=>'h','ð—µ'=>'h','ð˜©'=>'h','ð™'=>'h','ðš‘'=>'h','ɦ'=>'hÌ”','ħ'=>'h̵','â„'=>'h̵','῾'=>'Ê»','‘'=>'Ê»','‛'=>'Ê»','ʽ'=>'Ê»','â³'=>'i','i'=>'i','â…°'=>'i','ℹ'=>'i','â…ˆ'=>'i','ð¢'=>'i','ð‘–'=>'i','ð’Š'=>'i','ð’¾'=>'i','ð“²'=>'i','ð”¦'=>'i','ð•š'=>'i','ð–Ž'=>'i','ð—‚'=>'i','ð—¶'=>'i','ð˜ª'=>'i','ð™ž'=>'i','ðš’'=>'i','ı'=>'i','ðš¤'=>'i','ɪ'=>'i','É©'=>'i','ð›Š'=>'i','ðœ„'=>'i','ðœ¾'=>'i','ð¸'=>'i','ðž²'=>'i','ɨ'=>'i̵','â…±'=>'ii','â…²'=>'iii','ij'=>'ij','â…³'=>'iv','â…¸'=>'ix','j'=>'j','â…‰'=>'j','ð£'=>'j','ð‘—'=>'j','ð’‹'=>'j','ð’¿'=>'j','ð“³'=>'j','ð”§'=>'j','ð•›'=>'j','ð–'=>'j','ð—ƒ'=>'j','ð—·'=>'j','ð˜«'=>'j','ð™Ÿ'=>'j','ðš“'=>'j','ϳ'=>'j','ðš¥'=>'È·','k'=>'k','ð¤'=>'k','ð‘˜'=>'k','ð’Œ'=>'k','ð“€'=>'k','ð“´'=>'k','ð”¨'=>'k','ð•œ'=>'k','ð–'=>'k','ð—„'=>'k','ð—¸'=>'k','ð˜¬'=>'k','ð™ '=>'k','ðš”'=>'k','Æ™'=>'kÌ”','ï½'=>'m','â…¿'=>'m','ð¦'=>'m','ð‘š'=>'m','ð’Ž'=>'m','ð“‚'=>'m','ð“¶'=>'m','ð”ª'=>'m','ð•ž'=>'m','ð–’'=>'m','ð—†'=>'m','ð—º'=>'m','ð˜®'=>'m','ð™¢'=>'m','ðš–'=>'m','ɱ'=>'mÌ¡','n'=>'n','ð§'=>'n','ð‘›'=>'n','ð’'=>'n','ð“ƒ'=>'n','ð“·'=>'n','ð”«'=>'n','ð•Ÿ'=>'n','ð–“'=>'n','ð—‡'=>'n','ð—»'=>'n','ð˜¯'=>'n','ð™£'=>'n','ðš—'=>'n','ð'=>'N','ð‘'=>'N','ð‘µ'=>'N','ð’©'=>'N','ð“'=>'N','ð”‘'=>'N','ð•¹'=>'N','ð–'=>'N','ð—¡'=>'N','ð˜•'=>'N','ð™‰'=>'N','ð™½'=>'N','ðš´'=>'N','ð›®'=>'N','ðœ¨'=>'N','ð¢'=>'N','ðžœ'=>'N','ɲ'=>'ņ','ɳ'=>'nÌ¢','Æž'=>'nÌ©','ð›ˆ'=>'nÌ©','ðœ‚'=>'nÌ©','ðœ¼'=>'nÌ©','ð¶'=>'nÌ©','ðž°'=>'nÌ©','ÇŒ'=>'nj','ï½'=>'o','â„´'=>'o','ð¨'=>'o','ð‘œ'=>'o','ð’'=>'o','ð“¸'=>'o','ð”¬'=>'o','ð• '=>'o','ð–”'=>'o','ð—ˆ'=>'o','ð—¼'=>'o','ð˜°'=>'o','ð™¤'=>'o','ðš˜'=>'o','á´'=>'o','ð›'=>'o','ðœŠ'=>'o','ð„'=>'o','ð¾'=>'o','ðž¸'=>'o','ɵ'=>'o̵','Ç¿'=>'o̵Ì','ø'=>'oÌ·','Å“'=>'oe','Æ¡'=>'oʼ','â´'=>'p','ï½'=>'p','ð©'=>'p','ð‘'=>'p','ð’‘'=>'p','ð“…'=>'p','ð“¹'=>'p','ð”'=>'p','ð•¡'=>'p','ð–•'=>'p','ð—‰'=>'p','ð—½'=>'p','ð˜±'=>'p','ð™¥'=>'p','ðš™'=>'p','ð›’'=>'p','ð› '=>'p','ðœŒ'=>'p','ðœš'=>'p','ð†'=>'p','ð”'=>'p','ðž€'=>'p','ðžŽ'=>'p','ðžº'=>'p','ðŸˆ'=>'p','Æ¥'=>'pÌ”','q'=>'q','ðª'=>'q','ð‘ž'=>'q','ð’’'=>'q','ð“†'=>'q','ð“º'=>'q','ð”®'=>'q','ð•¢'=>'q','ð––'=>'q','ð—Š'=>'q','ð—¾'=>'q','ð˜²'=>'q','ð™¦'=>'q','ðšš'=>'q','ð'=>'Q','ð‘„'=>'Q','ð‘¸'=>'Q','ð’¬'=>'Q','ð“ '=>'Q','ð””'=>'Q','ð•¼'=>'Q','ð–°'=>'Q','ð—¤'=>'Q','ð˜˜'=>'Q','ð™Œ'=>'Q','ðš€'=>'Q','Ê '=>'qÌ”','ð›‹'=>'ĸ','ð›ž'=>'ĸ','ðœ…'=>'ĸ','ðœ˜'=>'ĸ','ðœ¿'=>'ĸ','ð’'=>'ĸ','ð¹'=>'ĸ','ðžŒ'=>'ĸ','ðž³'=>'ĸ','ðŸ†'=>'ĸ','ï½’'=>'r','ð«'=>'r','ð‘Ÿ'=>'r','ð’“'=>'r','ð“‡'=>'r','ð“»'=>'r','ð”¯'=>'r','ð•£'=>'r','ð–—'=>'r','ð—‹'=>'r','ð—¿'=>'r','ð˜³'=>'r','ð™§'=>'r','ðš›'=>'r','ɽ'=>'rÌ¢','ɼ'=>'rÌ©','s'=>'s','ð¬'=>'s','ð‘ '=>'s','ð’”'=>'s','ð“ˆ'=>'s','ð“¼'=>'s','ð”°'=>'s','ð•¤'=>'s','ð–˜'=>'s','ð—Œ'=>'s','ð˜€'=>'s','ð˜´'=>'s','ð™¨'=>'s','ðšœ'=>'s','ƽ'=>'s','Ê‚'=>'sÌ¢','∫'=>'ʃ','∬'=>'ʃʃ','âˆ'=>'ʃʃʃ','⨌'=>'ʃʃʃʃ','ï½”'=>'t','ð'=>'t','ð‘¡'=>'t','ð’•'=>'t','ð“‰'=>'t','ð“½'=>'t','ð”±'=>'t','ð•¥'=>'t','ð–™'=>'t','ð—'=>'t','ð˜'=>'t','ð˜µ'=>'t','ð™©'=>'t','ðš'=>'t','ð‘‡'=>'T','ð‘»'=>'T','ð’¯'=>'T','ð“£'=>'T','ð”—'=>'T','ð•‹'=>'T','ð•¿'=>'T','ð–³'=>'T','ð—§'=>'T','ð˜›'=>'T','ð™'=>'T','ðšƒ'=>'T','ðš»'=>'T','ð›µ'=>'T','ðœ¯'=>'T','ð©'=>'T','ðž£'=>'T','Æ'=>'tÌ”','È›'=>'Å£','Æ«'=>'Å£','ŧ'=>'t̵','u'=>'u','ð®'=>'u','ð‘¢'=>'u','ð’–'=>'u','ð“Š'=>'u','ð“¾'=>'u','ð”²'=>'u','ð•¦'=>'u','ð–š'=>'u','ð—Ž'=>'u','ð˜‚'=>'u','ð˜¶'=>'u','ð™ª'=>'u','ðšž'=>'u','ÊŠ'=>'u','Ê‹'=>'u','ð›–'=>'u','ðœ'=>'u','ðŠ'=>'u','ðž„'=>'u','ðž¾'=>'u','ð‘ˆ'=>'U','ð‘¼'=>'U','ð’°'=>'U','ð“¤'=>'U','ð”˜'=>'U','ð•Œ'=>'U','ð–€'=>'U','ð–´'=>'U','ð—¨'=>'U','ð˜œ'=>'U','ð™'=>'U','ðš„'=>'U','ï½–'=>'v','â…´'=>'v','ð¯'=>'v','ð‘£'=>'v','ð’—'=>'v','ð“‹'=>'v','ð“¿'=>'v','ð”³'=>'v','ð•§'=>'v','ð–›'=>'v','ð—'=>'v','ð˜ƒ'=>'v','ð˜·'=>'v','ð™«'=>'v','ðšŸ'=>'v','ð›Ž'=>'v','ðœˆ'=>'v','ð‚'=>'v','ð¼'=>'v','ðž¶'=>'v','â…µ'=>'vi','â…¶'=>'vii','â…·'=>'viii','ɯ'=>'w','ï½—'=>'w','ð°'=>'w','ð‘¤'=>'w','ð’˜'=>'w','ð“Œ'=>'w','ð”€'=>'w','ð”´'=>'w','ð•¨'=>'w','ð–œ'=>'w','ð—'=>'w','ð˜„'=>'w','ð˜¸'=>'w','ð™¬'=>'w','ðš '=>'w','ð‘Š'=>'W','ð‘¾'=>'W','ð’²'=>'W','ð“¦'=>'W','ð”š'=>'W','ð•Ž'=>'W','ð–‚'=>'W','ð–¶'=>'W','ð—ª'=>'W','ð˜ž'=>'W','ð™’'=>'W','ðš†'=>'W','×'=>'x','x'=>'x','â…¹'=>'x','ð±'=>'x','ð‘¥'=>'x','ð’™'=>'x','ð“'=>'x','ð”'=>'x','ð”µ'=>'x','ð•©'=>'x','ð–'=>'x','ð—‘'=>'x','ð˜…'=>'x','ð˜¹'=>'x','ð™'=>'x','ðš¡'=>'x','á™'=>'X','ð‘‹'=>'X','ð‘¿'=>'X','ð’³'=>'X','ð“§'=>'X','ð”›'=>'X','ð•'=>'X','ð–ƒ'=>'X','ð–·'=>'X','ð—«'=>'X','ð˜Ÿ'=>'X','ð™“'=>'X','ðš‡'=>'X','ðš¾'=>'X','ð›¸'=>'X','ðœ²'=>'X','ð¬'=>'X','ðž¦'=>'X','â…º'=>'xi','â…»'=>'xii','ï½™'=>'y','ð²'=>'y','ð‘¦'=>'y','ð’š'=>'y','ð“Ž'=>'y','ð”‚'=>'y','ð”¶'=>'y','ð•ª'=>'y','ð–ž'=>'y','ð—’'=>'y','ð˜†'=>'y','ð˜º'=>'y','ð™®'=>'y','ðš¢'=>'y','Æ´'=>'yÌ”','z'=>'z','ð³'=>'z','ð‘§'=>'z','ð’›'=>'z','ð“'=>'z','ð”ƒ'=>'z','ð”·'=>'z','ð•«'=>'z','ð–Ÿ'=>'z','ð—“'=>'z','ð˜‡'=>'z','ð˜»'=>'z','ð™¯'=>'z','ðš£'=>'z','È¥'=>'zÌ¡','Ê'=>'zÌ¢','ƶ'=>'z̵','È'=>'Ê’','?'=>'Ê”','?'=>'Ê”','â‡'=>'ʔʔ','âˆ'=>'ʔǃ','á¾½'=>'ʼ','᾿'=>'ʼ','’'=>'ʼ','ʾ'=>'ʼ','!'=>'ǃ','ï¼'=>'ǃ','â‰'=>'ǃʔ','‼'=>'ǃǃ','âº'=>'α','ð›‚'=>'α','ð›¼'=>'α','ðœ¶'=>'α','ð°'=>'α','ðžª'=>'α','ð›ƒ'=>'β','ð›½'=>'β','ðœ·'=>'β','ð±'=>'β','ðž«'=>'β','ℽ'=>'γ','ð›„'=>'γ','ð›¾'=>'γ','ðœ¸'=>'γ','ð²'=>'γ','ðž¬'=>'γ','ð›…'=>'δ','ð›¿'=>'δ','ðœ¹'=>'δ','ð³'=>'δ','ðž'=>'δ','ðŸ‹'=>'Ï','ð›‡'=>'ζ','ðœ'=>'ζ','ðœ»'=>'ζ','ðµ'=>'ζ','ðž¯'=>'ζ','â¬'=>'θ','ð›‰'=>'θ','ð›'=>'θ','ðœƒ'=>'θ','ðœ—'=>'θ','ðœ½'=>'θ','ð‘'=>'θ','ð·'=>'θ','ðž‹'=>'θ','ðž±'=>'θ','ðŸ…'=>'θ','ð›Œ'=>'λ','ðœ†'=>'λ','ð€'=>'λ','ðº'=>'λ','ðž´'=>'λ','ð›¬'=>'Λ','ðœ¦'=>'Λ','ð '=>'Λ','ðžš'=>'Λ','ð›'=>'μ','ðœ‡'=>'μ','ð'=>'μ','ð»'=>'μ','ðžµ'=>'μ','ð›'=>'ξ','ðœ‰'=>'ξ','ðƒ'=>'ξ','ð½'=>'ξ','ðž·'=>'ξ','ð›¯'=>'Ξ','ðœ©'=>'Ξ','ð£'=>'Ξ','ðž'=>'Ξ','ℼ'=>'Ï€','ð›‘'=>'Ï€','ð›¡'=>'Ï€','ðœ‹'=>'Ï€','ðœ›'=>'Ï€','ð…'=>'Ï€','ð•'=>'Ï€','ð¿'=>'Ï€','ðž'=>'Ï€','ðž¹'=>'Ï€','ðŸ‰'=>'Ï€','á´¨'=>'Ï€','âˆ'=>'Î ','ðš·'=>'Î ','ð›±'=>'Î ','ðœ«'=>'Î ','ð¥'=>'Î ','ðžŸ'=>'Î ','ð›”'=>'σ','ðœŽ'=>'σ','ðˆ'=>'σ','ðž‚'=>'σ','ðž¼'=>'σ','ð›•'=>'Ï„','ðœ'=>'Ï„','ð‰'=>'Ï„','ðžƒ'=>'Ï„','ðž½'=>'Ï„','ð˜'=>'Y','ð‘Œ'=>'Y','ð’€'=>'Y','ð’´'=>'Y','ð“¨'=>'Y','ð”œ'=>'Y','ð•'=>'Y','ð–„'=>'Y','ð–¸'=>'Y','ð—¬'=>'Y','ð˜ '=>'Y','ð™”'=>'Y','ðšˆ'=>'Y','ðš¼'=>'Y','ð›¶'=>'Y','ðœ°'=>'Y','ðª'=>'Y','ðž¤'=>'Y','ð›—'=>'φ','ð›Ÿ'=>'φ','ðœ‘'=>'φ','ðœ™'=>'φ','ð‹'=>'φ','ð“'=>'φ','ðž…'=>'φ','ðž'=>'φ','ðž¿'=>'φ','ðŸ‡'=>'φ','ð›·'=>'Φ','ðœ±'=>'Φ','ð«'=>'Φ','ðž¥'=>'Φ','ð›˜'=>'χ','ðœ’'=>'χ','ðŒ'=>'χ','ðž†'=>'χ','ðŸ€'=>'χ','ð›™'=>'ψ','ðœ“'=>'ψ','ð'=>'ψ','ðž‡'=>'ψ','ðŸ'=>'ψ','ð›¹'=>'Ψ','ðœ³'=>'Ψ','ð'=>'Ψ','ðž§'=>'Ψ','âµ'=>'ω','ð›š'=>'ω','ðœ”'=>'ω','ðŽ'=>'ω','ðžˆ'=>'ω','ðŸ‚'=>'ω','Ó•'=>'ae','Ò“'=>'r̵','Ò‘'=>'rᑊ','Ò—'=>'ж̩','Ò™'=>'з̡','Ó'=>'i','Ò‹'=>'й̡','Ò›'=>'ĸ̩','ÒŸ'=>'ĸ̵','á´«'=>'л','Ó†'=>'л̡','ÓŽ'=>'м̡','ÓŠ'=>'н̡','Óˆ'=>'н̡','Ò£'=>'н̩','Ó©'=>'o̵','ѳ'=>'o̵','Ò«'=>'cÌ¡','Ò'=>'т̩','Ò¯'=>'y','Ò±'=>'y̵','Ñ›'=>'h̵','ѽ'=>'ѡ҃','ÓŒ'=>'Ò·','Ò¿'=>'ҽ̢','Ò'=>'Ь̵','Õ¦'=>'q','Õ¼'=>'n','ℵ'=>'×','ﬡ'=>'×','אָ'=>'אַ','אּ'=>'אַ','ï'=>'×ל','â„¶'=>'ב','â„·'=>'×’','ℸ'=>'ד','ﬢ'=>'ד','ﬣ'=>'×”','ﬤ'=>'×›','ﬥ'=>'ל','ﬦ'=>'×','ï¬ '=>'×¢','ﬧ'=>'ר','ﬨ'=>'ת','ﺀ'=>'Ø¡','ﺂ'=>'Ø¢','ïº'=>'Ø¢','ﺄ'=>'Ø£','ﺃ'=>'Ø£','Ùµ'=>'أ','ï‘'=>'Ù±','ï'=>'Ù±','ﺆ'=>'ؤ','ﺅ'=>'ؤ','Ù¶'=>'ÙˆÙ”','ﺈ'=>'Ø¥','ﺇ'=>'Ø¥','ﺋ'=>'ئ','ﺌ'=>'ئ','ﺊ'=>'ئ','ﺉ'=>'ئ','ﯫ'=>'ئا','ﯪ'=>'ئا','ﯸ'=>'ئٻ','ﯷ'=>'ئٻ','ﯶ'=>'ئٻ','ï²—'=>'ئج','ï°€'=>'ئج','ﲘ'=>'ئØ','ï°'=>'ئØ','ï²™'=>'ئخ','ﱤ'=>'ئر','ï±¥'=>'ئز','ﲚ'=>'ئم','ﳟ'=>'ئم','ﱦ'=>'ئم','ï°‚'=>'ئم','ï±§'=>'ئن','ï²›'=>'ئه','ï³ '=>'ئه','ï¯'=>'ئه','ﯬ'=>'ئه','ﯯ'=>'ئو','ﯮ'=>'ئو','ﯳ'=>'ئۆ','ﯲ'=>'ئۆ','ﯱ'=>'ئۇ','ﯰ'=>'ئۇ','ﯵ'=>'ئۈ','ﯴ'=>'ئۈ','ﯻ'=>'ئى','ﯺ'=>'ئى','ﱨ'=>'ئى','ﯹ'=>'ئى','ï°ƒ'=>'ئى','ﱩ'=>'ئى','ï°„'=>'ئى','ﺎ'=>'ا','ïº'=>'ا','ï´¼'=>'اً','ï´½'=>'اً','ï·³'=>'اكبر','ï·²'=>'الله','ﺑ'=>'ب','ﺒ'=>'ب','ïº'=>'ب','ïº'=>'ب','ﲜ'=>'بج','ï°…'=>'بج','ï²'=>'بØ','ï°†'=>'بØ','ï·‚'=>'بØÙ‰','ﲞ'=>'بخ','ï°‡'=>'بخ','ï¶ž'=>'بخى','ﱪ'=>'بر','ﱫ'=>'بز','ﲟ'=>'بم','ﳡ'=>'بم','ﱬ'=>'بم','ï°ˆ'=>'بم','ï±'=>'بن','ï² '=>'به','ï³¢'=>'به','ï±®'=>'بى','ï°‰'=>'بى','ﱯ'=>'بى','ï°Š'=>'بى','ï”'=>'Ù»','ï•'=>'Ù»','ï“'=>'Ù»','ï’'=>'Ù»','Û'=>'Ù»','ﯦ'=>'Ù»','ﯧ'=>'Ù»','ﯥ'=>'Ù»','ﯤ'=>'Ù»','ï˜'=>'Ù¾','ï™'=>'Ù¾','ï—'=>'Ù¾','ï–'=>'Ù¾','ïœ'=>'Ú€','ï'=>'Ú€','ï›'=>'Ú€','ïš'=>'Ú€','ﺔ'=>'Ø©','ﺓ'=>'Ø©','ﺗ'=>'ت','ﺘ'=>'ت','ﺖ'=>'ت','ﺕ'=>'ت','ﲡ'=>'تج','ï°‹'=>'تج','ïµ'=>'تجم','ï¶ '=>'تجى','ï¶Ÿ'=>'تجى','ï²¢'=>'تØ','ï°Œ'=>'تØ','ïµ’'=>'ØªØØ¬','ﵑ'=>'ØªØØ¬','ﵓ'=>'تØÙ…','ï²£'=>'تخ','ï°'=>'تخ','ïµ”'=>'تخم','ï¶¢'=>'تخى','ï¶¡'=>'تخى','ï±°'=>'تر','ï±±'=>'تز','ﲤ'=>'تم','ï³£'=>'تم','ï±²'=>'تم','ï°Ž'=>'تم','ﵕ'=>'تمج','ïµ–'=>'تمØ','ïµ—'=>'تمخ','ﶤ'=>'تمى','ï¶£'=>'تمى','ï±³'=>'تن','ï²¥'=>'ته','ﳤ'=>'ته','ï±´'=>'تى','ï°'=>'تى','ï±µ'=>'تى','ï°'=>'تى','ﺛ'=>'Ø«','ﺜ'=>'Ø«','ﺚ'=>'Ø«','ﺙ'=>'Ø«','ï°‘'=>'ثج','ï±¶'=>'ثر','ï±·'=>'ثز','ﲦ'=>'ثم','ï³¥'=>'ثم','ﱸ'=>'ثم','ï°’'=>'ثم','ï±¹'=>'ثن','ﳦ'=>'ثه','ﱺ'=>'ثى','ï°“'=>'ثى','ï±»'=>'ثى','ï°”'=>'ثى','ï¨'=>'Ù¹','ï©'=>'Ù¹','ï§'=>'Ù¹','ï¦'=>'Ù¹','Ú»'=>'Ù¹','ﮢ'=>'Ù¹','ﮣ'=>'Ù¹','ﮡ'=>'Ù¹','ï® '=>'Ù¹','ï '=>'Ùº','ï¡'=>'Ùº','ïŸ'=>'Ùº','ïž'=>'Ùº','ï¤'=>'Ù¿','ï¥'=>'Ù¿','ï£'=>'Ù¿','ï¢'=>'Ù¿','ﺟ'=>'ج','ïº '=>'ج','ﺞ'=>'ج','ïº'=>'ج','ï²§'=>'جØ','ï°•'=>'جØ','ﶦ'=>'جØÙ‰','ï¶¾'=>'جØÙ‰','ï·»'=>'جل جلاله','ﲨ'=>'جم','ï°–'=>'جم','ïµ™'=>'جمØ','ﵘ'=>'جمØ','ï¶§'=>'جمى','ï¶¥'=>'جمى','ï´'=>'جى','ï´'=>'جى','ï´ž'=>'جى','ï´‚'=>'جى','ï¸'=>'Úƒ','ï¹'=>'Úƒ','ï·'=>'Úƒ','ï¶'=>'Úƒ','ï´'=>'Ú„','ïµ'=>'Ú„','ï³'=>'Ú„','ï²'=>'Ú„','ï¼'=>'Ú†','ï½'=>'Ú†','ï»'=>'Ú†','ïº'=>'Ú†','ﮀ'=>'Ú‡','ï®'=>'Ú‡','ï¿'=>'Ú‡','ï¾'=>'Ú‡','ﺣ'=>'Ø','ﺤ'=>'Ø','ﺢ'=>'Ø','ﺡ'=>'Ø','ﲩ'=>'ØØ¬','ï°—'=>'ØØ¬','ï¶¿'=>'ØØ¬Ù‰','ﲪ'=>'ØÙ…','ï°˜'=>'ØÙ…','ïµ›'=>'ØÙ…Ù‰','ﵚ'=>'ØÙ…Ù‰','ï´›'=>'ØÙ‰','ﳿ'=>'ØÙ‰','ï´œ'=>'ØÙ‰','ï´€'=>'ØÙ‰','ﺧ'=>'Ø®','ﺨ'=>'Ø®','ﺦ'=>'Ø®','ﺥ'=>'Ø®','ﲫ'=>'خج','ï°™'=>'خج','ï°š'=>'Ø®Ø','ﲬ'=>'خم','ï°›'=>'خم','ï´Ÿ'=>'خى','ï´ƒ'=>'خى','ï´ '=>'خى','ï´„'=>'خى','ﺪ'=>'د','ﺩ'=>'د','ﺬ'=>'ذ','ﺫ'=>'ذ','ï±›'=>'ذٰ','ﮉ'=>'Úˆ','ﮈ'=>'Úˆ','ï®…'=>'ÚŒ','ﮄ'=>'ÚŒ','ﮃ'=>'Ú','ﮂ'=>'Ú','ﮇ'=>'ÚŽ','ﮆ'=>'ÚŽ','ﺮ'=>'ر','ïº'=>'ر','ﱜ'=>'رٰ','ï·¶'=>'رسول','ï·¼'=>'رىال','ﺰ'=>'ز','ﺯ'=>'ز','ï®'=>'Ú‘','ﮌ'=>'Ú‘','ﮋ'=>'Ú˜','ﮊ'=>'Ú˜','ﺳ'=>'س','ﺴ'=>'س','ﺲ'=>'س','ﺱ'=>'س','ï²'=>'سج','ï´´'=>'سج','ï°œ'=>'سج','ïµ'=>'سجØ','ﵞ'=>'سجى','ï²®'=>'سØ','ï´µ'=>'سØ','ï°'=>'سØ','ﵜ'=>'Ø³ØØ¬','ﲯ'=>'سخ','ï´¶'=>'سخ','ï°ž'=>'سخ','ﶨ'=>'سخى','ï·†'=>'سخى','ï´ª'=>'سر','ï´Ž'=>'سر','ï²°'=>'سم','ï³§'=>'سم','ï°Ÿ'=>'سم','ﵡ'=>'سمج','ïµ '=>'سمØ','ﵟ'=>'سمØ','ïµ£'=>'سمم','ïµ¢'=>'سمم','ï´±'=>'سه','ﳨ'=>'سه','ï´—'=>'سى','ï³»'=>'سى','ï´˜'=>'سى','ï³¼'=>'سى','ﺷ'=>'Ø´','ﺸ'=>'Ø´','ﺶ'=>'Ø´','ﺵ'=>'Ø´','ï´'=>'شج','ï´·'=>'شج','ï´¥'=>'شج','ï´‰'=>'شج','ﵩ'=>'شجى','ï´®'=>'Ø´Ø','ï´¸'=>'Ø´Ø','ï´¦'=>'Ø´Ø','ï´Š'=>'Ø´Ø','ﵨ'=>'Ø´ØÙ…','ïµ§'=>'Ø´ØÙ…','ﶪ'=>'Ø´ØÙ‰','ï´¯'=>'شخ','ï´¹'=>'شخ','ï´§'=>'شخ','ï´‹'=>'شخ','ï´©'=>'شر','ï´'=>'شر','ï´°'=>'شم','ﳩ'=>'شم','ï´¨'=>'شم','ï´Œ'=>'شم','ﵫ'=>'شمخ','ﵪ'=>'شمخ','ïµ'=>'شمم','ﵬ'=>'شمم','ï´²'=>'شه','ﳪ'=>'شه','ï´™'=>'شى','ï³½'=>'شى','ï´š'=>'شى','ï³¾'=>'شى','ﺻ'=>'ص','ﺼ'=>'ص','ﺺ'=>'ص','ﺹ'=>'ص','ï²±'=>'صØ','ï° '=>'صØ','ïµ¥'=>'ØµØØ','ﵤ'=>'ØµØØ','ï¶©'=>'صØÙ‰','ï²²'=>'صخ','ï´«'=>'صر','ï´'=>'صر','ï·µ'=>'صلعم','ï·¹'=>'صلى','ï·º'=>'صلى الله علىه وسلم','ï·°'=>'صلے','ï²³'=>'صم','ï°¡'=>'صم','ï·…'=>'صمم','ﵦ'=>'صمم','ï´¡'=>'صى','ï´…'=>'صى','ï´¢'=>'صى','ï´†'=>'صى','ﺿ'=>'ض','ﻀ'=>'ض','ﺾ'=>'ض','ﺽ'=>'ض','ï²´'=>'ضج','ï°¢'=>'ضج','ï²µ'=>'ضØ','ï°£'=>'ضØ','ïµ®'=>'ضØÙ‰','ï¶«'=>'ضØÙ‰','ï²¶'=>'ضخ','ï°¤'=>'ضخ','ïµ°'=>'ضخم','ﵯ'=>'ضخم','ï´¬'=>'ضر','ï´'=>'ضر','ï²·'=>'ضم','ï°¥'=>'ضم','ï´£'=>'ضى','ï´‡'=>'ضى','ï´¤'=>'ضى','ï´ˆ'=>'ضى','ﻃ'=>'Ø·','ﻄ'=>'Ø·','ﻂ'=>'Ø·','ï»'=>'Ø·','ﲸ'=>'Ø·Ø','ï°¦'=>'Ø·Ø','ï´³'=>'طم','ï´º'=>'طم','ï°§'=>'طم','ïµ²'=>'طمØ','ïµ±'=>'طمØ','ïµ³'=>'طمم','ïµ´'=>'طمى','ï´‘'=>'طى','ï³µ'=>'طى','ï´’'=>'طى','ï³¶'=>'طى','ﻇ'=>'ظ','ﻈ'=>'ظ','ﻆ'=>'ظ','ï»…'=>'ظ','ï²¹'=>'ظم','ï´»'=>'ظم','ï°¨'=>'ظم','ﻋ'=>'ع','ﻌ'=>'ع','ﻊ'=>'ع','ﻉ'=>'ع','ﲺ'=>'عج','ï°©'=>'عج','ï·„'=>'عجم','ïµµ'=>'عجم','ï··'=>'علىه','ï²»'=>'عم','ï°ª'=>'عم','ïµ·'=>'عمم','ïµ¶'=>'عمم','ﵸ'=>'عمى','ï¶¶'=>'عمى','ï´“'=>'عى','ï³·'=>'عى','ï´”'=>'عى','ﳸ'=>'عى','ï»'=>'غ','ï»'=>'غ','ﻎ'=>'غ','ï»'=>'غ','ï²¼'=>'غج','ï°«'=>'غج','ï²½'=>'غم','ï°¬'=>'غم','ïµ¹'=>'غمم','ïµ»'=>'غمى','ﵺ'=>'غمى','ï´•'=>'غى','ï³¹'=>'غى','ï´–'=>'غى','ﳺ'=>'غى','ﻓ'=>'Ù','ï»”'=>'Ù','ï»’'=>'Ù','ﻑ'=>'Ù','ï²¾'=>'ÙØ¬','ï°'=>'ÙØ¬','ﲿ'=>'ÙØ','ï°®'=>'ÙØ','ï³€'=>'ÙØ®','ï°¯'=>'ÙØ®','ïµ½'=>'ÙØ®Ù…','ïµ¼'=>'ÙØ®Ù…','ï³'=>'ÙÙ…','ï°°'=>'ÙÙ…','ï·'=>'Ùمى','ï±¼'=>'ÙÙ‰','ï°±'=>'ÙÙ‰','ï±½'=>'ÙÙ‰','ï°²'=>'ÙÙ‰','ï¬'=>'Ú¤','ï'=>'Ú¤','ï«'=>'Ú¤','ïª'=>'Ú¤','ï°'=>'Ú¦','ï±'=>'Ú¦','ï¯'=>'Ú¦','ï®'=>'Ú¦','ï»—'=>'Ù‚','ﻘ'=>'Ù‚','ï»–'=>'Ù‚','ﻕ'=>'Ù‚','ﳂ'=>'Ù‚Ø','ï°³'=>'Ù‚Ø','ï·±'=>'قلے','ﳃ'=>'قم','ï°´'=>'قم','ï¶´'=>'قمØ','ïµ¾'=>'قمØ','ﵿ'=>'قمم','ï¶²'=>'قمى','ï±¾'=>'قى','ï°µ'=>'قى','ﱿ'=>'قى','ï°¶'=>'قى','ï»›'=>'Ùƒ','ﻜ'=>'Ùƒ','ﻚ'=>'Ùƒ','ï»™'=>'Ùƒ','Ú©'=>'Ùƒ','ï®'=>'Ùƒ','ﮑ'=>'Ùƒ','ï®'=>'Ùƒ','ﮎ'=>'Ùƒ','ï²€'=>'كا','ï°·'=>'كا','ﳄ'=>'كج','ï°¸'=>'كج','ï³…'=>'ÙƒØ','ï°¹'=>'ÙƒØ','ﳆ'=>'كخ','ï°º'=>'كخ','ﳇ'=>'كل','ﳫ'=>'كل','ï²'=>'كل','ï°»'=>'كل','ﳈ'=>'كم','ﳬ'=>'كم','ﲂ'=>'كم','ï°¼'=>'كم','ï·ƒ'=>'كمم','ï¶»'=>'كمم','ï¶·'=>'كمى','ﲃ'=>'كى','ï°½'=>'كى','ﲄ'=>'كى','ï°¾'=>'كى','ﯕ'=>'Ú','ﯖ'=>'Ú','ﯔ'=>'Ú','ﯓ'=>'Ú','ï®”'=>'Ú¯','ﮕ'=>'Ú¯','ﮓ'=>'Ú¯','ï®’'=>'Ú¯','ﮜ'=>'Ú±','ï®'=>'Ú±','ï®›'=>'Ú±','ﮚ'=>'Ú±','ﮘ'=>'Ú³','ï®™'=>'Ú³','ï®—'=>'Ú³','ï®–'=>'Ú³','ﻟ'=>'Ù„','ï» '=>'Ù„','ﻞ'=>'Ù„','ï»'=>'Ù„','ï»¶'=>'لآ','ﻵ'=>'لآ','ﻸ'=>'لأ','ï»·'=>'لأ','ﻺ'=>'لإ','ﻹ'=>'لإ','ﻼ'=>'لا','ï»»'=>'لا','ﳉ'=>'لج','ï°¿'=>'لج','ﶃ'=>'لجج','ï¶„'=>'لجج','ﶺ'=>'لجم','ï¶¼'=>'لجم','ﶬ'=>'لجى','ﳊ'=>'Ù„Ø','ï±€'=>'Ù„Ø','ï¶µ'=>'Ù„ØÙ…','ï¶€'=>'Ù„ØÙ…','ï¶‚'=>'Ù„ØÙ‰','ï¶'=>'Ù„ØÙ‰','ﳋ'=>'لخ','ï±'=>'لخ','ﶆ'=>'لخم','ï¶…'=>'لخم','ﳌ'=>'لم','ï³'=>'لم','ï²…'=>'لم','ﱂ'=>'لم','ﶈ'=>'لمØ','ﶇ'=>'لمØ','ï¶'=>'لمى','ï³'=>'له','ﲆ'=>'لى','ﱃ'=>'لى','ﲇ'=>'لى','ﱄ'=>'لى','ﻣ'=>'Ù…','ﻤ'=>'Ù…','ﻢ'=>'Ù…','ﻡ'=>'Ù…','ﲈ'=>'ما','ﳎ'=>'مج','ï±…'=>'مج','ï¶Œ'=>'مجØ','ï¶’'=>'مجخ','ï¶'=>'مجم','ï·€'=>'مجى','ï³'=>'Ù…Ø','ﱆ'=>'Ù…Ø','ﶉ'=>'Ù…ØØ¬','ï¶Š'=>'Ù…ØÙ…','ï·´'=>'Ù…ØÙ…د','ï¶‹'=>'Ù…ØÙ‰','ï³'=>'مخ','ﱇ'=>'مخ','ï¶Ž'=>'مخج','ï¶'=>'مخم','ï¶¹'=>'مخى','ﳑ'=>'مم','ﲉ'=>'مم','ﱈ'=>'مم','ï¶±'=>'ممى','ﱉ'=>'مى','ﱊ'=>'مى','ï»§'=>'Ù†','ﻨ'=>'Ù†','ﻦ'=>'Ù†','ﻥ'=>'Ù†','ï³’'=>'نج','ﱋ'=>'نج','ﶸ'=>'نجØ','ï¶½'=>'نجØ','ﶘ'=>'نجم','ï¶—'=>'نجم','ï¶™'=>'نجى','ï·‡'=>'نجى','ﳓ'=>'Ù†Ø','ﱌ'=>'Ù†Ø','ï¶•'=>'Ù†ØÙ…','ï¶–'=>'Ù†ØÙ‰','ï¶³'=>'Ù†ØÙ‰','ï³”'=>'نخ','ï±'=>'نخ','ﲊ'=>'نر','ﲋ'=>'نز','ﳕ'=>'نم','ï³®'=>'نم','ﲌ'=>'نم','ﱎ'=>'نم','ï¶›'=>'نمى','ï¶š'=>'نمى','ï²'=>'نن','ï³–'=>'نه','ﳯ'=>'نه','ﲎ'=>'نى','ï±'=>'نى','ï²'=>'نى','ï±'=>'نى','ﮟ'=>'Úº','ﮞ'=>'Úº','ﻫ'=>'Ù‡','ﻬ'=>'Ù‡','ﻪ'=>'Ù‡','ﻩ'=>'Ù‡','Ú¾'=>'Ù‡','ﮬ'=>'Ù‡','ï®'=>'Ù‡','ﮫ'=>'Ù‡','ﮪ'=>'Ù‡','Û'=>'Ù‡','ﮨ'=>'Ù‡','ﮩ'=>'Ù‡','ï®§'=>'Ù‡','ﮦ'=>'Ù‡','Û•'=>'Ù‡','ï³™'=>'هٰ','ï³—'=>'هج','ﱑ'=>'هج','ﳘ'=>'هم','ï±’'=>'هم','ï¶“'=>'همج','ï¶”'=>'همم','ﱓ'=>'هى','ï±”'=>'هى','ﮥ'=>'Û€','ﮤ'=>'Û€','ï»®'=>'Ùˆ','ï»'=>'Ùˆ','ï·¸'=>'وسلم','ﯡ'=>'Û…','ï¯ '=>'Û…','ﯚ'=>'Û†','ﯙ'=>'Û†','ﯘ'=>'Û‡','ﯗ'=>'Û‡','Ù·'=>'Û‡Ù”','ï¯'=>'Û‡Ù”','ﯜ'=>'Ûˆ','ﯛ'=>'Ûˆ','ﯣ'=>'Û‰','ﯢ'=>'Û‰','ﯟ'=>'Û‹','ﯞ'=>'Û‹','ﯨ'=>'Ù‰','ﯩ'=>'Ù‰','ï»°'=>'Ù‰','ﻯ'=>'Ù‰','ÙŠ'=>'Ù‰','ﻳ'=>'Ù‰','ï»´'=>'Ù‰','ﻲ'=>'Ù‰','ï»±'=>'Ù‰','ÛŒ'=>'Ù‰','ﯾ'=>'Ù‰','ﯿ'=>'Ù‰','ﯽ'=>'Ù‰','ﯼ'=>'Ù‰','Ù¸'=>'Ù‰Ù”','ï²'=>'ىٰ','ï±'=>'ىٰ','ﳚ'=>'ىج','ﱕ'=>'ىج','ﶯ'=>'ىجى','ï³›'=>'Ù‰Ø','ï±–'=>'Ù‰Ø','ï¶®'=>'Ù‰ØÙ‰','ﳜ'=>'ىخ','ï±—'=>'ىخ','ﲑ'=>'ىر','ï²’'=>'ىز','ï³'=>'ىم','ï³°'=>'ىم','ﲓ'=>'ىم','ﱘ'=>'ىم','ï¶'=>'ىمم','ï¶œ'=>'ىمم','ï¶°'=>'ىمى','ï²”'=>'ىن','ﳞ'=>'ىه','ï³±'=>'ىه','ﲕ'=>'ىى','ï±™'=>'ىى','ï²–'=>'ىى','ﱚ'=>'ىى','Û§'=>'Û¦','ﮯ'=>'Û’','ï®®'=>'Û’','ï®±'=>'Û“','ï®°'=>'Û“','∃'=>'â´º','आ'=>'अा','ऒ'=>'अाॆ','ओ'=>'अाे','औ'=>'अाै','ऄ'=>'अॆ','ऑ'=>'अॉ','à¤'=>'à¤à¥…','ऎ'=>'à¤à¥†','à¤'=>'à¤à¥‡','ई'=>'रà¥à¤‡','আ'=>'অা','à§ '=>'ঋৃ','à§¡'=>'ঌৢ','ਉ'=>'ੳà©','ਊ'=>'ੳੂ','ਆ'=>'ਅਾ','à¨'=>'ਅੈ','ਔ'=>'ਅੌ','ਇ'=>'ੲਿ','ਈ'=>'ੲੀ','à¨'=>'ੲੇ','આ'=>'અા','ઑ'=>'અાૅ','ઓ'=>'અાે','ઔ'=>'અાૈ','àª'=>'અૅ','àª'=>'અે','àª'=>'અૈ','ଆ'=>'ଅା','௮'=>'à®…','à®°'=>'ஈ','ா'=>'ஈ','௫'=>'ஈà¯','௨'=>'உ','ஊ'=>'உள','à¯'=>'எ','௷'=>'எவ','ஜ'=>'à®','௧'=>'க','௪'=>'ச','௬'=>'சà¯','௲'=>'சூ','௺'=>'நீ','ை'=>'ன','௴'=>'மீ','௰'=>'ய','ௗ'=>'ள','௸'=>'à®·','ொ'=>'ெஈ','ௌ'=>'ெள','ோ'=>'ேஈ','à± '=>'à°‹à°¾','ౡ'=>'ఌా','à°”'=>'ఒౌ','à°“'=>'ఒౕ','à°¢'=>'à°¡Ì£','à°'=>'బ̣','à°·'=>'వ̣','à°¹'=>'వా','à°®'=>'à°µà±','ూ'=>'à±à°¾','ౄ'=>'ృా','ೡ'=>'ಌಾ','ಔ'=>'ఒౌ','à´ˆ'=>'ഇൗ','à´Š'=>'உൗ','à´'=>'എെ','à´“'=>'à´’à´¾','à´”'=>'ഒൗ','ൡ'=>'à´ž','൫'=>'à´¦àµà´°','à´Œ'=>'നூ','à´™'=>'നூ','൯'=>'à´¨àµ','à´±'=>'à´°','൪'=>'à´°àµ','൮'=>'à´µàµ','ീ'=>'ி','ൂ'=>'ூ','ൃ'=>'ூ','ൈ'=>'െെ','ฃ'=>'ข','ด'=>'ค','ต'=>'ค','ม'=>'ฆ','ซ'=>'ช','à¸'=>'ฎ','ท'=>'ฑ','ๅ'=>'า','ำ'=>'̊า','à¹'=>'เเ','ໜ'=>'ຫນ','à»'=>'ຫມ','ຳ'=>'̊າ','ཷ'=>'ྲཱྀ','ཹ'=>'ླཱྀ','á€'=>'o','ឣ'=>'អ','á§'=>'ᦞ','á’'=>'á¬','á“'=>'ᬑ','á˜'=>'ᬨ','ᢖ'=>'ᡜ','á¡•'=>'á µ','á’'=>'Ꭱ','Ꮍ'=>'y','ð€'=>'A','ð´'=>'A','ð‘¨'=>'A','ð’œ'=>'A','ð“'=>'A','ð”„'=>'A','ð”¸'=>'A','ð•¬'=>'A','ð– '=>'A','ð—”'=>'A','ð˜ˆ'=>'A','ð˜¼'=>'A','ð™°'=>'A','ðš¨'=>'A','ð›¢'=>'A','ðœœ'=>'A','ð–'=>'A','ðž'=>'A','ð‰'=>'J','ð½'=>'J','ð‘±'=>'J','ð’¥'=>'J','ð“™'=>'J','ð”'=>'J','ð•'=>'J','ð•µ'=>'J','ð–©'=>'J','ð—'=>'J','ð˜‘'=>'J','ð™…'=>'J','ð™¹'=>'J','á§'=>'J','â‹¿'=>'E','â„°'=>'E','ð„'=>'E','ð¸'=>'E','ð‘¬'=>'E','ð“”'=>'E','ð”ˆ'=>'E','ð”¼'=>'E','ð•°'=>'E','ð–¤'=>'E','ð—˜'=>'E','ð˜Œ'=>'E','ð™€'=>'E','ð™´'=>'E','ðš¬'=>'E','ð›¦'=>'E','ðœ '=>'E','ðš'=>'E','ðž”'=>'E','ℾ'=>'Ꮁ','ðšª'=>'Ꮁ','ð›¤'=>'Ꮁ','ðœž'=>'Ꮁ','ð˜'=>'Ꮁ','ðž’'=>'Ꮁ','á”'=>'w','ℳ'=>'M','ðŒ'=>'M','ð‘€'=>'M','ð‘´'=>'M','ð“œ'=>'M','ð”'=>'M','ð•„'=>'M','ð•¸'=>'M','ð–¬'=>'M','ð— '=>'M','ð˜”'=>'M','ð™ˆ'=>'M','ð™¼'=>'M','ðš³'=>'M','ð›'=>'M','ðœ§'=>'M','ð¡'=>'M','ðž›'=>'M','â„‹'=>'H','ℌ'=>'H','â„'=>'H','ð‡'=>'H','ð»'=>'H','ð‘¯'=>'H','ð“—'=>'H','ð•³'=>'H','ð–§'=>'H','ð—›'=>'H','ð˜'=>'H','ð™ƒ'=>'H','ð™·'=>'H','ðš®'=>'H','ð›¨'=>'H','ðœ¢'=>'H','ðœ'=>'H','ðž–'=>'H','ð†'=>'G','ðº'=>'G','ð‘®'=>'G','ð’¢'=>'G','ð“–'=>'G','ð”Š'=>'G','ð”¾'=>'G','ð•²'=>'G','ð–¦'=>'G','ð—š'=>'G','ð˜Ž'=>'G','ð™‚'=>'G','ð™¶'=>'G','á³'=>'G','ℤ'=>'Z','ℨ'=>'Z','ð™'=>'Z','ð‘'=>'Z','ð’'=>'Z','ð’µ'=>'Z','ð“©'=>'Z','ð–…'=>'Z','ð–¹'=>'Z','ð—'=>'Z','ð˜¡'=>'Z','ð™•'=>'Z','ðš‰'=>'Z','ðš'=>'Z','ð›§'=>'Z','ðœ¡'=>'Z','ð›'=>'Z','ðž•'=>'Z','ð’'=>'S','ð‘†'=>'S','ð‘º'=>'S','ð’®'=>'S','ð“¢'=>'S','ð”–'=>'S','ð•Š'=>'S','ð•¾'=>'S','ð–²'=>'S','ð—¦'=>'S','ð˜š'=>'S','ð™Ž'=>'S','ðš‚'=>'S','áš'=>'S','ð•'=>'V','ð‘‰'=>'V','ð‘½'=>'V','ð’±'=>'V','ð“¥'=>'V','ð”™'=>'V','ð•'=>'V','ð–'=>'V','ð–µ'=>'V','ð—©'=>'V','ð˜'=>'V','ð™‘'=>'V','ðš…'=>'V','â„’'=>'L','ð‹'=>'L','ð¿'=>'L','ð‘³'=>'L','ð“›'=>'L','ð”'=>'L','ð•ƒ'=>'L','ð•·'=>'L','ð–«'=>'L','ð—Ÿ'=>'L','ð˜“'=>'L','ð™‡'=>'L','ð™»'=>'L','∑'=>'C','â…€'=>'C','â„‚'=>'C','â„'=>'C','ð‚'=>'C','ð¶'=>'C','ð‘ª'=>'C','ð’ž'=>'C','ð“’'=>'C','ð•®'=>'C','ð–¢'=>'C','ð—–'=>'C','ð˜Š'=>'C','ð˜¾'=>'C','ð™²'=>'C','ðšº'=>'C','ð›´'=>'C','ðœ®'=>'C','ð¨'=>'C','ðž¢'=>'C','â„™'=>'P','ð'=>'P','ð‘ƒ'=>'P','ð‘·'=>'P','ð’«'=>'P','ð“Ÿ'=>'P','ð”“'=>'P','ð•»'=>'P','ð–¯'=>'P','ð—£'=>'P','ð˜—'=>'P','ð™‹'=>'P','ð™¿'=>'P','ðš¸'=>'P','ð›²'=>'P','ðœ¬'=>'P','ð¦'=>'P','ðž '=>'P','ðŠ'=>'K','ð¾'=>'K','ð‘²'=>'K','ð’¦'=>'K','ð“š'=>'K','ð”Ž'=>'K','ð•‚'=>'K','ð•¶'=>'K','ð–ª'=>'K','ð—ž'=>'K','ð˜’'=>'K','ð™†'=>'K','ð™º'=>'K','ðš±'=>'K','ð›«'=>'K','ðœ¥'=>'K','ðŸ'=>'K','ðž™'=>'K','ℬ'=>'B','ð'=>'B','ðµ'=>'B','ð‘©'=>'B','ð“‘'=>'B','ð”…'=>'B','ð”¹'=>'B','ð•'=>'B','ð–¡'=>'B','ð—•'=>'B','ð˜‰'=>'B','ð˜½'=>'B','ð™±'=>'B','ðš©'=>'B','ð›£'=>'B','ðœ'=>'B','ð—'=>'B','ðž‘'=>'B','á'=>'á·','∆'=>'áƒ','ðš«'=>'áƒ','ð›¥'=>'áƒ','ðœŸ'=>'áƒ','ð™'=>'áƒ','ðž“'=>'áƒ','á'=>'áƒÂ·','á‘'=>'á„·','á“'=>'á…·','á•'=>'á†Â·','á˜'=>'áŠÂ·','áš'=>'á‹Â·','á“‘'=>'á¡','á‘¶'=>'·P','ᑺ'=>'·d','á’˜'=>'·J','á‘'=>'á³Â·','ᑃ'=>'á´Â·','á‘…'=>'á¸Â·','ᑇ'=>'á¹Â·','ˈ'=>'ᑊ','ᑘ'=>'ᑌ·','á‘§'=>'ᑌᑊ','ᑚ'=>'ᑎ·','ᑨ'=>'ᑎᑊ','ᑜ'=>'á‘·','ᑞ'=>'á‘·','á‘©'=>'á‘ᑊ','á‘ '=>'ᑑ·','á‘¢'=>'ᑕ·','ᑪ'=>'ᑕᑊ','ᑤ'=>'ᑖ·','ᑵ'=>'ᑫ·','á’…'=>'ᑫᑊ','á‘·'=>'P·','á’†'=>'Pᑊ','ᑹ'=>'ᑮ·','á‘»'=>'d·','á’‡'=>'dᑊ','ᑽ'=>'ᑰ·','á‘¿'=>'ᑲ·','á’ˆ'=>'ᑲᑊ','á’'=>'ᑳ·','ᘃ'=>'á’‰','á’“'=>'ᒉ·','á’•'=>'ᒋ·','á’—'=>'ᒌ·','á’™'=>'J·','á’›'=>'ᒎ·','ᘂ'=>'á’','á’'=>'á’·','á’Ÿ'=>'ᒑ·','á’'=>'ᒣ·','á’¯'=>'ᒥ·','á’±'=>'ᒦ·','á’³'=>'ᒧ·','á’µ'=>'ᒨ·','á’¹'=>'ᒫ·','ᓊ'=>'ᓀ·','ᓌ'=>'ᓇ·','ᓎ'=>'ᓈᒫ','ᘄ'=>'á““','á“'=>'ᓓ·','ᓟ'=>'ᓕ·','á“¡'=>'ᓖ·','á“£'=>'ᓗ·','á“¥'=>'ᓘ·','ᘇ'=>'ᓚ','á“§'=>'ᓚ·','á“©'=>'ᓛ·','á“·'=>'á“·','ᓹ'=>'ᓯ·','á“»'=>'ᓰ·','ᓽ'=>'ᓱ·','á“¿'=>'ᓲ·','á”'=>'ᓴ·','ᔃ'=>'ᓵ·','ᔌ'=>'ᔋá¸','á”'=>'ᔋᑕ','ᔎ'=>'ᔋᑲ','á”'=>'ᔋá’','ᔘ'=>'á”·','ᔚ'=>'ᔑ·','ᔜ'=>'ᔒ·','ᔞ'=>'ᔓ·','á” '=>'ᔔ·','ᔢ'=>'ᔕ·','ᔤ'=>'ᔖ·','ᔲ'=>'ᔨ·','á”´'=>'ᔩ·','á”¶'=>'ᔪ·','ᔸ'=>'ᔫ·','ᔺ'=>'á”·','ᔼ'=>'ᔮ·','á™®'=>'x','ᕽ'=>'x','ᘢ'=>'ᕃ','ᘣ'=>'ᕆ','ᘤ'=>'ᕊ','á•'=>'ᕌ·','ᙯ'=>'á•á‘«','ᕾ'=>'á•ᑬ','á•¿'=>'á•P','á–€'=>'á•á‘®','á–'=>'á•d','á–‚'=>'á•á‘°','á–ƒ'=>'á•ᑲ','á–„'=>'á•ᑳ','á–…'=>'á•á’ƒ','ᕜ'=>'ᕚ·','á•©'=>'ᕧ·','â„›'=>'R','ℜ'=>'R','â„'=>'R','ð‘'=>'R','ð‘…'=>'R','ð‘¹'=>'R','ð“¡'=>'R','ð•½'=>'R','ð–±'=>'R','ð—¥'=>'R','ð˜™'=>'R','ð™'=>'R','ðš'=>'R','á™°'=>'á–•á’‰','á–Ž'=>'á–•á’Š','á–'=>'á–•á’‹','á–'=>'á–•á’Œ','á–‘'=>'á–•J','á–’'=>'á–•á’Ž','á–“'=>'á–•á’','á–”'=>'á–•á’‘','á™±'=>'á––á’‹','ᙲ'=>'á––á’Œ','ᙳ'=>'á––J','á™´'=>'á––á’Ž','ᙵ'=>'á––á’','á™¶'=>'á––á’‘','ℱ'=>'F','ð…'=>'F','ð¹'=>'F','ð‘'=>'F','ð“•'=>'F','ð”‰'=>'F','ð”½'=>'F','ð•±'=>'F','ð–¥'=>'F','ð—™'=>'F','ð˜'=>'F','ð™'=>'F','ð™µ'=>'F','ðŸŠ'=>'F','â……'=>'D','ðƒ'=>'D','ð·'=>'D','ð‘«'=>'D','ð’Ÿ'=>'D','ð““'=>'D','ð”‡'=>'D','ð”»'=>'D','ð•¯'=>'D','ð–£'=>'D','ð——'=>'D','ð˜‹'=>'D','ð˜¿'=>'D','ð™³'=>'D','á—ª'=>'D','â„§'=>'ᘮ','ᘴ'=>'ᘮ','ð›€'=>'ᘯ','ð›º'=>'ᘯ','ðœ´'=>'ᘯ','ð®'=>'ᘯ','ðž¨'=>'ᘯ','ᘵ'=>'ᘯ','ㄱ'=>'á„€','ᄀ'=>'á„€','ᆨ'=>'á„€','ㄲ'=>'á„','ï¾¢'=>'á„','ᆩ'=>'á„','ã„´'=>'á„‚','ᄂ'=>'á„‚','ᆫ'=>'á„‚','ã„·'=>'ᄃ','ï¾§'=>'ᄃ','ᆮ'=>'ᄃ','ㄸ'=>'á„„','ᄄ'=>'á„„','ㄹ'=>'á„…','ᄅ'=>'á„…','ᆯ'=>'á„…','ã…'=>'ᄆ','ï¾±'=>'ᄆ','ᆷ'=>'ᄆ','ã…‚'=>'ᄇ','ï¾²'=>'ᄇ','ᆸ'=>'ᄇ','ã…ƒ'=>'ᄈ','ï¾³'=>'ᄈ','ã……'=>'ᄉ','ï¾µ'=>'ᄉ','ᆺ'=>'ᄉ','ã…†'=>'ᄊ','ï¾¶'=>'ᄊ','ᆻ'=>'ᄊ','ã…‡'=>'á„‹','ï¾·'=>'á„‹','ᆼ'=>'á„‹','ã…ˆ'=>'ᄌ','ᄌ'=>'ᄌ','ᆽ'=>'ᄌ','ã…‰'=>'á„','ï¾¹'=>'á„','ã…Š'=>'ᄎ','ᄎ'=>'ᄎ','ᆾ'=>'ᄎ','ã…‹'=>'á„','ï¾»'=>'á„','ᆿ'=>'á„','ã…Œ'=>'á„','ï¾¼'=>'á„','ᇀ'=>'á„','ã…'=>'á„‘','ï¾½'=>'á„‘','á‡'=>'á„‘','ã…Ž'=>'á„’','ï¾¾'=>'á„’','ᇂ'=>'á„’','ᇅ'=>'á„“','ã…¥'=>'á„”','ã…¦'=>'á„•','ᇆ'=>'á„•','ᇊ'=>'á„—','á‡'=>'ᄘ','á‡'=>'á„™','ã…€'=>'ᄚ','ï¾°'=>'ᄚ','á„»'=>'ᄚ','ᆶ'=>'ᄚ','ã…®'=>'ᄜ','ᇜ'=>'ᄜ','ã…±'=>'á„','ᇢ'=>'á„','ã…²'=>'ᄞ','ã…³'=>'á„ ','ã…„'=>'á„¡','ï¾´'=>'á„¡','ᆹ'=>'á„¡','ã…´'=>'á„¢','ã…µ'=>'á„£','ã…¶'=>'á„§','ã…·'=>'á„©','ã…¸'=>'á„«','ᇦ'=>'á„«','ã…¹'=>'ᄬ','ã…º'=>'á„','ᇧ'=>'á„','ã…»'=>'á„®','ã…¼'=>'ᄯ','ᇨ'=>'ᄯ','ᇩ'=>'á„°','ã…½'=>'ᄲ','ᇪ'=>'ᄲ','ã…¾'=>'á„¶','ã…¿'=>'á…€','ᇫ'=>'á…€','ᇬ'=>'á…','ᇱ'=>'á……','ㆂ'=>'á……','ᇲ'=>'á…†','ㆃ'=>'á…†','ㆀ'=>'á…‡','ᇮ'=>'á…‡','ã†'=>'á…Œ','ᇰ'=>'á…Œ','ᇳ'=>'á…–','ㆄ'=>'á…—','ᇴ'=>'á…—','ㆅ'=>'á…˜','ㆆ'=>'á…™','ᇹ'=>'á…™','ã…¤'=>'á… ','ï¾ '=>'á… ','ã…'=>'á…¡','ï¿‚'=>'á…¡','ã…'=>'á…¢','ᅢ'=>'á…¢','ã…‘'=>'á…£','ï¿„'=>'á…£','ã…’'=>'á…¤','ï¿…'=>'á…¤','ã…“'=>'á…¥','ᅥ'=>'á…¥','ã…”'=>'á…¦','ᅦ'=>'á…¦','ã…•'=>'á…§','ᅧ'=>'á…§','ã…–'=>'á…¨','ï¿‹'=>'á…¨','ã…—'=>'á…©','ᅩ'=>'á…©','ã…˜'=>'á…ª','ï¿'=>'á…ª','ã…™'=>'á…«','ᅫ'=>'á…«','ã…š'=>'á…¬','ï¿'=>'á…¬','ã…›'=>'á…','ï¿’'=>'á…','ã…œ'=>'á…®','ï¿“'=>'á…®','ã…'=>'á…¯','ï¿”'=>'á…¯','ã…ž'=>'á…°','ï¿•'=>'á…°','ã…Ÿ'=>'á…±','ï¿–'=>'á…±','ã… '=>'á…²','ï¿—'=>'á…²','ã…¡'=>'一','ᅳ'=>'一','ã…¢'=>'á…´','ï¿›'=>'á…´','ã…£'=>'丨','ᅵ'=>'丨','ㆇ'=>'ᆄ','ᆆ'=>'ᆄ','ㆈ'=>'ᆅ','ㆉ'=>'ᆈ','ㆊ'=>'ᆑ','ㆋ'=>'ᆒ','ㆌ'=>'ᆔ','ã†'=>'ᆞ','ㆎ'=>'ᆡ','ㄳ'=>'ᆪ','ï¾£'=>'ᆪ','ㄵ'=>'ᆬ','ï¾¥'=>'ᆬ','ã„¶'=>'á†','ᆭ'=>'á†','ㄺ'=>'ᆰ','ᆰ'=>'ᆰ','ã„»'=>'ᆱ','ᆱ'=>'ᆱ','ㄼ'=>'ᆲ','ᆲ'=>'ᆲ','ㄽ'=>'ᆳ','ï¾'=>'ᆳ','ㄾ'=>'ᆴ','ï¾®'=>'ᆴ','ã„¿'=>'ᆵ','ᆵ'=>'ᆵ','ã…§'=>'ᇇ','ã…¨'=>'ᇈ','ã…©'=>'ᇌ','ã…ª'=>'ᇎ','ã…«'=>'ᇓ','ã…¬'=>'ᇗ','ã…'=>'ᇙ','ã…¯'=>'á‡','ã…°'=>'ᇟ','ï½§'=>'ã‚¡','ï½±'=>'ã‚¢','ィ'=>'ã‚£','ï½²'=>'イ','ゥ'=>'ã‚¥','ï½³'=>'ウ','ェ'=>'ã‚§','ï½´'=>'エ','ォ'=>'ã‚©','ï½µ'=>'オ','ï½¶'=>'ã‚«','ï½·'=>'ã‚','ク'=>'ク','ï½¹'=>'ケ','コ'=>'コ','ï½»'=>'サ','ï½¼'=>'ã‚·','ï½½'=>'ス','ï½¾'=>'ã‚»','ソ'=>'ソ','ï¾€'=>'ã‚¿','ï¾'=>'ãƒ','ッ'=>'ッ','ツ'=>'ツ','テ'=>'テ','ト'=>'ト','ï¾…'=>'ナ','ニ'=>'ニ','ヌ'=>'ヌ','ネ'=>'ãƒ','ノ'=>'ノ','ハ'=>'ãƒ','ヒ'=>'ヒ','フ'=>'フ','ï¾'=>'ã¸','ホ'=>'ホ','ï¾'=>'マ','â§„'=>'〼','ï¾'=>'ミ','ム'=>'ム','ï¾’'=>'メ','モ'=>'モ','ャ'=>'ャ','ï¾”'=>'ヤ','ï½'=>'ュ','ユ'=>'ユ','ï½®'=>'ョ','ï¾–'=>'ヨ','ï¾—'=>'ラ','リ'=>'リ','ï¾™'=>'ル','レ'=>'レ','ï¾›'=>'ãƒ','ワ'=>'ワ','ヲ'=>'ヲ','ï¾'=>'ン','ê’ž'=>'êŠ','ê’¬'=>'ê','ê’œ'=>'ꃀ','ê’¿'=>'ꉙ','ê’¾'=>'ꊱ','ê“€'=>'ꎫ','ê“‚'=>'ꎵ','ê’º'=>'ꎿ','ê’°'=>'ê‚','ð’ '=>'ð’†','—'=>'一','―'=>'一','−'=>'一','─'=>'一','â¼€'=>'一','不'=>'ä¸','ï©°'=>'並','|'=>'丨','|'=>'丨','∣'=>'丨','â¼'=>'丨','‖'=>'丨丨','∥'=>'丨丨','串'=>'串','⼂'=>'丶','ð¯ '=>'丸','丹'=>'丹','丽'=>'丽','⼃'=>'丿','乁'=>'ä¹','⼄'=>'ä¹™','亂'=>'亂','â¼…'=>'亅','了'=>'了','⼆'=>'二','⼇'=>'äº ','亮'=>'亮','⼈'=>'人','ï§½'=>'什','仌'=>'仌','令'=>'令','你'=>'ä½ ','倂'=>'ä½µ','倂'=>'ä½µ','侀'=>'ä¾€','ï¤'=>'來','例'=>'例','侮'=>'ä¾®','侮'=>'ä¾®','侻'=>'ä¾»','便'=>'便','值'=>'値','ï§”'=>'倫','偺'=>'åº','備'=>'å‚™','像'=>'åƒ','僚'=>'僚','僧'=>'僧','僧'=>'僧','⼉'=>'å„¿','兀'=>'å…€','ï©´'=>'å……','免'=>'å…','免'=>'å…','ð¯ '=>'å…”','ð¯ '=>'å…¤','⼊'=>'å…¥','內'=>'å…§','全'=>'å…¨','兩'=>'å…©','⼋'=>'å…«','ï§‘'=>'å…','具'=>'å…·','冀'=>'冀','⼌'=>'冂','再'=>'å†','冒'=>'冒','冕'=>'冕','â¼'=>'冖','冗'=>'冗','冤'=>'冤','⼎'=>'冫','冬'=>'冬','况'=>'况','况'=>'况','冷'=>'冷','凉'=>'凉','凌'=>'凌','凜'=>'凜','凞'=>'凞','â¼'=>'å‡ ','ð¯ '=>'凵','â¼'=>'凵','⼑'=>'刀','刃'=>'刃','切'=>'切','ð¯¡'=>'切','列'=>'列','ï§'=>'利','ï§¿'=>'刺','ð¯ '=>'刻','剆'=>'剆','割'=>'割','剷'=>'剷','劉'=>'劉','力'=>'力','â¼’'=>'力','ï¦'=>'劣','劳'=>'劳','ï©¶'=>'勇','勇'=>'勇','勉'=>'勉','勉'=>'勉','勒'=>'å‹’','勞'=>'勞','勤'=>'勤','勤'=>'勤','勵'=>'勵','⼓'=>'勹','ï©·'=>'勺','勺'=>'勺','包'=>'包','匆'=>'匆','â¼”'=>'匕','北'=>'北','北'=>'北','⼕'=>'匚','â¼–'=>'匸','ï§«'=>'匿','â¼—'=>'å','〸'=>'å','〹'=>'å„','〺'=>'å…','卉'=>'å‰','卑'=>'å‘','ð¯ '=>'å‘','博'=>'åš','⼘'=>'åœ','â¼™'=>'å©','即'=>'å³','卵'=>'åµ','卽'=>'å½','卿'=>'å¿','卿'=>'å¿','卿'=>'å¿','⼚'=>'厂','â¼›'=>'厶','參'=>'åƒ','⼜'=>'åˆ','及'=>'åŠ','叟'=>'åŸ','â¼'=>'å£','句'=>'å¥','叫'=>'å«','叱'=>'å±','吆'=>'å†','ï§ž'=>'å','ï§'=>'å','吸'=>'å¸','呂'=>'å‘‚','呈'=>'呈','周'=>'周','咞'=>'å’ž','咢'=>'å’¢','咽'=>'å’½','ð¯¡'=>'å“¶','唐'=>'å”','啓'=>'å•“','啟'=>'å•“','啕'=>'å••','啣'=>'å•£','善'=>'å–„','善'=>'å–„','喇'=>'å–‡','喙'=>'å–™','喙'=>'å–™','喝'=>'å–','喝'=>'å–','喫'=>'å–«','喳'=>'å–³','ï¨'=>'å—€','嗂'=>'å—‚','ï©»'=>'å—¢','嘆'=>'嘆','嘆'=>'嘆','噑'=>'噑','器'=>'器','ð¯¡'=>'å™´','⼞'=>'å›—','囹'=>'囹','圖'=>'圖','ð¯¡'=>'圗','⼟'=>'土','型'=>'åž‹','城'=>'城','埴'=>'埴','堍'=>'å ','報'=>'å ±','堲'=>'å ²','塀'=>'å¡€','ï¨'=>'塚','塚'=>'塚','塞'=>'塞','å¡«'=>'å¡¡','墨'=>'墨','壿'=>'墫','墬'=>'墬','墳'=>'墳','壘'=>'壘','壟'=>'壟','â¼ '=>'士','壮'=>'壮','売'=>'売','壷'=>'壷','⼡'=>'夂','夆'=>'夆','â¼¢'=>'夊','â¼£'=>'夕','ð¯¡'=>'多','夢'=>'夢','⼤'=>'大','奄'=>'奄','奈'=>'奈','契'=>'契','ï©¿'=>'奔','奢'=>'奢','ï¦'=>'女','â¼¥'=>'女','姘'=>'姘','姬'=>'姬','娛'=>'娛','娧'=>'娧','婢'=>'å©¢','婦'=>'婦','嬀'=>'媯','媵'=>'媵','嬈'=>'嬈','ïª'=>'嬨','嬾'=>'嬾','嬾'=>'嬾','⼦'=>'å','â¼§'=>'宀','宅'=>'å®…','ð¯¡'=>'寃','寘'=>'寘','寧'=>'寧','寧'=>'寧','寧'=>'寧','寮'=>'寮','寳'=>'寳','⼨'=>'寸','寿'=>'寿','将'=>'å°†','⼩'=>'å°','尢'=>'å°¢','⼪'=>'å°¢','⼫'=>'å°¸','尿'=>'å°¿','屠'=>'å± ','屢'=>'å±¢','層'=>'層','ï§Ÿ'=>'å±¥','屮'=>'å±®','屮'=>'å±®','⼬'=>'å±®','â¼'=>'å±±','岍'=>'å²','峀'=>'å³€','ï§•'=>'å´™','嵃'=>'嵃','嵐'=>'åµ','嵫'=>'嵫','嵮'=>'åµ®','嵼'=>'åµ¼','嶲'=>'å¶²','嶺'=>'嶺','â¼®'=>'å·›','ð¯¢'=>'å·¡','巢'=>'å·¢','⼯'=>'å·¥','â¼°'=>'å·±','巽'=>'å·½','â¼±'=>'å·¾','帲'=>'帡','帨'=>'帨','帽'=>'帽','幩'=>'幩','â¼²'=>'å¹²','年'=>'å¹´','â¼³'=>'幺','â¼´'=>'广','ï¨'=>'度','庰'=>'庰','庳'=>'庳','ð¯¢'=>'庶','廉'=>'廉','廊'=>'廊','廊'=>'廊','廒'=>'å»’','廓'=>'廓','廙'=>'å»™','廬'=>'廬','â¼µ'=>'å»´','ð¯¢'=>'廾','â¼¶'=>'廾','弄'=>'弄','â¼·'=>'弋','⼸'=>'弓','弢'=>'å¼¢','弢'=>'å¼¢','â¼¹'=>'å½','当'=>'当','⼺'=>'彡','形'=>'å½¢','彩'=>'彩','彫'=>'彫','â¼»'=>'å½³','律'=>'律','徚'=>'徚','復'=>'復','徭'=>'å¾','â¼¼'=>'心','ð¯¢'=>'å¿','志'=>'å¿—','念'=>'念','忹'=>'忹','ï¥ '=>'怒','怜'=>'怜','悁'=>'æ‚','悔'=>'æ‚”','悔'=>'æ‚”','惇'=>'惇','惘'=>'惘','惡'=>'惡','愈'=>'愈','ï§™'=>'æ…„','慈'=>'æ…ˆ','慌'=>'æ…Œ','慌'=>'æ…Œ','慎'=>'æ…Ž','慎'=>'æ…Ž','慠'=>'æ… ','慨'=>'æ…¨','慺'=>'æ…º','憎'=>'憎','憎'=>'憎','憎'=>'憎','ï¦'=>'æ†','ð¯¢'=>'憤','憯'=>'憯','憲'=>'憲','懞'=>'懞','ï©€'=>'懲','懲'=>'懲','懲'=>'懲','ï¤'=>'懶','懶'=>'懶','ï¦'=>'戀','â¼½'=>'戈','成'=>'æˆ','戛'=>'戛','ï§’'=>'戮','戴'=>'戴','â¼¾'=>'戶','⼿'=>'手','扝'=>'æ‰','抱'=>'抱','拉'=>'拉','拏'=>'æ‹','拓'=>'æ‹“','拔'=>'æ‹”','拼'=>'拼','拾'=>'拾','挽'=>'挽','捐'=>'æ','捨'=>'æ¨','捻'=>'æ»','掃'=>'掃','掠'=>'æŽ ','ð¯£'=>'掩','ïª'=>'æ„','揅'=>'æ…','揤'=>'æ¤','ã©'=>'æ‰','搜'=>'æœ','搢'=>'æ¢','ïª'=>'æ‘’','摩'=>'æ‘©','摷'=>'æ‘·','摾'=>'摾','撚'=>'æ’š','撝'=>'æ’','擄'=>'æ“„','â½€'=>'支','â½'=>'æ”´','ï©'=>'æ•','敏'=>'æ•','ïª'=>'æ•–','敬'=>'敬','數'=>'數','⽂'=>'æ–‡','⽃'=>'æ–—','料'=>'æ–™','⽄'=>'æ–¤','â½…'=>'æ–¹','旅'=>'æ—…','⽆'=>'æ— ','ï©‚'=>'æ—¢','旣'=>'æ—£','⽇'=>'æ—¥','ï§ '=>'易','ð¯£'=>'晉','晩'=>'晚','䀿'=>'晣','晴'=>'æ™´','晴'=>'æ™´','ï§…'=>'暈','暑'=>'æš‘','ð¯£'=>'æš‘','暜'=>'æšœ','暴'=>'æš´','曆'=>'曆','⽈'=>'æ›°','ï¤'=>'æ›´','㫚'=>'æ›¶','書'=>'書','最'=>'最','⽉'=>'月','肦'=>'朌','èƒ'=>'æœ','胊'=>'æœ','è„'=>'朓','朗'=>'朗','朗'=>'朗','朗'=>'朗','è„§'=>'朘','望'=>'望','望'=>'望','朡'=>'朡','膧'=>'朣','⽊'=>'木','ï§¡'=>'æŽ','杓'=>'æ“','杖'=>'æ–','杞'=>'æž','柿'=>'æ®','杻'=>'æ»','枅'=>'æž…','ï§´'=>'æž—','柳'=>'柳','柺'=>'柺','ï§š'=>'æ —','栟'=>'æ Ÿ','桒'=>'æ¡’','梁'=>'æ¢','ï©„'=>'梅','梅'=>'梅','梎'=>'梎','ï§¢'=>'梨','椔'=>'椔','楂'=>'楂','樧'=>'æ¦','榣'=>'榣','槪'=>'槪','樂'=>'樂','樂'=>'樂','樂'=>'樂','樓'=>'樓','檨'=>'檨','櫓'=>'æ«“','ð¯£'=>'æ«›','ï¤'=>'欄','⽋'=>'æ¬ ','次'=>'次','歔'=>'æ”','⽌'=>'æ¢','歲'=>'æ²','歷'=>'æ·','歹'=>'æ¹','â½'=>'æ¹','殟'=>'殟','殮'=>'æ®®','⽎'=>'殳','殺'=>'殺','殺'=>'殺','殺'=>'殺','殻'=>'æ®»','â½'=>'毋','⺟'=>'æ¯','â½'=>'比','⽑'=>'毛','â½’'=>'æ°','⽓'=>'æ°”','â½”'=>'æ°´','汎'=>'汎','汧'=>'æ±§','沈'=>'沈','沿'=>'沿','泌'=>'泌','泍'=>'æ³','ï§£'=>'æ³¥','洖'=>'æ´–','洛'=>'æ´›','洞'=>'æ´ž','洴'=>'æ´´','派'=>'æ´¾','ï§Š'=>'æµ','流'=>'æµ','流'=>'æµ','浩'=>'浩','浪'=>'浪','ï©…'=>'æµ·','ð¯¤'=>'æµ·','浸'=>'浸','涅'=>'æ¶…','ï§µ'=>'æ·‹','ï¥'=>'æ·š','ï§–'=>'æ·ª','淹'=>'æ·¹','渚'=>'渚','港'=>'港','湮'=>'æ¹®','æ½™'=>'溈','ï§‹'=>'溜','溺'=>'溺','滇'=>'滇','滋'=>'滋','滋'=>'滋','滑'=>'滑','滛'=>'æ»›','漏'=>'æ¼','漢'=>'æ¼¢','漢'=>'æ¼¢','漣'=>'æ¼£','ð¯¤'=>'æ½®','濆'=>'濆','濫'=>'æ¿«','濾'=>'濾','瀛'=>'瀛','瀞'=>'瀞','瀞'=>'瀞','瀹'=>'瀹','灊'=>'çŠ','⽕'=>'ç«','灰'=>'ç°','灷'=>'ç·','災'=>'ç½','ï§»'=>'ç‚™','炭'=>'ç‚','烈'=>'烈','烙'=>'烙','煅'=>'ç……','煉'=>'ç…‰','煮'=>'ç…®','煮'=>'ç…®','熜'=>'熜','ï§€'=>'燎','ï§®'=>'ç‡','爐'=>'çˆ','爛'=>'爛','爨'=>'爨','â½–'=>'爪','爫'=>'爫','⺤'=>'爫','爵'=>'爵','爵'=>'爵','â½—'=>'父','⽘'=>'爻','â½™'=>'爿','⽚'=>'片','牐'=>'ç‰','â½›'=>'牙','⽜'=>'牛','牢'=>'牢','犀'=>'犀','犕'=>'犕','â½'=>'犬','犯'=>'犯','狀'=>'ç‹€','狼'=>'狼','猪'=>'猪','ïª '=>'猪','獵'=>'çµ','獺'=>'çº','⽞'=>'玄','率'=>'率','ï§›'=>'率','⽟'=>'玉','王'=>'王','玥'=>'玥','ï¦'=>'玲','珞'=>'çž','理'=>'ç†','ï§Œ'=>'ç‰','琢'=>'ç¢','瑇'=>'瑇','瑜'=>'瑜','瑩'=>'ç‘©','瑱'=>'瑱','瑱'=>'瑱','璅'=>'ç’…','璉'=>'ç’‰','璘'=>'ç’˜','瓊'=>'瓊','â½ '=>'瓜','⽡'=>'瓦','甆'=>'甆','â½¢'=>'甘','â½£'=>'生','甤'=>'甤','⽤'=>'用','â½¥'=>'ç”°','画'=>'ç”»','甾'=>'甾','ï§'=>'ç•™','略'=>'ç•¥','異'=>'ç•°','異'=>'ç•°','⽦'=>'ç–‹','â½§'=>'ç–’','ï§¥'=>'ç—¢','瘐'=>'ç˜','瘝'=>'ç˜','瘟'=>'瘟','ï§'=>'療','癩'=>'癩','⽨'=>'ç™¶','⽩'=>'白','⽪'=>'çš®','⽫'=>'çš¿','益'=>'益','益'=>'益','盛'=>'ç››','盧'=>'ç›§','⽬'=>'ç›®','直'=>'ç›´','直'=>'ç›´','ï¥'=>'çœ','眞'=>'眞','真'=>'真','真'=>'真','着'=>'ç€','睊'=>'çŠ','睊'=>'çŠ','瞋'=>'çž‹','ïª'=>'çž§','â½'=>'矛','â½®'=>'矢','⽯'=>'石','ç¡'=>'ç ”','硎'=>'硎','ï§Ž'=>'ç¡«','碌'=>'碌','ð¯¥'=>'碌','ï©‹'=>'碑','磊'=>'磊','磌'=>'磌','ð¯¥'=>'磌','磻'=>'磻','礪'=>'礪','â½°'=>'示','礼'=>'礼','社'=>'社','祈'=>'祈','ï©'=>'祉','ï©'=>'ç¥','ï©'=>'祖','祖'=>'祖','ï©‘'=>'ç¥','神'=>'神','祥'=>'祥','祿'=>'祿','ï©’'=>'ç¦','ï©“'=>'禎','福'=>'ç¦','福'=>'ç¦','禮'=>'禮','â½±'=>'禸','â½²'=>'禾','秊'=>'ç§Š','秫'=>'ç§«','稜'=>'稜','ï©”'=>'ç©€','穀'=>'ç©€','穊'=>'穊','穏'=>'ç©','â½³'=>'ç©´','ï©•'=>'çª','窱'=>'窱','ï§·'=>'ç«‹','â½´'=>'ç«‹','竮'=>'ç«®','â½µ'=>'竹','笠'=>'ç¬ ','ï©–'=>'節','ïª'=>'節','篆'=>'篆','築'=>'築','簾'=>'ç°¾','籠'=>'ç± ','â½¶'=>'ç±³','类'=>'ç±»','ï§¹'=>'ç²’','ï¨'=>'ç²¾','糒'=>'ç³’','糖'=>'ç³–','糣'=>'ç³£','糧'=>'ç³§','糨'=>'糨','â½·'=>'糸','紀'=>'ç´€','ï§'=>'ç´','索'=>'ç´¢','ï¥'=>'ç´¯','çµ¶'=>'絕','絛'=>'çµ›','絣'=>'çµ£','綠'=>'ç¶ ','綾'=>'ç¶¾','緇'=>'ç·‡','練'=>'ç·´','ï©—'=>'ç·´','練'=>'ç·´','縂'=>'縂','縉'=>'縉','ï¥'=>'縷','ï©™'=>'ç¹','繅'=>'ç¹…','⽸'=>'ç¼¶','缾'=>'ç¼¾','â½¹'=>'网','⺫'=>'ç½’','署'=>'ç½²','罹'=>'ç½¹','罺'=>'罺','ï¤'=>'ç¾…','⽺'=>'羊','羕'=>'羕','羚'=>'羚','羽'=>'ç¾½','â½»'=>'ç¾½','翺'=>'翺','老'=>'è€','â½¼'=>'è€','ï©›'=>'者','者'=>'者','者'=>'者','â½½'=>'而','â½¾'=>'耒','⽿'=>'耳','聆'=>'è†','聠'=>'è ','聯'=>'è¯','聰'=>'è°','聾'=>'è¾','â¾€'=>'è¿','â¾'=>'肉','肋'=>'è‚‹','肭'=>'è‚','育'=>'育','㬵'=>'胶','è…'=>'胼','脃'=>'脃','脾'=>'脾','臘'=>'臘','⾂'=>'臣','ï§¶'=>'臨','⾃'=>'自','臭'=>'è‡','⾄'=>'至','â¾…'=>'臼','舁'=>'èˆ','舁'=>'èˆ','舄'=>'舄','⾆'=>'舌','⾇'=>'舛','⾈'=>'舟','⾉'=>'艮','良'=>'良','⾊'=>'色','⾋'=>'艸','ï©'=>'艹','艹'=>'艹','ð¯¦'=>'芋','ð¯¦'=>'芑','芝'=>'èŠ','花'=>'花','芳'=>'芳','芽'=>'芽','若'=>'è‹¥','若'=>'è‹¥','苦'=>'苦','茝'=>'èŒ','茣'=>'茣','ï§¾'=>'茶','荒'=>'è’','荓'=>'è“','荣'=>'è£','莭'=>'èŽ','ð¯¦'=>'莽','菉'=>'è‰','菊'=>'èŠ','菌'=>'èŒ','菜'=>'èœ','菧'=>'è§','華'=>'è¯','菱'=>'è±','落'=>'è½','葉'=>'葉','著'=>'è‘—','著'=>'è‘—','蔿'=>'è’','蓮'=>'è“®','蓱'=>'蓱','蓳'=>'蓳','ï§‚'=>'蓼','蔖'=>'è”–','蕤'=>'蕤','藍'=>'è—','ï§°'=>'è—º','蘆'=>'蘆','ï¨ '=>'蘒','蘭'=>'è˜','è™'=>'蘷','ï¤'=>'蘿','⾌'=>'è™','虐'=>'è™','虜'=>'虜','虜'=>'虜','虧'=>'è™§','虩'=>'虩','â¾'=>'虫','蚈'=>'蚈','蚩'=>'èš©','蛢'=>'蛢','蜎'=>'蜎','蜨'=>'蜨','蝫'=>'è«','蝹'=>'è¹','蝹'=>'è¹','螆'=>'螆','螺'=>'螺','蟡'=>'蟡','ð¯§'=>'è ','蠟'=>'è Ÿ','⾎'=>'è¡€','行'=>'行','â¾'=>'行','衠'=>'è¡ ','衣'=>'è¡£','â¾'=>'è¡£','ï¦ '=>'裂','ï§§'=>'è£','裗'=>'裗','裞'=>'裞','裡'=>'裡','裸'=>'裸','裺'=>'裺','ï© '=>'è¤','襁'=>'è¥','襤'=>'襤','⾑'=>'襾','覆'=>'覆','見'=>'見','â¾’'=>'見','ï©¡'=>'視','視'=>'視','⾓'=>'è§’','â¾”'=>'言','äš¶'=>'訞','詽'=>'訮','ð¯§'=>'èª ','說'=>'說','說'=>'說','調'=>'調','請'=>'è«‹','諒'=>'è«’','ï¥'=>'è«–','諭'=>'è«','ð¯§'=>'è«','諸'=>'諸','諸'=>'諸','ï¥'=>'諾','諾'=>'諾','ï©¢'=>'è¬','謁'=>'è¬','ï©£'=>'謹','謹'=>'謹','ï§¼'=>'è˜','讀'=>'讀','è®'=>'讆','ï«€'=>'變','變'=>'變','⾕'=>'è°·','â¾–'=>'豆','豈'=>'豈','豕'=>'豕','â¾—'=>'豕','⾘'=>'豸','â¾™'=>'è²','貫'=>'貫','賁'=>'è³','賂'=>'賂','賈'=>'賈','賓'=>'賓','ï©¥'=>'è´ˆ','ï«'=>'è´ˆ','贛'=>'è´›','⾚'=>'赤','â¾›'=>'èµ°','起'=>'èµ·','趆'=>'赿','⾜'=>'è¶³','趼'=>'è¶¼','跋'=>'è·‹','è·º'=>'è·¥','路'=>'è·¯','跰'=>'è·°','躛'=>'躗','â¾'=>'身','車'=>'車','⾞'=>'車','軔'=>'è»”','è¼§'=>'軿','輦'=>'輦','ï§—'=>'輪','ï«‚'=>'輸','輸'=>'輸','輻'=>'è¼»','ï¦'=>'è½¢','⾟'=>'è¾›','ð¯¦'=>'辞','辰'=>'è¾°','â¾ '=>'è¾°','⾡'=>'è¾µ','辶'=>'è¾¶','⻌'=>'è¾¶','連'=>'連','逸'=>'逸','ï©§'=>'逸','遲'=>'é²','遼'=>'é¼','邏'=>'é‚','â¾¢'=>'é‚‘','邔'=>'é‚”','郎'=>'郎','郱'=>'郱','都'=>'都','鄑'=>'é„‘','鄛'=>'é„›','â¾£'=>'é…‰','酪'=>'é…ª','ï«„'=>'醙','醴'=>'醴','⾤'=>'釆','ï§©'=>'里','â¾¥'=>'里','量'=>'é‡','金'=>'金','⾦'=>'金','鈴'=>'鈴','鈸'=>'鈸','ï«…'=>'鉶','鉼'=>'鉼','鋗'=>'é‹—','鋘'=>'鋘','錄'=>'錄','鍊'=>'éŠ','鎮'=>'éŽ','鏹'=>'é¹','鐕'=>'é•','â¾§'=>'é•·','⾨'=>'é–€','開'=>'é–‹','閭'=>'é–','閷'=>'é–·','⾩'=>'阜','阮'=>'阮','陋'=>'陋','降'=>'é™','陵'=>'陵','ï§“'=>'陸','陼'=>'陼','ï§œ'=>'隆','ï§±'=>'隣','⾪'=>'éš¶','隸'=>'隸','⾫'=>'éš¹','雃'=>'雃','離'=>'離','難'=>'難','難'=>'難','⾬'=>'雨','零'=>'é›¶','雷'=>'é›·','霣'=>'霣','露'=>'露','靈'=>'éˆ','â¾'=>'é‘','靖'=>'é–','靖'=>'é–','â¾®'=>'éž','⾯'=>'é¢','â¾°'=>'é©','â¾±'=>'韋','韛'=>'韛','韠'=>'éŸ ','â¾²'=>'éŸ','â¾³'=>'音','ï©©'=>'響','響'=>'響','â¾´'=>'é ','ï«‹'=>'é ‹','頋'=>'é ‹','頋'=>'é ‹','領'=>'é ˜','頩'=>'é ©','頻'=>'é »','頻'=>'é »','ï§'=>'類','â¾µ'=>'風','â¾¶'=>'飛','â»'=>'食','â¾·'=>'食','飢'=>'飢','飯'=>'飯','飼'=>'飼','館'=>'館','餩'=>'餩','⾸'=>'首','â¾¹'=>'香','馧'=>'馧','⾺'=>'馬','駂'=>'é§‚','駱'=>'é§±','駾'=>'é§¾','驪'=>'驪','â¾»'=>'骨','â¾¼'=>'高','â¾½'=>'髟','ï«'=>'鬒','鬒'=>'鬒','â¾¾'=>'鬥','⾿'=>'鬯','â¿€'=>'鬲','â¿'=>'鬼','â¿‚'=>'éš','魯'=>'é¯','鱀'=>'é±€','ï§²'=>'é±—','⿃'=>'é³¥','鳽'=>'é³½','ð¯¨'=>'éµ§','ï¨'=>'é¶´','鷺'=>'é·º','ï¤ '=>'鸞','鹃'=>'鹂','â¿„'=>'é¹µ','鹿'=>'鹿','â¿…'=>'鹿','麗'=>'麗','ï§³'=>'麟','⿆'=>'麥','麻'=>'麻','⿇'=>'麻','⿈'=>'黃','⿉'=>'é»','黎'=>'黎','⿊'=>'黑','黹'=>'黹','â¿‹'=>'黹','⿌'=>'黽','黾'=>'黾','鼅'=>'é¼…','â¿'=>'鼎','鼏'=>'é¼','⿎'=>'鼓','鼖'=>'é¼–','â¿'=>'é¼ ','鼻'=>'é¼»','â¿'=>'é¼»','齃'=>'齃','â¿‘'=>'齊','â¿’'=>'é½’','ï§„'=>'é¾','â¿“'=>'é¾','ï«™'=>'龎','龜'=>'龜','龜'=>'龜','龜'=>'龜','â¿”'=>'龜','⻳'=>'龟','â¿•'=>'é¾ ','㒞'=>'ã’ž','㒹'=>'ã’¹','㒻'=>'ã’»','㓟'=>'㓟','㔕'=>'㔕','䎛'=>'ã–ˆ','㛮'=>'ã›®','㛼'=>'㛼','㞁'=>'ãž','㠯'=>'ã ¯','㡢'=>'ã¡¢','㡼'=>'㡼','㣇'=>'㣇','㣣'=>'㣣','㤜'=>'㤜','㤺'=>'㤺','㨮'=>'㨮','㩬'=>'㩬','㫤'=>'㫤','ð¯£'=>'㬈','㬙'=>'㬙','ä '=>'㬻','㭉'=>'ã‰','ï«’'=>'ã®','㮝'=>'ã®','㰘'=>'ã°˜','㱎'=>'㱎','㴳'=>'ã´³','㶖'=>'ã¶–','㺬'=>'㺬','㺸'=>'㺸','ð¯¤'=>'㺸','㼛'=>'ã¼›','㿼'=>'㿼','䀈'=>'䀈','ï«“'=>'䀘','ï«”'=>'䀹','䀹'=>'䀹','䁆'=>'ä†','䂖'=>'ä‚–','䃣'=>'䃣','䄯'=>'䄯','䈂'=>'䈂','䈧'=>'䈧','䊠'=>'äŠ ','ð¯¥'=>'äŒ','䌴'=>'䌴','䍙'=>'ä™','ð¯¦'=>'ä•','䏙'=>'ä™','䐋'=>'ä‹','䑫'=>'ä‘«','䔫'=>'䔫','䕝'=>'ä•','䕡'=>'ä•¡','䕫'=>'ä•«','䗗'=>'ä——','䗹'=>'ä—¹','䘵'=>'䘵','ð¯§'=>'äš¾','䛇'=>'䛇','䦕'=>'䦕','䧦'=>'䧦','䩮'=>'ä©®','䩶'=>'ä©¶','䪲'=>'䪲','䬳'=>'䬳','䯎'=>'䯎','ð¯¨'=>'䳎','䳭'=>'ä³','䳸'=>'䳸','䵖'=>'äµ–','𠄢'=>'ð „¢','𠔜'=>'𠔜','𠔥'=>'𠔥','𠕋'=>'ð •‹','ð¯ '=>'𠘺','𠠄'=>'ð „','ð¯§'=>'𠣞','𠨬'=>'𠨬','𠭣'=>'ð £','𡓤'=>'𡓤','𡚨'=>'𡚨','𡛪'=>'𡛪','𡧈'=>'𡧈','𡬘'=>'𡬘','𡴋'=>'ð¡´‹','𡷤'=>'ð¡·¤','𡷦'=>'ð¡·¦','𢆃'=>'𢆃','𢆟'=>'𢆟','𢌱'=>'𢌱','𢌱'=>'𢌱','𢛔'=>'𢛔','ï«'=>'𢡄','ï«'=>'𢡊','𢬌'=>'𢬌','𢯱'=>'𢯱','𣀊'=>'𣀊','𣊸'=>'𣊸','𣍟'=>'ð£Ÿ','𣎓'=>'𣎓','𣎜'=>'𣎜','ð¯£'=>'ð£ƒ','ï«‘'=>'ð£•','𣑭'=>'ð£‘','𣚣'=>'𣚣','𣢧'=>'𣢧','𣪍'=>'ð£ª','𣫺'=>'𣫺','𣲼'=>'𣲼','𣴞'=>'𣴞','ð¯¤'=>'𣻑','ð¯¤'=>'𣽞','𣾎'=>'𣾎','ð¯¤'=>'𤉣','𤎫'=>'𤎫','𤘈'=>'𤘈','𤜵'=>'𤜵','𤠔'=>'𤠔','𤰶'=>'𤰶','𤲒'=>'𤲒','𤾡'=>'𤾡','𤾸'=>'𤾸','𥁄'=>'ð¥„','𥃲'=>'𥃲','ð¯¥'=>'𥃳','𥄙'=>'𥄙','𥄳'=>'𥄳','ï«•'=>'𥉉','ð¯¥'=>'ð¥','𥘦'=>'𥘦','𥚚'=>'𥚚','𥛅'=>'𥛅','𥥼'=>'𥥼','ð¯¥'=>'𥪧','𥪧'=>'𥪧','𥮫'=>'𥮫','𥲀'=>'𥲀','ï«–'=>'ð¥³','𥾆'=>'𥾆','𦇚'=>'𦇚','𦈨'=>'𦈨','𦉇'=>'𦉇','𦋙'=>'𦋙','𦌾'=>'𦌾','𦓚'=>'𦓚','𦔣'=>'𦔣','𦖨'=>'𦖨','𦞧'=>'𦞧','𦞵'=>'𦞵','𦬼'=>'𦬼','𦰶'=>'𦰶','𦳕'=>'𦳕','𦵫'=>'𦵫','ð¯¦'=>'𦼬','𦾱'=>'𦾱','𧃒'=>'𧃒','𧏊'=>'ð§Š','𧙧'=>'ð§™§','𧢮'=>'ð§¢®','𧥦'=>'𧥦','𧲨'=>'𧲨','ï«—'=>'𧻓','𧼯'=>'𧼯','𨗒'=>'𨗒','𨗭'=>'ð¨—','𨜮'=>'𨜮','ð¯§'=>'𨯺','𨵷'=>'𨵷','𩅅'=>'ð©……','𩇟'=>'𩇟','𩈚'=>'𩈚','𩐊'=>'ð©Š','𩒖'=>'ð©’–','ð¯¨'=>'ð©–¶','𩬰'=>'𩬰','ð¯¨'=>'𪃎','𪄅'=>'𪄅','𪈎'=>'𪈎','𪊑'=>'𪊑','ð¯¢'=>'𪎒','ð¯¨'=>'𪘀','℃'=>'°C','℉'=>'°F','ℇ'=>'Æ','â„»'=>'FAX','â„•'=>'N','â„–'=>'No','ℚ'=>'Q','₨'=>'Rs','ð“'=>'T','â„¡'=>'TEL','ð”'=>'U','ð–'=>'W','â‚©'=>'W̵','ð—'=>'X','Â¥'=>'Y̵','ðš²'=>'Λ','ðšµ'=>'Ξ','â„¿'=>'Î ','ϲ'=>'c','Ï’'=>'Y','ðš½'=>'Φ','ðš¿'=>'Ψ','Ñ£'=>'Ь̵','ਃ'=>'ঃ','ಃ'=>'à°ƒ','່'=>'่','់'=>'่','້'=>'้','໊'=>'๊','໋'=>'๋','៕'=>'๚','៚'=>'๛','ÑŠ'=>'ˉb','៙'=>'à¹','à³§'=>'à±§','૨'=>'२','೨'=>'౨','à«©'=>'३','૪'=>'४','à«®'=>'८','೯'=>'౯','а'=>'a','á'=>'b','á–¯'=>'b','Ñ'=>'c','Ô'=>'d','ᑯ'=>'d','е'=>'e','Ó™'=>'Ç','ε'=>'É›','Ñ”'=>'É›','Ö„'=>'f','Ö'=>'g','Ò»'=>'h','Õ°'=>'h','á‚'=>'h','á²'=>'hÌ”','ι'=>'i','Ñ–'=>'i','Ꭵ'=>'i','ј'=>'j','Õµ'=>'j','á—°'=>'m','Õ¸'=>'n','η'=>'nÌ©','à°‚'=>'o','ಂ'=>'o','à´‚'=>'o','०'=>'o','੦'=>'o','૦'=>'o','à¹'=>'o','à»'=>'o','ο'=>'o','о'=>'o','Ö…'=>'o','á€'=>'o','Ï'=>'p','Ñ€'=>'p','á´©'=>'á´˜','Õ£'=>'q','κ'=>'ĸ','к'=>'ĸ','á´¦'=>'r','г'=>'r','Ñ•'=>'s','Ï…'=>'u','Õ½'=>'u','ν'=>'v','ѵ'=>'v','Ꮃ'=>'w','á—¯'=>'w','Ñ…'=>'x','á•'=>'x','у'=>'y','Ꭹ'=>'y','Ó¡'=>'Ê’','ჳ'=>'Ê’','Ï©'=>'ƨ','ÑŒ'=>'Æ…','Ñ‹'=>'Æ…i','É‘'=>'α','Õ®'=>'δ','á•·'=>'δ','п'=>'Ï€','ɸ'=>'φ','Ñ„'=>'φ','Ê™'=>'в','Éœ'=>'з','á´'=>'м','Êœ'=>'н','É¢'=>'Ô','á´›'=>'Ñ‚','á´™'=>'Ñ','ઽ'=>'ऽ','à«'=>'à¥','à«‚'=>'ू','à©‹'=>'ॆ','à©'=>'à¥','à«'=>'à¥','à´‰'=>'உ','à´œ'=>'à®','à´£'=>'ண','à´´'=>'à®´','à´¿'=>'ி','àµ'=>'ூ','ಅ'=>'à°…','ಆ'=>'à°†','ಇ'=>'à°‡','ಒ'=>'à°’','ಓ'=>'ఒౕ','ಜ'=>'à°œ','ಞ'=>'à°ž','ಣ'=>'à°£','à°¥'=>'à°§Ö¼','ಯ'=>'à°¯','à° '=>'à°°Ö¼','ಱ'=>'à°±','ಲ'=>'à°²','à¶Œ'=>'à´¨àµà´¨','à®¶'=>'à´¶','ຈ'=>'จ','ບ'=>'บ','ປ'=>'ป','àº'=>'à¸','ພ'=>'พ','ຟ'=>'ฟ','àº'=>'ย','។'=>'ฯ','áž·'=>'ิ','ី'=>'ี','áž¹'=>'ึ','ឺ'=>'ื','ຸ'=>'ุ','ູ'=>'ู','á—…'=>'A','á’'=>'J','ᕼ'=>'H','á¯'=>'V','á‘'=>'P','á—·'=>'B','ヘ'=>'ã¸','ð‘'=>'ðŽ‚','ð“'=>'ðŽ“','𒀸'=>'ðŽš','á…³'=>'一','Ç€'=>'丨','á…µ'=>'丨','Ꭺ'=>'A','á´'=>'B','áŸ'=>'C','á—ž'=>'D','Ꭼ'=>'E','á–´'=>'F','á€'=>'G','Ꮋ'=>'H','Ꭻ'=>'J','á¦'=>'K','áž'=>'L','Ꮇ'=>'M','á¢'=>'P','á–‡'=>'R','á•'=>'S','á™'=>'V','áƒ'=>'Z');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_0.php b/phpBB/includes/utf/data/search_indexer_0.php deleted file mode 100644 index 3304b18cdd..0000000000 --- a/phpBB/includes/utf/data/search_indexer_0.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array(0=>'0',1=>'1',2=>'2',3=>'3',4=>'4',5=>'5',6=>'6',7=>'7',8=>'8',9=>'9','A'=>'a','B'=>'b','C'=>'c','D'=>'d','E'=>'e','F'=>'f','G'=>'g','H'=>'h','I'=>'i','J'=>'j','K'=>'k','L'=>'l','M'=>'m','N'=>'n','O'=>'o','P'=>'p','Q'=>'q','R'=>'r','S'=>'s','T'=>'t','U'=>'u','V'=>'v','W'=>'w','X'=>'x','Y'=>'y','Z'=>'z','a'=>'a','b'=>'b','c'=>'c','d'=>'d','e'=>'e','f'=>'f','g'=>'g','h'=>'h','i'=>'i','j'=>'j','k'=>'k','l'=>'l','m'=>'m','n'=>'n','o'=>'o','p'=>'p','q'=>'q','r'=>'r','s'=>'s','t'=>'t','u'=>'u','v'=>'v','w'=>'w','x'=>'x','y'=>'y','z'=>'z','ª'=>'ª','²'=>'2','³'=>'3','µ'=>'µ','¹'=>'1','º'=>'º','¼'=>'1/4','½'=>'1/2','¾'=>'3/4','À'=>'à ','Ã'=>'á','Â'=>'â','Ã'=>'ã','Ä'=>'ae','Ã…'=>'Ã¥','Æ'=>'ae','Ç'=>'ç','È'=>'è','É'=>'é','Ê'=>'ê','Ë'=>'ë','ÃŒ'=>'ì','Ã'=>'Ã','ÃŽ'=>'î','Ã'=>'ï','Ã'=>'ð','Ñ'=>'ñ','Ã’'=>'ò','Ó'=>'ó','Ô'=>'ô','Õ'=>'õ','Ö'=>'oe','Ø'=>'ø','Ù'=>'ù','Ú'=>'ú','Û'=>'û','Ü'=>'ü','Ã'=>'ý','Þ'=>'þ','ß'=>'ss','à '=>'à ','á'=>'á','â'=>'â','ã'=>'ã','ä'=>'ae','Ã¥'=>'Ã¥','æ'=>'ae','ç'=>'ç','è'=>'è','é'=>'é','ê'=>'ê','ë'=>'ë','ì'=>'ì','Ã'=>'Ã','î'=>'î','ï'=>'ï','ð'=>'ð','ñ'=>'ñ','ò'=>'ò','ó'=>'ó','ô'=>'ô','õ'=>'õ','ö'=>'oe','ø'=>'ø','ù'=>'ù','ú'=>'ú','û'=>'û','ü'=>'ue','ý'=>'ý','þ'=>'þ','ÿ'=>'ÿ','Ä€'=>'Ä','Ä'=>'Ä','Ä‚'=>'ă','ă'=>'ă','Ä„'=>'Ä…','Ä…'=>'Ä…','Ć'=>'ć','ć'=>'ć','Ĉ'=>'ĉ','ĉ'=>'ĉ','ÄŠ'=>'Ä‹','Ä‹'=>'Ä‹','ÄŒ'=>'Ä','Ä'=>'Ä','ÄŽ'=>'Ä','Ä'=>'Ä','Ä'=>'Ä‘','Ä‘'=>'Ä‘','Ä’'=>'Ä“','Ä“'=>'Ä“','Ä”'=>'Ä•','Ä•'=>'Ä•','Ä–'=>'Ä—','Ä—'=>'Ä—','Ę'=>'Ä™','Ä™'=>'Ä™','Äš'=>'Ä›','Ä›'=>'Ä›','Äœ'=>'Ä','Ä'=>'Ä','Äž'=>'ÄŸ','ÄŸ'=>'ÄŸ','Ä '=>'Ä¡','Ä¡'=>'Ä¡','Ä¢'=>'Ä£','Ä£'=>'Ä£','Ĥ'=>'Ä¥','Ä¥'=>'Ä¥','Ħ'=>'ħ','ħ'=>'ħ','Ĩ'=>'Ä©','Ä©'=>'Ä©','Ī'=>'Ä«','Ä«'=>'Ä«','Ĭ'=>'Ä','Ä'=>'Ä','Ä®'=>'į','į'=>'į','İ'=>'i','ı'=>'ı','IJ'=>'ij','ij'=>'ij','Ä´'=>'ĵ','ĵ'=>'ĵ','Ķ'=>'Ä·','Ä·'=>'Ä·','ĸ'=>'ĸ','Ĺ'=>'ĺ','ĺ'=>'ĺ','Ä»'=>'ļ','ļ'=>'ļ','Ľ'=>'ľ','ľ'=>'ľ','Ä¿'=>'Å€','Å€'=>'Å€','Å'=>'Å‚','Å‚'=>'Å‚','Ń'=>'Å„','Å„'=>'Å„','Å…'=>'ņ','ņ'=>'ņ','Ň'=>'ň','ň'=>'ň','ʼn'=>'ʼn','ÅŠ'=>'Å‹','Å‹'=>'Å‹','ÅŒ'=>'Å','Å'=>'Å','ÅŽ'=>'Å','Å'=>'Å','Å'=>'Å‘','Å‘'=>'Å‘','Å’'=>'oe','Å“'=>'oe','Å”'=>'Å•','Å•'=>'Å•','Å–'=>'Å—','Å—'=>'Å—','Ř'=>'Å™','Å™'=>'Å™','Åš'=>'Å›','Å›'=>'Å›','Åœ'=>'Å','Å'=>'Å','Åž'=>'ÅŸ','ÅŸ'=>'ÅŸ','Å '=>'Å¡','Å¡'=>'Å¡','Å¢'=>'Å£','Å£'=>'Å£','Ť'=>'Å¥','Å¥'=>'Å¥','Ŧ'=>'ŧ','ŧ'=>'ŧ','Ũ'=>'Å©','Å©'=>'Å©','Ū'=>'Å«','Å«'=>'Å«','Ŭ'=>'Å','Å'=>'Å','Å®'=>'ů','ů'=>'ů','Ű'=>'ű','ű'=>'ű','Ų'=>'ų','ų'=>'ų','Å´'=>'ŵ','ŵ'=>'ŵ','Ŷ'=>'Å·','Å·'=>'Å·','Ÿ'=>'ÿ','Ź'=>'ź','ź'=>'ź','Å»'=>'ż','ż'=>'ż','Ž'=>'ž','ž'=>'ž','Å¿'=>'Å¿','Æ€'=>'Æ€','Æ'=>'É“','Æ‚'=>'ƃ','ƃ'=>'ƃ','Æ„'=>'Æ…','Æ…'=>'Æ…','Ɔ'=>'É”','Ƈ'=>'ƈ','ƈ'=>'ƈ','Ɖ'=>'É–','ÆŠ'=>'É—','Æ‹'=>'ÆŒ','ÆŒ'=>'ÆŒ','Æ'=>'Æ','ÆŽ'=>'Ç','Æ'=>'É™','Æ'=>'É›','Æ‘'=>'Æ’','Æ’'=>'Æ’','Æ“'=>'É ','Æ”'=>'É£','Æ•'=>'hv','Æ–'=>'É©','Æ—'=>'ɨ','Ƙ'=>'Æ™','Æ™'=>'Æ™','Æš'=>'Æš','Æ›'=>'Æ›','Æœ'=>'ɯ','Æ'=>'ɲ','Æž'=>'Æž','ÆŸ'=>'ɵ','Æ '=>'Æ¡','Æ¡'=>'Æ¡','Æ¢'=>'oi','Æ£'=>'oi','Ƥ'=>'Æ¥','Æ¥'=>'Æ¥','Ʀ'=>'yr','Ƨ'=>'ƨ','ƨ'=>'ƨ','Æ©'=>'ʃ','ƪ'=>'ƪ','Æ«'=>'Æ«','Ƭ'=>'Æ','Æ'=>'Æ','Æ®'=>'ʈ','Ư'=>'ư','ư'=>'ư','Ʊ'=>'ÊŠ','Ʋ'=>'Ê‹','Ƴ'=>'Æ´','Æ´'=>'Æ´','Ƶ'=>'ƶ','ƶ'=>'ƶ','Æ·'=>'Ê’','Ƹ'=>'ƹ','ƹ'=>'ƹ','ƺ'=>'ƺ','Æ»'=>'Æ»','Ƽ'=>'ƽ','ƽ'=>'ƽ','ƾ'=>'ƾ','Æ¿'=>'Æ¿','Ç€'=>'Ç€','Ç'=>'Ç','Ç‚'=>'Ç‚','ǃ'=>'ǃ','Ç„'=>'dž','Ç…'=>'dž','dž'=>'dž','LJ'=>'lj','Lj'=>'lj','lj'=>'lj','ÇŠ'=>'nj','Ç‹'=>'ÇŒ','ÇŒ'=>'nj','Ç'=>'ÇŽ','ÇŽ'=>'ÇŽ','Ç'=>'Ç','Ç'=>'Ç','Ç‘'=>'Ç’','Ç’'=>'Ç’','Ç“'=>'Ç”','Ç”'=>'Ç”','Ç•'=>'Ç–','Ç–'=>'Ç–','Ç—'=>'ǘ','ǘ'=>'ǘ','Ç™'=>'Çš','Çš'=>'Çš','Ç›'=>'Çœ','Çœ'=>'Çœ','Ç'=>'Ç','Çž'=>'ÇŸ','ÇŸ'=>'ÇŸ','Ç '=>'Ç¡','Ç¡'=>'Ç¡','Ç¢'=>'Ç£','Ç£'=>'Ç£','Ǥ'=>'Ç¥','Ç¥'=>'Ç¥','Ǧ'=>'ǧ','ǧ'=>'ǧ','Ǩ'=>'Ç©','Ç©'=>'Ç©','Ǫ'=>'Ç«','Ç«'=>'Ç«','Ǭ'=>'Ç','Ç'=>'Ç','Ç®'=>'ǯ','ǯ'=>'ǯ','ǰ'=>'ǰ','DZ'=>'dz','Dz'=>'dz','dz'=>'dz','Ç´'=>'ǵ','ǵ'=>'ǵ','Ƕ'=>'Æ•','Ç·'=>'Æ¿','Ǹ'=>'ǹ','ǹ'=>'ǹ','Ǻ'=>'Ç»','Ç»'=>'Ç»','Ǽ'=>'ǽ','ǽ'=>'ǽ','Ǿ'=>'Ç¿','Ç¿'=>'Ç¿','È€'=>'È','È'=>'È','È‚'=>'ȃ','ȃ'=>'ȃ','È„'=>'È…','È…'=>'È…','Ȇ'=>'ȇ','ȇ'=>'ȇ','Ȉ'=>'ȉ','ȉ'=>'ȉ','ÈŠ'=>'È‹','È‹'=>'È‹','ÈŒ'=>'È','È'=>'È','ÈŽ'=>'È','È'=>'È','È'=>'È‘','È‘'=>'È‘','È’'=>'È“','È“'=>'È“','È”'=>'È•','È•'=>'È•','È–'=>'È—','È—'=>'È—','Ș'=>'È™','È™'=>'È™','Èš'=>'È›','È›'=>'È›','Èœ'=>'È','È'=>'È','Èž'=>'ÈŸ','ÈŸ'=>'ÈŸ','È '=>'Æž','È¡'=>'È¡','È¢'=>'ou','È£'=>'ou','Ȥ'=>'È¥','È¥'=>'È¥','Ȧ'=>'ȧ','ȧ'=>'ȧ','Ȩ'=>'È©','È©'=>'È©','Ȫ'=>'È«','È«'=>'È«','Ȭ'=>'È','È'=>'È','È®'=>'ȯ','ȯ'=>'ȯ','Ȱ'=>'ȱ','ȱ'=>'ȱ','Ȳ'=>'ȳ','ȳ'=>'ȳ','È´'=>'È´','ȵ'=>'ȵ','ȶ'=>'ȶ','È·'=>'È·','ȸ'=>'ȸ','ȹ'=>'ȹ','Ⱥ'=>'â±¥','È»'=>'ȼ','ȼ'=>'ȼ','Ƚ'=>'Æš','Ⱦ'=>'ⱦ','È¿'=>'È¿','É€'=>'É€','É'=>'É‚','É‚'=>'É‚','Ƀ'=>'Æ€','É„'=>'ʉ','É…'=>'ÊŒ','Ɇ'=>'ɇ','ɇ'=>'ɇ','Ɉ'=>'ɉ','ɉ'=>'ɉ','ÉŠ'=>'É‹','É‹'=>'É‹','ÉŒ'=>'É','É'=>'É','ÉŽ'=>'É','É'=>'É','É'=>'É','É‘'=>'É‘','É’'=>'É’','É“'=>'É“','É”'=>'É”','É•'=>'É•','É–'=>'É–','É—'=>'É—','ɘ'=>'ɘ','É™'=>'É™','Éš'=>'Éš','É›'=>'É›','Éœ'=>'Éœ','É'=>'É','Éž'=>'Éž','ÉŸ'=>'ÉŸ','É '=>'É ','É¡'=>'É¡','É¢'=>'É¢','É£'=>'É£','ɤ'=>'ɤ','É¥'=>'É¥','ɦ'=>'ɦ','ɧ'=>'ɧ','ɨ'=>'ɨ','É©'=>'É©','ɪ'=>'ɪ','É«'=>'É«','ɬ'=>'ɬ','É'=>'É','É®'=>'É®','ɯ'=>'ɯ','ɰ'=>'ɰ','ɱ'=>'ɱ','ɲ'=>'ɲ','ɳ'=>'ɳ','É´'=>'É´','ɵ'=>'ɵ','ɶ'=>'ɶ','É·'=>'É·','ɸ'=>'ɸ','ɹ'=>'ɹ','ɺ'=>'ɺ','É»'=>'É»','ɼ'=>'ɼ','ɽ'=>'ɽ','ɾ'=>'ɾ','É¿'=>'É¿','Ê€'=>'Ê€','Ê'=>'Ê','Ê‚'=>'Ê‚','ʃ'=>'ʃ','Ê„'=>'Ê„','Ê…'=>'Ê…','ʆ'=>'ʆ','ʇ'=>'ʇ','ʈ'=>'ʈ','ʉ'=>'ʉ','ÊŠ'=>'ÊŠ','Ê‹'=>'Ê‹','ÊŒ'=>'ÊŒ','Ê'=>'Ê','ÊŽ'=>'ÊŽ','Ê'=>'Ê','Ê'=>'Ê','Ê‘'=>'Ê‘','Ê’'=>'Ê’','Ê“'=>'Ê“','Ê”'=>'Ê”','Ê•'=>'Ê•','Ê–'=>'Ê–','Ê—'=>'Ê—','ʘ'=>'ʘ','Ê™'=>'Ê™','Êš'=>'Êš','Ê›'=>'Ê›','Êœ'=>'Êœ','Ê'=>'Ê','Êž'=>'Êž','ÊŸ'=>'ÊŸ','Ê '=>'Ê ','Ê¡'=>'Ê¡','Ê¢'=>'Ê¢','Ê£'=>'Ê£','ʤ'=>'ʤ','Ê¥'=>'Ê¥','ʦ'=>'ʦ','ʧ'=>'ʧ','ʨ'=>'ʨ','Ê©'=>'Ê©','ʪ'=>'ʪ','Ê«'=>'Ê«','ʬ'=>'ʬ','Ê'=>'Ê','Ê®'=>'Ê®','ʯ'=>'ʯ','ʰ'=>'ʰ','ʱ'=>'ʱ','ʲ'=>'ʲ','ʳ'=>'ʳ','Ê´'=>'Ê´','ʵ'=>'ʵ','ʶ'=>'ʶ','Ê·'=>'Ê·','ʸ'=>'ʸ','ʹ'=>'ʹ','ʺ'=>'ʺ','Ê»'=>'Ê»','ʼ'=>'ʼ','ʽ'=>'ʽ','ʾ'=>'ʾ','Ê¿'=>'Ê¿','Ë€'=>'Ë€','Ë'=>'Ë','ˆ'=>'ˆ','ˇ'=>'ˇ','ˈ'=>'ˈ','ˉ'=>'ˉ','ËŠ'=>'ËŠ','Ë‹'=>'Ë‹','ËŒ'=>'ËŒ','Ë'=>'Ë','ËŽ'=>'ËŽ','Ë'=>'Ë','Ë'=>'Ë','Ë‘'=>'Ë‘','Ë '=>'Ë ','Ë¡'=>'Ë¡','Ë¢'=>'Ë¢','Ë£'=>'Ë£','ˤ'=>'ˤ','Ë®'=>'Ë®','Ì€'=>'Ì€','Ì'=>'Ì','Ì‚'=>'Ì‚','̃'=>'̃','Ì„'=>'Ì„','Ì…'=>'Ì…','̆'=>'̆','̇'=>'̇','̈'=>'̈','̉'=>'̉','ÌŠ'=>'ÌŠ','Ì‹'=>'Ì‹','ÌŒ'=>'ÌŒ','Ì'=>'Ì','ÌŽ'=>'ÌŽ','Ì'=>'Ì','Ì'=>'Ì','Ì‘'=>'Ì‘','Ì’'=>'Ì’','Ì“'=>'Ì“','Ì”'=>'Ì”','Ì•'=>'Ì•','Ì–'=>'Ì–','Ì—'=>'Ì—','̘'=>'̘','Ì™'=>'Ì™','Ìš'=>'Ìš','Ì›'=>'Ì›','Ìœ'=>'Ìœ','Ì'=>'Ì','Ìž'=>'Ìž','ÌŸ'=>'ÌŸ','Ì '=>'Ì ','Ì¡'=>'Ì¡','Ì¢'=>'Ì¢','Ì£'=>'Ì£','̤'=>'̤','Ì¥'=>'Ì¥','̦'=>'̦','̧'=>'̧','̨'=>'̨','Ì©'=>'Ì©','̪'=>'̪','Ì«'=>'Ì«','̬'=>'̬','Ì'=>'Ì','Ì®'=>'Ì®','̯'=>'̯','̰'=>'̰','̱'=>'̱','̲'=>'̲','̳'=>'̳','Ì´'=>'Ì´','̵'=>'̵','̶'=>'̶','Ì·'=>'Ì·','̸'=>'̸','̹'=>'̹','̺'=>'̺','Ì»'=>'Ì»','̼'=>'̼','̽'=>'̽','̾'=>'̾','Ì¿'=>'Ì¿','Í€'=>'Í€','Í'=>'Í','Í‚'=>'Í‚','̓'=>'̓','Í„'=>'Í„','Í…'=>'Í…','͆'=>'͆','͇'=>'͇','͈'=>'͈','͉'=>'͉','ÍŠ'=>'ÍŠ','Í‹'=>'Í‹','ÍŒ'=>'ÍŒ','Í'=>'Í','ÍŽ'=>'ÍŽ','Í'=>'Í','Í'=>'Í','Í‘'=>'Í‘','Í’'=>'Í’','Í“'=>'Í“','Í”'=>'Í”','Í•'=>'Í•','Í–'=>'Í–','Í—'=>'Í—','͘'=>'͘','Í™'=>'Í™','Íš'=>'Íš','Í›'=>'Í›','Íœ'=>'Íœ','Í'=>'Í','Íž'=>'Íž','ÍŸ'=>'ÍŸ','Í '=>'Í ','Í¡'=>'Í¡','Í¢'=>'Í¢','Í£'=>'Í£','ͤ'=>'ͤ','Í¥'=>'Í¥','ͦ'=>'ͦ','ͧ'=>'ͧ','ͨ'=>'ͨ','Í©'=>'Í©','ͪ'=>'ͪ','Í«'=>'Í«','ͬ'=>'ͬ','Í'=>'Í','Í®'=>'Í®','ͯ'=>'ͯ','ͺ'=>'ͺ','Í»'=>'Í»','ͼ'=>'ͼ','ͽ'=>'ͽ','Ά'=>'ά','Έ'=>'Î','Ή'=>'ή','Ί'=>'ί','ÎŒ'=>'ÏŒ','ÎŽ'=>'Ï','Î'=>'ÏŽ','Î'=>'Î','Α'=>'α','Î’'=>'β','Γ'=>'γ','Δ'=>'δ','Ε'=>'ε','Ζ'=>'ζ','Η'=>'η','Θ'=>'θ','Ι'=>'ι','Κ'=>'κ','Λ'=>'λ','Μ'=>'μ','Î'=>'ν','Ξ'=>'ξ','Ο'=>'ο','Î '=>'Ï€','Ρ'=>'Ï','Σ'=>'σ','Τ'=>'Ï„','Î¥'=>'Ï…','Φ'=>'φ','Χ'=>'χ','Ψ'=>'ψ','Ω'=>'ω','Ϊ'=>'ÏŠ','Ϋ'=>'Ï‹','ά'=>'ά','Î'=>'Î','ή'=>'ή','ί'=>'ί','ΰ'=>'ΰ','α'=>'α','β'=>'β','γ'=>'γ','δ'=>'δ','ε'=>'ε','ζ'=>'ζ','η'=>'η','θ'=>'θ','ι'=>'ι','κ'=>'κ','λ'=>'λ','μ'=>'μ','ν'=>'ν','ξ'=>'ξ','ο'=>'ο','Ï€'=>'Ï€','Ï'=>'Ï','Ï‚'=>'Ï‚','σ'=>'σ','Ï„'=>'Ï„','Ï…'=>'Ï…','φ'=>'φ','χ'=>'χ','ψ'=>'ψ','ω'=>'ω','ÏŠ'=>'ÏŠ','Ï‹'=>'Ï‹','ÏŒ'=>'ÏŒ','Ï'=>'Ï','ÏŽ'=>'ÏŽ','Ï'=>'Ï','Ï‘'=>'Ï‘','Ï’'=>'Ï’','Ï“'=>'Ï“','Ï”'=>'Ï”','Ï•'=>'Ï•','Ï–'=>'Ï–','Ï—'=>'Ï—','Ϙ'=>'Ï™','Ï™'=>'Ï™','Ïš'=>'Ï›','Ï›'=>'Ï›','Ïœ'=>'Ï','Ï'=>'Ï','Ïž'=>'ÏŸ','ÏŸ'=>'ÏŸ','Ï '=>'Ï¡','Ï¡'=>'Ï¡','Ï¢'=>'Ï£','Ï£'=>'Ï£','Ϥ'=>'Ï¥','Ï¥'=>'Ï¥','Ϧ'=>'ϧ','ϧ'=>'ϧ','Ϩ'=>'Ï©','Ï©'=>'Ï©','Ϫ'=>'Ï«','Ï«'=>'Ï«','Ϭ'=>'Ï','Ï'=>'Ï','Ï®'=>'ϯ','ϯ'=>'ϯ','ϰ'=>'ϰ','ϱ'=>'ϱ','ϲ'=>'ϲ','ϳ'=>'ϳ','Ï´'=>'θ','ϵ'=>'ϵ','Ï·'=>'ϸ','ϸ'=>'ϸ','Ϲ'=>'ϲ','Ϻ'=>'Ï»','Ï»'=>'Ï»','ϼ'=>'ϼ','Ͻ'=>'Í»','Ͼ'=>'ͼ','Ï¿'=>'ͽ','Ѐ'=>'Ñ','Ð'=>'Ñ‘','Ђ'=>'Ñ’','Ѓ'=>'Ñ“','Є'=>'Ñ”','Ð…'=>'Ñ•','І'=>'Ñ–','Ї'=>'Ñ—','Ј'=>'ј','Љ'=>'Ñ™','Њ'=>'Ñš','Ћ'=>'Ñ›','ÐŒ'=>'Ñœ','Ð'=>'Ñ','ÐŽ'=>'Ñž','Ð'=>'ÑŸ','Ð'=>'а','Б'=>'б','Ð’'=>'в','Г'=>'г','Д'=>'д','Е'=>'е','Ж'=>'ж','З'=>'з','И'=>'и','Й'=>'й','К'=>'к','Л'=>'л','М'=>'м','Ð'=>'н','О'=>'о','П'=>'п','Ð '=>'Ñ€','С'=>'Ñ','Т'=>'Ñ‚','У'=>'у','Ф'=>'Ñ„','Ð¥'=>'Ñ…','Ц'=>'ц','Ч'=>'ч','Ш'=>'ш','Щ'=>'щ','Ъ'=>'ÑŠ','Ы'=>'Ñ‹','Ь'=>'ÑŒ','Ð'=>'Ñ','Ю'=>'ÑŽ','Я'=>'Ñ','а'=>'а','б'=>'б','в'=>'в','г'=>'г','д'=>'д','е'=>'е','ж'=>'ж','з'=>'з','и'=>'и','й'=>'й','к'=>'к','л'=>'л','м'=>'м','н'=>'н','о'=>'о','п'=>'п','Ñ€'=>'Ñ€','Ñ'=>'Ñ','Ñ‚'=>'Ñ‚','у'=>'у','Ñ„'=>'Ñ„','Ñ…'=>'Ñ…','ц'=>'ц','ч'=>'ч','ш'=>'ш','щ'=>'щ','ÑŠ'=>'ÑŠ','Ñ‹'=>'Ñ‹','ÑŒ'=>'ÑŒ','Ñ'=>'Ñ','ÑŽ'=>'ÑŽ','Ñ'=>'Ñ','Ñ'=>'Ñ','Ñ‘'=>'Ñ‘','Ñ’'=>'Ñ’','Ñ“'=>'Ñ“','Ñ”'=>'Ñ”','Ñ•'=>'Ñ•','Ñ–'=>'Ñ–','Ñ—'=>'Ñ—','ј'=>'ј','Ñ™'=>'Ñ™','Ñš'=>'Ñš','Ñ›'=>'Ñ›','Ñœ'=>'Ñœ','Ñ'=>'Ñ','Ñž'=>'Ñž','ÑŸ'=>'ÑŸ','Ñ '=>'Ñ¡','Ñ¡'=>'Ñ¡','Ñ¢'=>'Ñ£','Ñ£'=>'Ñ£','Ѥ'=>'Ñ¥','Ñ¥'=>'Ñ¥','Ѧ'=>'ѧ','ѧ'=>'ѧ','Ѩ'=>'Ñ©','Ñ©'=>'Ñ©','Ѫ'=>'Ñ«','Ñ«'=>'Ñ«','Ѭ'=>'Ñ','Ñ'=>'Ñ','Ñ®'=>'ѯ','ѯ'=>'ѯ','Ѱ'=>'ѱ','ѱ'=>'ѱ','Ѳ'=>'ѳ','ѳ'=>'ѳ','Ñ´'=>'ѵ','ѵ'=>'ѵ','Ѷ'=>'Ñ·','Ñ·'=>'Ñ·','Ѹ'=>'ѹ','ѹ'=>'ѹ','Ѻ'=>'Ñ»','Ñ»'=>'Ñ»','Ѽ'=>'ѽ','ѽ'=>'ѽ','Ѿ'=>'Ñ¿','Ñ¿'=>'Ñ¿','Ò€'=>'Ò','Ò'=>'Ò','Òƒ'=>'Òƒ','Ò„'=>'Ò„','Ò…'=>'Ò…','Ò†'=>'Ò†','Òˆ'=>'Òˆ','Ò‰'=>'Ò‰','ÒŠ'=>'Ò‹','Ò‹'=>'Ò‹','ÒŒ'=>'Ò','Ò'=>'Ò','ÒŽ'=>'Ò','Ò'=>'Ò','Ò'=>'Ò‘','Ò‘'=>'Ò‘','Ò’'=>'Ò“','Ò“'=>'Ò“','Ò”'=>'Ò•','Ò•'=>'Ò•','Ò–'=>'Ò—','Ò—'=>'Ò—','Ò˜'=>'Ò™','Ò™'=>'Ò™','Òš'=>'Ò›','Ò›'=>'Ò›','Òœ'=>'Ò','Ò'=>'Ò','Òž'=>'ÒŸ','ÒŸ'=>'ÒŸ','Ò '=>'Ò¡','Ò¡'=>'Ò¡','Ò¢'=>'Ò£','Ò£'=>'Ò£','Ò¤'=>'Ò¥','Ò¥'=>'Ò¥','Ò¦'=>'Ò§','Ò§'=>'Ò§','Ò¨'=>'Ò©','Ò©'=>'Ò©','Òª'=>'Ò«','Ò«'=>'Ò«','Ò¬'=>'Ò','Ò'=>'Ò','Ò®'=>'Ò¯','Ò¯'=>'Ò¯','Ò°'=>'Ò±','Ò±'=>'Ò±','Ò²'=>'Ò³','Ò³'=>'Ò³','Ò´'=>'Òµ','Òµ'=>'Òµ','Ò¶'=>'Ò·','Ò·'=>'Ò·','Ò¸'=>'Ò¹','Ò¹'=>'Ò¹','Òº'=>'Ò»','Ò»'=>'Ò»','Ò¼'=>'Ò½','Ò½'=>'Ò½','Ò¾'=>'Ò¿','Ò¿'=>'Ò¿','Ó€'=>'Ó','Ó'=>'Ó‚','Ó‚'=>'Ó‚','Óƒ'=>'Ó„','Ó„'=>'Ó„','Ó…'=>'Ó†','Ó†'=>'Ó†','Ó‡'=>'Óˆ','Óˆ'=>'Óˆ','Ó‰'=>'ÓŠ','ÓŠ'=>'ÓŠ','Ó‹'=>'ÓŒ','ÓŒ'=>'ÓŒ','Ó'=>'ÓŽ','ÓŽ'=>'ÓŽ','Ó'=>'Ó','Ó'=>'Ó‘','Ó‘'=>'Ó‘','Ó’'=>'Ó“','Ó“'=>'Ó“','Ó”'=>'Ó•','Ó•'=>'Ó•','Ó–'=>'Ó—','Ó—'=>'Ó—','Ó˜'=>'Ó™','Ó™'=>'Ó™','Óš'=>'Ó›','Ó›'=>'Ó›','Óœ'=>'Ó','Ó'=>'Ó','Óž'=>'ÓŸ','ÓŸ'=>'ÓŸ','Ó '=>'Ó¡','Ó¡'=>'Ó¡','Ó¢'=>'Ó£','Ó£'=>'Ó£','Ó¤'=>'Ó¥','Ó¥'=>'Ó¥','Ó¦'=>'Ó§','Ó§'=>'Ó§','Ó¨'=>'Ó©','Ó©'=>'Ó©','Óª'=>'Ó«','Ó«'=>'Ó«','Ó¬'=>'Ó','Ó'=>'Ó','Ó®'=>'Ó¯','Ó¯'=>'Ó¯','Ó°'=>'Ó±','Ó±'=>'Ó±','Ó²'=>'Ó³','Ó³'=>'Ó³','Ó´'=>'Óµ','Óµ'=>'Óµ','Ó¶'=>'Ó·','Ó·'=>'Ó·','Ó¸'=>'Ó¹','Ó¹'=>'Ó¹','Óº'=>'Ó»','Ó»'=>'Ó»','Ó¼'=>'Ó½','Ó½'=>'Ó½','Ó¾'=>'Ó¿','Ó¿'=>'Ó¿','Ô€'=>'Ô','Ô'=>'Ô','Ô‚'=>'Ôƒ','Ôƒ'=>'Ôƒ','Ô„'=>'Ô…','Ô…'=>'Ô…','Ô†'=>'Ô‡','Ô‡'=>'Ô‡','Ôˆ'=>'Ô‰','Ô‰'=>'Ô‰','ÔŠ'=>'Ô‹','Ô‹'=>'Ô‹','ÔŒ'=>'Ô','Ô'=>'Ô','ÔŽ'=>'Ô','Ô'=>'Ô','Ô'=>'Ô‘','Ô‘'=>'Ô‘','Ô’'=>'Ô“','Ô“'=>'Ô“','Ô±'=>'Õ¡','Ô²'=>'Õ¢','Ô³'=>'Õ£','Ô´'=>'Õ¤','Ôµ'=>'Õ¥','Ô¶'=>'Õ¦','Ô·'=>'Õ§','Ô¸'=>'Õ¨','Ô¹'=>'Õ©','Ôº'=>'Õª','Ô»'=>'Õ«','Ô¼'=>'Õ¬','Ô½'=>'Õ','Ô¾'=>'Õ®','Ô¿'=>'Õ¯','Õ€'=>'Õ°','Õ'=>'Õ±','Õ‚'=>'Õ²','Õƒ'=>'Õ³','Õ„'=>'Õ´','Õ…'=>'Õµ','Õ†'=>'Õ¶','Õ‡'=>'Õ·','Õˆ'=>'Õ¸','Õ‰'=>'Õ¹','ÕŠ'=>'Õº','Õ‹'=>'Õ»','ÕŒ'=>'Õ¼','Õ'=>'Õ½','ÕŽ'=>'Õ¾','Õ'=>'Õ¿','Õ'=>'Ö€','Õ‘'=>'Ö','Õ’'=>'Ö‚','Õ“'=>'Öƒ','Õ”'=>'Ö„','Õ•'=>'Ö…','Õ–'=>'Ö†','Õ™'=>'Õ™','Õ¡'=>'Õ¡','Õ¢'=>'Õ¢','Õ£'=>'Õ£','Õ¤'=>'Õ¤','Õ¥'=>'Õ¥','Õ¦'=>'Õ¦','Õ§'=>'Õ§','Õ¨'=>'Õ¨','Õ©'=>'Õ©','Õª'=>'Õª','Õ«'=>'Õ«','Õ¬'=>'Õ¬','Õ'=>'Õ','Õ®'=>'Õ®','Õ¯'=>'Õ¯','Õ°'=>'Õ°','Õ±'=>'Õ±','Õ²'=>'Õ²','Õ³'=>'Õ³','Õ´'=>'Õ´','Õµ'=>'Õµ','Õ¶'=>'Õ¶','Õ·'=>'Õ·','Õ¸'=>'Õ¸','Õ¹'=>'Õ¹','Õº'=>'Õº','Õ»'=>'Õ»','Õ¼'=>'Õ¼','Õ½'=>'Õ½','Õ¾'=>'Õ¾','Õ¿'=>'Õ¿','Ö€'=>'Ö€','Ö'=>'Ö','Ö‚'=>'Ö‚','Öƒ'=>'Öƒ','Ö„'=>'Ö„','Ö…'=>'Ö…','Ö†'=>'Ö†','Ö‡'=>'Ö‡','Ö‘'=>'Ö‘','Ö’'=>'Ö’','Ö“'=>'Ö“','Ö”'=>'Ö”','Ö•'=>'Ö•','Ö–'=>'Ö–','Ö—'=>'Ö—','Ö˜'=>'Ö˜','Ö™'=>'Ö™','Öš'=>'Öš','Ö›'=>'Ö›','Öœ'=>'Öœ','Ö'=>'Ö','Öž'=>'Öž','ÖŸ'=>'ÖŸ','Ö '=>'Ö ','Ö¡'=>'Ö¡','Ö¢'=>'Ö¢','Ö£'=>'Ö£','Ö¤'=>'Ö¤','Ö¥'=>'Ö¥','Ö¦'=>'Ö¦','Ö§'=>'Ö§','Ö¨'=>'Ö¨','Ö©'=>'Ö©','Öª'=>'Öª','Ö«'=>'Ö«','Ö¬'=>'Ö¬','Ö'=>'Ö','Ö®'=>'Ö®','Ö¯'=>'Ö¯','Ö°'=>'Ö°','Ö±'=>'Ö±','Ö²'=>'Ö²','Ö³'=>'Ö³','Ö´'=>'Ö´','Öµ'=>'Öµ','Ö¶'=>'Ö¶','Ö·'=>'Ö·','Ö¸'=>'Ö¸','Ö¹'=>'Ö¹','Öº'=>'Öº','Ö»'=>'Ö»','Ö¼'=>'Ö¼','Ö½'=>'Ö½','Ö¿'=>'Ö¿','×'=>'×','ׂ'=>'ׂ','ׄ'=>'ׄ','×…'=>'×…','ׇ'=>'ׇ','×'=>'×','ב'=>'ב','×’'=>'×’','ד'=>'ד','×”'=>'×”','ו'=>'ו','×–'=>'×–','×—'=>'×—','ט'=>'ט','×™'=>'×™','ך'=>'ך','×›'=>'×›','ל'=>'ל','×'=>'×','מ'=>'מ','ן'=>'ן','× '=>'× ','ס'=>'ס','×¢'=>'×¢','×£'=>'×£','פ'=>'פ','×¥'=>'×¥','צ'=>'צ','×§'=>'×§','ר'=>'ר','ש'=>'ש','ת'=>'ת','×°'=>'×°','×±'=>'×±','ײ'=>'ײ','Ø'=>'Ø','Ø‘'=>'Ø‘','Ø’'=>'Ø’','Ø“'=>'Ø“','Ø”'=>'Ø”','Ø•'=>'Ø•','Ø¡'=>'Ø¡','Ø¢'=>'Ø¢','Ø£'=>'Ø£','ؤ'=>'ؤ','Ø¥'=>'Ø¥','ئ'=>'ئ','ا'=>'ا','ب'=>'ب','Ø©'=>'Ø©','ت'=>'ت','Ø«'=>'Ø«','ج'=>'ج','Ø'=>'Ø','Ø®'=>'Ø®','د'=>'د','ذ'=>'ذ','ر'=>'ر','ز'=>'ز','س'=>'س','Ø´'=>'Ø´','ص'=>'ص','ض'=>'ض','Ø·'=>'Ø·','ظ'=>'ظ','ع'=>'ع','غ'=>'غ','Ù€'=>'Ù€','Ù'=>'Ù','Ù‚'=>'Ù‚','Ùƒ'=>'Ùƒ','Ù„'=>'Ù„','Ù…'=>'Ù…','Ù†'=>'Ù†','Ù‡'=>'Ù‡','Ùˆ'=>'Ùˆ','Ù‰'=>'Ù‰','ÙŠ'=>'ÙŠ','Ù‹'=>'Ù‹','ÙŒ'=>'ÙŒ','Ù'=>'Ù','ÙŽ'=>'ÙŽ','Ù'=>'Ù','Ù'=>'Ù','Ù‘'=>'Ù‘','Ù’'=>'Ù’','Ù“'=>'Ù“','Ù”'=>'Ù”','Ù•'=>'Ù•','Ù–'=>'Ù–','Ù—'=>'Ù—','Ù˜'=>'Ù˜','Ù™'=>'Ù™','Ùš'=>'Ùš','Ù›'=>'Ù›','Ùœ'=>'Ùœ','Ù'=>'Ù','Ùž'=>'Ùž','Ù '=>'0','Ù¡'=>'1','Ù¢'=>'2','Ù£'=>'3','Ù¤'=>'4','Ù¥'=>'5','Ù¦'=>'6','Ù§'=>'7','Ù¨'=>'8','Ù©'=>'9','Ù®'=>'Ù®','Ù¯'=>'Ù¯','Ù°'=>'Ù°','Ù±'=>'Ù±','Ù²'=>'Ù²','Ù³'=>'Ù³','Ù´'=>'Ù´','Ùµ'=>'Ùµ','Ù¶'=>'Ù¶','Ù·'=>'Ù·','Ù¸'=>'Ù¸','Ù¹'=>'Ù¹','Ùº'=>'Ùº','Ù»'=>'Ù»','Ù¼'=>'Ù¼','Ù½'=>'Ù½','Ù¾'=>'Ù¾','Ù¿'=>'Ù¿','Ú€'=>'Ú€','Ú'=>'Ú','Ú‚'=>'Ú‚','Úƒ'=>'Úƒ','Ú„'=>'Ú„','Ú…'=>'Ú…','Ú†'=>'Ú†','Ú‡'=>'Ú‡','Úˆ'=>'Úˆ','Ú‰'=>'Ú‰','ÚŠ'=>'ÚŠ','Ú‹'=>'Ú‹','ÚŒ'=>'ÚŒ','Ú'=>'Ú','ÚŽ'=>'ÚŽ','Ú'=>'Ú','Ú'=>'Ú','Ú‘'=>'Ú‘','Ú’'=>'Ú’','Ú“'=>'Ú“','Ú”'=>'Ú”','Ú•'=>'Ú•','Ú–'=>'Ú–','Ú—'=>'Ú—','Ú˜'=>'Ú˜','Ú™'=>'Ú™','Úš'=>'Úš','Ú›'=>'Ú›','Úœ'=>'Úœ','Ú'=>'Ú','Úž'=>'Úž','ÚŸ'=>'ÚŸ','Ú '=>'Ú ','Ú¡'=>'Ú¡','Ú¢'=>'Ú¢','Ú£'=>'Ú£','Ú¤'=>'Ú¤','Ú¥'=>'Ú¥','Ú¦'=>'Ú¦','Ú§'=>'Ú§','Ú¨'=>'Ú¨','Ú©'=>'Ú©','Úª'=>'Úª','Ú«'=>'Ú«','Ú¬'=>'Ú¬','Ú'=>'Ú','Ú®'=>'Ú®','Ú¯'=>'Ú¯','Ú°'=>'Ú°','Ú±'=>'Ú±','Ú²'=>'Ú²','Ú³'=>'Ú³','Ú´'=>'Ú´','Úµ'=>'Úµ','Ú¶'=>'Ú¶','Ú·'=>'Ú·','Ú¸'=>'Ú¸','Ú¹'=>'Ú¹','Úº'=>'Úº','Ú»'=>'Ú»','Ú¼'=>'Ú¼','Ú½'=>'Ú½','Ú¾'=>'Ú¾','Ú¿'=>'Ú¿','Û€'=>'Û€','Û'=>'Û','Û‚'=>'Û‚','Ûƒ'=>'Ûƒ','Û„'=>'Û„','Û…'=>'Û…','Û†'=>'Û†','Û‡'=>'Û‡','Ûˆ'=>'Ûˆ','Û‰'=>'Û‰','ÛŠ'=>'ÛŠ','Û‹'=>'Û‹','ÛŒ'=>'ÛŒ','Û'=>'Û','ÛŽ'=>'ÛŽ','Û'=>'Û','Û'=>'Û','Û‘'=>'Û‘','Û’'=>'Û’','Û“'=>'Û“','Û•'=>'Û•','Û–'=>'Û–','Û—'=>'Û—','Û˜'=>'Û˜','Û™'=>'Û™','Ûš'=>'Ûš','Û›'=>'Û›','Ûœ'=>'Ûœ','Ûž'=>'Ûž','ÛŸ'=>'ÛŸ','Û '=>'Û ','Û¡'=>'Û¡','Û¢'=>'Û¢','Û£'=>'Û£','Û¤'=>'Û¤','Û¥'=>'Û¥','Û¦'=>'Û¦','Û§'=>'Û§','Û¨'=>'Û¨','Ûª'=>'Ûª','Û«'=>'Û«','Û¬'=>'Û¬','Û'=>'Û','Û®'=>'Û®','Û¯'=>'Û¯','Û°'=>'0','Û±'=>'1','Û²'=>'2','Û³'=>'3','Û´'=>'4','Ûµ'=>'5','Û¶'=>'6','Û·'=>'7','Û¸'=>'8','Û¹'=>'9','Ûº'=>'Ûº','Û»'=>'Û»','Û¼'=>'Û¼','Û¿'=>'Û¿','Ü'=>'Ü','Ü‘'=>'Ü‘','Ü’'=>'Ü’','Ü“'=>'Ü“','Ü”'=>'Ü”','Ü•'=>'Ü•','Ü–'=>'Ü–','Ü—'=>'Ü—','ܘ'=>'ܘ','Ü™'=>'Ü™','Üš'=>'Üš','Ü›'=>'Ü›','Üœ'=>'Üœ','Ü'=>'Ü','Üž'=>'Üž','ÜŸ'=>'ÜŸ','Ü '=>'Ü ','Ü¡'=>'Ü¡','Ü¢'=>'Ü¢','Ü£'=>'Ü£','ܤ'=>'ܤ','Ü¥'=>'Ü¥','ܦ'=>'ܦ','ܧ'=>'ܧ','ܨ'=>'ܨ','Ü©'=>'Ü©','ܪ'=>'ܪ','Ü«'=>'Ü«','ܬ'=>'ܬ','Ü'=>'Ü','Ü®'=>'Ü®','ܯ'=>'ܯ','ܰ'=>'ܰ','ܱ'=>'ܱ','ܲ'=>'ܲ','ܳ'=>'ܳ','Ü´'=>'Ü´','ܵ'=>'ܵ','ܶ'=>'ܶ','Ü·'=>'Ü·','ܸ'=>'ܸ','ܹ'=>'ܹ','ܺ'=>'ܺ','Ü»'=>'Ü»','ܼ'=>'ܼ','ܽ'=>'ܽ','ܾ'=>'ܾ','Ü¿'=>'Ü¿','Ý€'=>'Ý€','Ý'=>'Ý','Ý‚'=>'Ý‚','݃'=>'݃','Ý„'=>'Ý„','Ý…'=>'Ý…','݆'=>'݆','݇'=>'݇','݈'=>'݈','݉'=>'݉','ÝŠ'=>'ÝŠ','Ý'=>'Ý','ÝŽ'=>'ÝŽ','Ý'=>'Ý','Ý'=>'Ý','Ý‘'=>'Ý‘','Ý’'=>'Ý’','Ý“'=>'Ý“','Ý”'=>'Ý”','Ý•'=>'Ý•','Ý–'=>'Ý–','Ý—'=>'Ý—','ݘ'=>'ݘ','Ý™'=>'Ý™','Ýš'=>'Ýš','Ý›'=>'Ý›','Ýœ'=>'Ýœ','Ý'=>'Ý','Ýž'=>'Ýž','ÝŸ'=>'ÝŸ','Ý '=>'Ý ','Ý¡'=>'Ý¡','Ý¢'=>'Ý¢','Ý£'=>'Ý£','ݤ'=>'ݤ','Ý¥'=>'Ý¥','ݦ'=>'ݦ','ݧ'=>'ݧ','ݨ'=>'ݨ','Ý©'=>'Ý©','ݪ'=>'ݪ','Ý«'=>'Ý«','ݬ'=>'ݬ','Ý'=>'Ý','Þ€'=>'Þ€','Þ'=>'Þ','Þ‚'=>'Þ‚','Þƒ'=>'Þƒ','Þ„'=>'Þ„','Þ…'=>'Þ…','Þ†'=>'Þ†','Þ‡'=>'Þ‡','Þˆ'=>'Þˆ','Þ‰'=>'Þ‰','ÞŠ'=>'ÞŠ','Þ‹'=>'Þ‹','ÞŒ'=>'ÞŒ','Þ'=>'Þ','ÞŽ'=>'ÞŽ','Þ'=>'Þ','Þ'=>'Þ','Þ‘'=>'Þ‘','Þ’'=>'Þ’','Þ“'=>'Þ“','Þ”'=>'Þ”','Þ•'=>'Þ•','Þ–'=>'Þ–','Þ—'=>'Þ—','Þ˜'=>'Þ˜','Þ™'=>'Þ™','Þš'=>'Þš','Þ›'=>'Þ›','Þœ'=>'Þœ','Þ'=>'Þ','Þž'=>'Þž','ÞŸ'=>'ÞŸ','Þ '=>'Þ ','Þ¡'=>'Þ¡','Þ¢'=>'Þ¢','Þ£'=>'Þ£','Þ¤'=>'Þ¤','Þ¥'=>'Þ¥','Þ¦'=>'Þ¦','Þ§'=>'Þ§','Þ¨'=>'Þ¨','Þ©'=>'Þ©','Þª'=>'Þª','Þ«'=>'Þ«','Þ¬'=>'Þ¬','Þ'=>'Þ','Þ®'=>'Þ®','Þ¯'=>'Þ¯','Þ°'=>'Þ°','Þ±'=>'Þ±','߀'=>'0','ß'=>'1','ß‚'=>'2','߃'=>'3','ß„'=>'4','ß…'=>'5','߆'=>'6','߇'=>'7','߈'=>'8','߉'=>'9','ߊ'=>'ߊ','ß‹'=>'ß‹','ߌ'=>'ߌ','ß'=>'ß','ߎ'=>'ߎ','ß'=>'ß','ß'=>'ß','ß‘'=>'ß‘','ß’'=>'ß’','ß“'=>'ß“','ß”'=>'ß”','ß•'=>'ß•','ß–'=>'ß–','ß—'=>'ß—','ߘ'=>'ߘ','ß™'=>'ß™','ßš'=>'ßš','ß›'=>'ß›','ßœ'=>'ßœ','ß'=>'ß','ßž'=>'ßž','ߟ'=>'ߟ','ß '=>'ß ','ß¡'=>'ß¡','ߢ'=>'ߢ','ߣ'=>'ߣ','ߤ'=>'ߤ','ߥ'=>'ߥ','ߦ'=>'ߦ','ß§'=>'ß§','ߨ'=>'ߨ','ß©'=>'ß©','ߪ'=>'ߪ','ß«'=>'ß«','߬'=>'߬','ß'=>'ß','ß®'=>'ß®','߯'=>'߯','ß°'=>'ß°','ß±'=>'ß±','ß²'=>'ß²','ß³'=>'ß³','ß´'=>'ß´','ßµ'=>'ßµ','ߺ'=>'ߺ');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_1.php b/phpBB/includes/utf/data/search_indexer_1.php deleted file mode 100644 index 6173117ffc..0000000000 --- a/phpBB/includes/utf/data/search_indexer_1.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('à¤'=>'à¤','ं'=>'ं','ः'=>'ः','ऄ'=>'ऄ','अ'=>'अ','आ'=>'आ','इ'=>'इ','ई'=>'ई','उ'=>'उ','ऊ'=>'ऊ','ऋ'=>'ऋ','ऌ'=>'ऌ','à¤'=>'à¤','ऎ'=>'ऎ','à¤'=>'à¤','à¤'=>'à¤','ऑ'=>'ऑ','ऒ'=>'ऒ','ओ'=>'ओ','औ'=>'औ','क'=>'क','ख'=>'ख','ग'=>'ग','घ'=>'घ','ङ'=>'ङ','च'=>'च','छ'=>'छ','ज'=>'ज','à¤'=>'à¤','ञ'=>'ञ','ट'=>'ट','ठ'=>'ठ','ड'=>'ड','ढ'=>'ढ','ण'=>'ण','त'=>'त','थ'=>'थ','द'=>'द','ध'=>'ध','न'=>'न','ऩ'=>'ऩ','प'=>'प','फ'=>'फ','ब'=>'ब','à¤'=>'à¤','म'=>'म','य'=>'य','र'=>'र','ऱ'=>'ऱ','ल'=>'ल','ळ'=>'ळ','ऴ'=>'ऴ','व'=>'व','श'=>'श','ष'=>'ष','स'=>'स','ह'=>'ह','़'=>'़','ऽ'=>'ऽ','ा'=>'ा','ि'=>'ि','ी'=>'ी','à¥'=>'à¥','ू'=>'ू','ृ'=>'ृ','ॄ'=>'ॄ','ॅ'=>'ॅ','ॆ'=>'ॆ','े'=>'े','ै'=>'ै','ॉ'=>'ॉ','ॊ'=>'ॊ','ो'=>'ो','ौ'=>'ौ','à¥'=>'à¥','à¥'=>'à¥','॑'=>'॑','॒'=>'॒','॓'=>'॓','॔'=>'॔','क़'=>'क़','ख़'=>'ख़','ग़'=>'ग़','ज़'=>'ज़','ड़'=>'ड़','à¥'=>'à¥','फ़'=>'फ़','य़'=>'य़','ॠ'=>'ॠ','ॡ'=>'ॡ','ॢ'=>'ॢ','ॣ'=>'ॣ','०'=>'0','१'=>'1','२'=>'2','३'=>'3','४'=>'4','५'=>'5','६'=>'6','à¥'=>'7','८'=>'8','९'=>'9','ॻ'=>'ॻ','ॼ'=>'ॼ','ॽ'=>'ॽ','ॾ'=>'ॾ','ॿ'=>'ॿ','à¦'=>'à¦','ং'=>'ং','ঃ'=>'ঃ','অ'=>'অ','আ'=>'আ','ই'=>'ই','ঈ'=>'ঈ','উ'=>'উ','ঊ'=>'ঊ','ঋ'=>'ঋ','ঌ'=>'ঌ','à¦'=>'à¦','à¦'=>'à¦','ও'=>'ও','ঔ'=>'ঔ','ক'=>'ক','খ'=>'খ','গ'=>'গ','ঘ'=>'ঘ','ঙ'=>'ঙ','চ'=>'চ','ছ'=>'ছ','জ'=>'জ','à¦'=>'à¦','ঞ'=>'ঞ','ট'=>'ট','ঠ'=>'ঠ','ড'=>'ড','ঢ'=>'ঢ','ণ'=>'ণ','ত'=>'ত','থ'=>'থ','দ'=>'দ','ধ'=>'ধ','ন'=>'ন','প'=>'প','ফ'=>'ফ','ব'=>'ব','à¦'=>'à¦','ম'=>'ম','য'=>'য','র'=>'র','ল'=>'ল','শ'=>'শ','ষ'=>'ষ','স'=>'স','হ'=>'হ','়'=>'়','ঽ'=>'ঽ','া'=>'া','ি'=>'ি','à§€'=>'à§€','à§'=>'à§','à§‚'=>'à§‚','ৃ'=>'ৃ','à§„'=>'à§„','ে'=>'ে','ৈ'=>'ৈ','à§‹'=>'à§‹','à§Œ'=>'à§Œ','à§'=>'à§','à§Ž'=>'à§Ž','à§—'=>'à§—','à§œ'=>'à§œ','à§'=>'à§','à§Ÿ'=>'à§Ÿ','à§ '=>'à§ ','à§¡'=>'à§¡','à§¢'=>'à§¢','à§£'=>'à§£','০'=>'0','à§§'=>'1','২'=>'2','à§©'=>'3','৪'=>'4','à§«'=>'5','৬'=>'6','à§'=>'7','à§®'=>'8','৯'=>'9','à§°'=>'à§°','à§±'=>'à§±','à§´'=>'1','à§µ'=>'2','à§¶'=>'3','à§·'=>'4','৸'=>'৸','à§¹'=>'16','à¨'=>'à¨','ਂ'=>'ਂ','ਃ'=>'ਃ','ਅ'=>'ਅ','ਆ'=>'ਆ','ਇ'=>'ਇ','ਈ'=>'ਈ','ਉ'=>'ਉ','ਊ'=>'ਊ','à¨'=>'à¨','à¨'=>'à¨','ਓ'=>'ਓ','ਔ'=>'ਔ','ਕ'=>'ਕ','ਖ'=>'ਖ','ਗ'=>'ਗ','ਘ'=>'ਘ','ਙ'=>'ਙ','ਚ'=>'ਚ','ਛ'=>'ਛ','ਜ'=>'ਜ','à¨'=>'à¨','ਞ'=>'ਞ','ਟ'=>'ਟ','ਠ'=>'ਠ','ਡ'=>'ਡ','ਢ'=>'ਢ','ਣ'=>'ਣ','ਤ'=>'ਤ','ਥ'=>'ਥ','ਦ'=>'ਦ','ਧ'=>'ਧ','ਨ'=>'ਨ','ਪ'=>'ਪ','ਫ'=>'ਫ','ਬ'=>'ਬ','à¨'=>'à¨','ਮ'=>'ਮ','ਯ'=>'ਯ','ਰ'=>'ਰ','ਲ'=>'ਲ','ਲ਼'=>'ਲ਼','ਵ'=>'ਵ','ਸ਼'=>'ਸ਼','ਸ'=>'ਸ','ਹ'=>'ਹ','਼'=>'਼','ਾ'=>'ਾ','ਿ'=>'ਿ','à©€'=>'à©€','à©'=>'à©','à©‚'=>'à©‚','ੇ'=>'ੇ','ੈ'=>'ੈ','à©‹'=>'à©‹','ੌ'=>'ੌ','à©'=>'à©','à©™'=>'à©™','ਗ਼'=>'ਗ਼','à©›'=>'à©›','ੜ'=>'ੜ','ਫ਼'=>'ਫ਼','੦'=>'0','à©§'=>'1','੨'=>'2','à©©'=>'3','੪'=>'4','à©«'=>'5','੬'=>'6','à©'=>'7','à©®'=>'8','੯'=>'9','à©°'=>'à©°','ੱ'=>'ੱ','ੲ'=>'ੲ','ੳ'=>'ੳ','à©´'=>'à©´','àª'=>'àª','ં'=>'ં','ઃ'=>'ઃ','અ'=>'અ','આ'=>'આ','ઇ'=>'ઇ','ઈ'=>'ઈ','ઉ'=>'ઉ','ઊ'=>'ઊ','ઋ'=>'ઋ','ઌ'=>'ઌ','àª'=>'àª','àª'=>'àª','àª'=>'àª','ઑ'=>'ઑ','ઓ'=>'ઓ','ઔ'=>'ઔ','ક'=>'ક','ખ'=>'ખ','ગ'=>'ગ','ઘ'=>'ઘ','ઙ'=>'ઙ','ચ'=>'ચ','છ'=>'છ','જ'=>'જ','àª'=>'àª','ઞ'=>'ઞ','ટ'=>'ટ','ઠ'=>'ઠ','ડ'=>'ડ','ઢ'=>'ઢ','ણ'=>'ણ','ત'=>'ત','થ'=>'થ','દ'=>'દ','ધ'=>'ધ','ન'=>'ન','પ'=>'પ','ફ'=>'ફ','બ'=>'બ','àª'=>'àª','મ'=>'મ','ય'=>'ય','ર'=>'ર','લ'=>'લ','ળ'=>'ળ','વ'=>'વ','શ'=>'શ','ષ'=>'ષ','સ'=>'સ','હ'=>'હ','઼'=>'઼','ઽ'=>'ઽ','ા'=>'ા','િ'=>'િ','à«€'=>'à«€','à«'=>'à«','à«‚'=>'à«‚','ૃ'=>'ૃ','à«„'=>'à«„','à«…'=>'à«…','ે'=>'ે','ૈ'=>'ૈ','ૉ'=>'ૉ','à«‹'=>'à«‹','ૌ'=>'ૌ','à«'=>'à«','à«'=>'à«','à« '=>'à« ','à«¡'=>'à«¡','à«¢'=>'à«¢','à«£'=>'à«£','૦'=>'0','à«§'=>'1','૨'=>'2','à«©'=>'3','૪'=>'4','à««'=>'5','૬'=>'6','à«'=>'7','à«®'=>'8','૯'=>'9','à¬'=>'à¬','ଂ'=>'ଂ','ଃ'=>'ଃ','ଅ'=>'ଅ','ଆ'=>'ଆ','ଇ'=>'ଇ','ଈ'=>'ଈ','ଉ'=>'ଉ','ଊ'=>'ଊ','ଋ'=>'ଋ','ଌ'=>'ଌ','à¬'=>'à¬','à¬'=>'à¬','ଓ'=>'ଓ','ଔ'=>'ଔ','କ'=>'କ','ଖ'=>'ଖ','ଗ'=>'ଗ','ଘ'=>'ଘ','ଙ'=>'ଙ','ଚ'=>'ଚ','ଛ'=>'ଛ','ଜ'=>'ଜ','à¬'=>'à¬','ଞ'=>'ଞ','ଟ'=>'ଟ','ଠ'=>'ଠ','ଡ'=>'ଡ','ଢ'=>'ଢ','ଣ'=>'ଣ','ତ'=>'ତ','ଥ'=>'ଥ','ଦ'=>'ଦ','ଧ'=>'ଧ','ନ'=>'ନ','ପ'=>'ପ','ଫ'=>'ଫ','ବ'=>'ବ','à¬'=>'à¬','ମ'=>'ମ','ଯ'=>'ଯ','ର'=>'ର','ଲ'=>'ଲ','ଳ'=>'ଳ','ଵ'=>'ଵ','ଶ'=>'ଶ','ଷ'=>'ଷ','ସ'=>'ସ','ହ'=>'ହ','଼'=>'଼','ଽ'=>'ଽ','ା'=>'ା','ି'=>'ି','à€'=>'à€','à'=>'à','à‚'=>'à‚','àƒ'=>'àƒ','à‡'=>'à‡','àˆ'=>'àˆ','à‹'=>'à‹','àŒ'=>'àŒ','à'=>'à','à–'=>'à–','à—'=>'à—','àœ'=>'àœ','à'=>'à','àŸ'=>'àŸ','à '=>'à ','à¡'=>'à¡','à¦'=>'0','à§'=>'1','à¨'=>'2','à©'=>'3','àª'=>'4','à«'=>'5','à¬'=>'6','à'=>'7','à®'=>'8','à¯'=>'9','à±'=>'à±','ஂ'=>'ஂ','ஃ'=>'ஃ','à®…'=>'à®…','ஆ'=>'ஆ','இ'=>'இ','ஈ'=>'ஈ','உ'=>'உ','ஊ'=>'ஊ','எ'=>'எ','à®'=>'à®','à®'=>'à®','à®’'=>'à®’','ஓ'=>'ஓ','à®”'=>'à®”','க'=>'க','à®™'=>'à®™','ச'=>'ச','ஜ'=>'ஜ','ஞ'=>'ஞ','ட'=>'ட','ண'=>'ண','த'=>'த','ந'=>'ந','ன'=>'ன','ப'=>'ப','à®®'=>'à®®','ய'=>'ய','à®°'=>'à®°','à®±'=>'à®±','ல'=>'ல','ள'=>'ள','à®´'=>'à®´','வ'=>'வ','à®¶'=>'à®¶','à®·'=>'à®·','ஸ'=>'ஸ','ஹ'=>'ஹ','ா'=>'ா','ி'=>'ி','ீ'=>'ீ','à¯'=>'à¯','ூ'=>'ூ','ெ'=>'ெ','ே'=>'ே','ை'=>'ை','ொ'=>'ொ','ோ'=>'ோ','ௌ'=>'ௌ','à¯'=>'à¯','ௗ'=>'ௗ','௦'=>'0','௧'=>'1','௨'=>'2','௩'=>'3','௪'=>'4','௫'=>'5','௬'=>'6','à¯'=>'7','௮'=>'8','௯'=>'9','௰'=>'10','௱'=>'100','௲'=>'1000','à°'=>'à°','à°‚'=>'à°‚','à°ƒ'=>'à°ƒ','à°…'=>'à°…','à°†'=>'à°†','à°‡'=>'à°‡','à°ˆ'=>'à°ˆ','à°‰'=>'à°‰','à°Š'=>'à°Š','à°‹'=>'à°‹','à°Œ'=>'à°Œ','à°Ž'=>'à°Ž','à°'=>'à°','à°'=>'à°','à°’'=>'à°’','à°“'=>'à°“','à°”'=>'à°”','à°•'=>'à°•','à°–'=>'à°–','à°—'=>'à°—','à°˜'=>'à°˜','à°™'=>'à°™','à°š'=>'à°š','à°›'=>'à°›','à°œ'=>'à°œ','à°'=>'à°','à°ž'=>'à°ž','à°Ÿ'=>'à°Ÿ','à° '=>'à° ','à°¡'=>'à°¡','à°¢'=>'à°¢','à°£'=>'à°£','à°¤'=>'à°¤','à°¥'=>'à°¥','à°¦'=>'à°¦','à°§'=>'à°§','à°¨'=>'à°¨','à°ª'=>'à°ª','à°«'=>'à°«','à°¬'=>'à°¬','à°'=>'à°','à°®'=>'à°®','à°¯'=>'à°¯','à°°'=>'à°°','à°±'=>'à°±','à°²'=>'à°²','à°³'=>'à°³','à°µ'=>'à°µ','à°¶'=>'à°¶','à°·'=>'à°·','à°¸'=>'à°¸','à°¹'=>'à°¹','à°¾'=>'à°¾','à°¿'=>'à°¿','à±€'=>'à±€','à±'=>'à±','ూ'=>'ూ','ృ'=>'ృ','ౄ'=>'ౄ','ె'=>'ె','ే'=>'ే','ై'=>'ై','ొ'=>'ొ','ో'=>'ో','ౌ'=>'ౌ','à±'=>'à±','ౕ'=>'ౕ','à±–'=>'à±–','à± '=>'à± ','ౡ'=>'ౡ','౦'=>'0','à±§'=>'1','౨'=>'2','౩'=>'3','౪'=>'4','౫'=>'5','౬'=>'6','à±'=>'7','à±®'=>'8','౯'=>'9','ಂ'=>'ಂ','ಃ'=>'ಃ','ಅ'=>'ಅ','ಆ'=>'ಆ','ಇ'=>'ಇ','ಈ'=>'ಈ','ಉ'=>'ಉ','ಊ'=>'ಊ','ಋ'=>'ಋ','ಌ'=>'ಌ','ಎ'=>'ಎ','à²'=>'à²','à²'=>'à²','ಒ'=>'ಒ','ಓ'=>'ಓ','ಔ'=>'ಔ','ಕ'=>'ಕ','ಖ'=>'ಖ','ಗ'=>'ಗ','ಘ'=>'ಘ','ಙ'=>'ಙ','ಚ'=>'ಚ','ಛ'=>'ಛ','ಜ'=>'ಜ','à²'=>'à²','ಞ'=>'ಞ','ಟ'=>'ಟ','ಠ'=>'ಠ','ಡ'=>'ಡ','ಢ'=>'ಢ','ಣ'=>'ಣ','ತ'=>'ತ','ಥ'=>'ಥ','ದ'=>'ದ','ಧ'=>'ಧ','ನ'=>'ನ','ಪ'=>'ಪ','ಫ'=>'ಫ','ಬ'=>'ಬ','à²'=>'à²','ಮ'=>'ಮ','ಯ'=>'ಯ','ರ'=>'ರ','ಱ'=>'ಱ','ಲ'=>'ಲ','ಳ'=>'ಳ','ವ'=>'ವ','ಶ'=>'ಶ','ಷ'=>'ಷ','ಸ'=>'ಸ','ಹ'=>'ಹ','಼'=>'಼','ಽ'=>'ಽ','ಾ'=>'ಾ','ಿ'=>'ಿ','à³€'=>'à³€','à³'=>'à³','ೂ'=>'ೂ','ೃ'=>'ೃ','ೄ'=>'ೄ','ೆ'=>'ೆ','ೇ'=>'ೇ','ೈ'=>'ೈ','ೊ'=>'ೊ','ೋ'=>'ೋ','ೌ'=>'ೌ','à³'=>'à³','ೕ'=>'ೕ','à³–'=>'à³–','ೞ'=>'ೞ','à³ '=>'à³ ','ೡ'=>'ೡ','à³¢'=>'à³¢','à³£'=>'à³£','೦'=>'0','à³§'=>'1','೨'=>'2','೩'=>'3','೪'=>'4','೫'=>'5','೬'=>'6','à³'=>'7','à³®'=>'8','೯'=>'9','à´‚'=>'à´‚','à´ƒ'=>'à´ƒ','à´…'=>'à´…','à´†'=>'à´†','à´‡'=>'à´‡','à´ˆ'=>'à´ˆ','à´‰'=>'à´‰','à´Š'=>'à´Š','à´‹'=>'à´‹','à´Œ'=>'à´Œ','à´Ž'=>'à´Ž','à´'=>'à´','à´'=>'à´','à´’'=>'à´’','à´“'=>'à´“','à´”'=>'à´”','à´•'=>'à´•','à´–'=>'à´–','à´—'=>'à´—','à´˜'=>'à´˜','à´™'=>'à´™','à´š'=>'à´š','à´›'=>'à´›','à´œ'=>'à´œ','à´'=>'à´','à´ž'=>'à´ž','à´Ÿ'=>'à´Ÿ','à´ '=>'à´ ','à´¡'=>'à´¡','à´¢'=>'à´¢','à´£'=>'à´£','à´¤'=>'à´¤','à´¥'=>'à´¥','à´¦'=>'à´¦','à´§'=>'à´§','à´¨'=>'à´¨','à´ª'=>'à´ª','à´«'=>'à´«','à´¬'=>'à´¬','à´'=>'à´','à´®'=>'à´®','à´¯'=>'à´¯','à´°'=>'à´°','à´±'=>'à´±','à´²'=>'à´²','à´³'=>'à´³','à´´'=>'à´´','à´µ'=>'à´µ','à´¶'=>'à´¶','à´·'=>'à´·','à´¸'=>'à´¸','à´¹'=>'à´¹','à´¾'=>'à´¾','à´¿'=>'à´¿','ീ'=>'ീ','àµ'=>'àµ','ൂ'=>'ൂ','ൃ'=>'ൃ','െ'=>'െ','േ'=>'േ','ൈ'=>'ൈ','ൊ'=>'ൊ','ോ'=>'ോ','ൌ'=>'ൌ','àµ'=>'àµ','ൗ'=>'ൗ','ൠ'=>'ൠ','ൡ'=>'ൡ','൦'=>'0','൧'=>'1','൨'=>'2','൩'=>'3','൪'=>'4','൫'=>'5','൬'=>'6','àµ'=>'7','൮'=>'8','൯'=>'9','à¶‚'=>'à¶‚','ඃ'=>'ඃ','à¶…'=>'à¶…','ආ'=>'ආ','ඇ'=>'ඇ','ඈ'=>'ඈ','ඉ'=>'ඉ','à¶Š'=>'à¶Š','à¶‹'=>'à¶‹','à¶Œ'=>'à¶Œ','à¶'=>'à¶','à¶Ž'=>'à¶Ž','à¶'=>'à¶','à¶'=>'à¶','à¶‘'=>'à¶‘','à¶’'=>'à¶’','à¶“'=>'à¶“','à¶”'=>'à¶”','à¶•'=>'à¶•','à¶–'=>'à¶–','à¶š'=>'à¶š','à¶›'=>'à¶›','à¶œ'=>'à¶œ','à¶'=>'à¶','à¶ž'=>'à¶ž','à¶Ÿ'=>'à¶Ÿ','à¶ '=>'à¶ ','à¶¡'=>'à¶¡','à¶¢'=>'à¶¢','à¶£'=>'à¶£','ඤ'=>'ඤ','à¶¥'=>'à¶¥','ඦ'=>'ඦ','à¶§'=>'à¶§','ඨ'=>'ඨ','à¶©'=>'à¶©','ඪ'=>'ඪ','à¶«'=>'à¶«','ඬ'=>'ඬ','à¶'=>'à¶','à¶®'=>'à¶®','ද'=>'ද','à¶°'=>'à¶°','à¶±'=>'à¶±','à¶³'=>'à¶³','à¶´'=>'à¶´','à¶µ'=>'à¶µ','à¶¶'=>'à¶¶','à¶·'=>'à¶·','ම'=>'ම','à¶¹'=>'à¶¹','ය'=>'ය','à¶»'=>'à¶»','à¶½'=>'à¶½','à·€'=>'à·€','à·'=>'à·','à·‚'=>'à·‚','à·ƒ'=>'à·ƒ','à·„'=>'à·„','à·…'=>'à·…','à·†'=>'à·†','à·Š'=>'à·Š','à·'=>'à·','à·'=>'à·','à·‘'=>'à·‘','à·’'=>'à·’','à·“'=>'à·“','à·”'=>'à·”','à·–'=>'à·–','à·˜'=>'à·˜','à·™'=>'à·™','à·š'=>'à·š','à·›'=>'à·›','à·œ'=>'à·œ','à·'=>'à·','à·ž'=>'à·ž','à·Ÿ'=>'à·Ÿ','à·²'=>'à·²','à·³'=>'à·³','à¸'=>'à¸','ข'=>'ข','ฃ'=>'ฃ','ค'=>'ค','ฅ'=>'ฅ','ฆ'=>'ฆ','ง'=>'ง','จ'=>'จ','ฉ'=>'ฉ','ช'=>'ช','ซ'=>'ซ','ฌ'=>'ฌ','à¸'=>'à¸','ฎ'=>'ฎ','à¸'=>'à¸','à¸'=>'à¸','ฑ'=>'ฑ','ฒ'=>'ฒ','ณ'=>'ณ','ด'=>'ด','ต'=>'ต','ถ'=>'ถ','ท'=>'ท','ธ'=>'ธ','น'=>'น','บ'=>'บ','ป'=>'ป','ผ'=>'ผ','à¸'=>'à¸','พ'=>'พ','ฟ'=>'ฟ','ภ'=>'ภ','ม'=>'ม','ย'=>'ย','ร'=>'ร','ฤ'=>'ฤ','ล'=>'ล','ฦ'=>'ฦ','ว'=>'ว','ศ'=>'ศ','ษ'=>'ษ','ส'=>'ส','ห'=>'ห','ฬ'=>'ฬ','à¸'=>'à¸','ฮ'=>'ฮ','ฯ'=>'ฯ','ะ'=>'ะ','ั'=>'ั','า'=>'า','ำ'=>'ำ','ิ'=>'ิ','ี'=>'ี','ึ'=>'ึ','ื'=>'ื','ุ'=>'ุ','ู'=>'ู','ฺ'=>'ฺ','เ'=>'เ','à¹'=>'à¹','โ'=>'โ','ใ'=>'ใ','ไ'=>'ไ','ๅ'=>'ๅ','ๆ'=>'ๆ','็'=>'็','่'=>'่','้'=>'้','๊'=>'๊','๋'=>'๋','์'=>'์','à¹'=>'à¹','๎'=>'๎','à¹'=>'0','๑'=>'1','๒'=>'2','๓'=>'3','๔'=>'4','๕'=>'5','๖'=>'6','๗'=>'7','๘'=>'8','๙'=>'9','àº'=>'àº','ຂ'=>'ຂ','ຄ'=>'ຄ','ງ'=>'ງ','ຈ'=>'ຈ','ຊ'=>'ຊ','àº'=>'àº','ດ'=>'ດ','ຕ'=>'ຕ','ຖ'=>'ຖ','ທ'=>'ທ','ນ'=>'ນ','ບ'=>'ບ','ປ'=>'ປ','ຜ'=>'ຜ','àº'=>'àº','ພ'=>'ພ','ຟ'=>'ຟ','ມ'=>'ມ','ຢ'=>'ຢ','ຣ'=>'ຣ','ລ'=>'ລ','ວ'=>'ວ','ສ'=>'ສ','ຫ'=>'ຫ','àº'=>'àº','ຮ'=>'ຮ','ຯ'=>'ຯ','ະ'=>'ະ','ັ'=>'ັ','າ'=>'າ','ຳ'=>'ຳ','ິ'=>'ິ','ີ'=>'ີ','ຶ'=>'ຶ','ື'=>'ື','ຸ'=>'ຸ','ູ'=>'ູ','ົ'=>'ົ','ຼ'=>'ຼ','ຽ'=>'ຽ','ເ'=>'ເ','à»'=>'à»','ໂ'=>'ໂ','ໃ'=>'ໃ','ໄ'=>'ໄ','ໆ'=>'ໆ','່'=>'່','້'=>'້','໊'=>'໊','໋'=>'໋','໌'=>'໌','à»'=>'à»','à»'=>'0','໑'=>'1','à»’'=>'2','໓'=>'3','à»”'=>'4','໕'=>'5','à»–'=>'6','à»—'=>'7','໘'=>'8','à»™'=>'9','ໜ'=>'ໜ','à»'=>'à»','ༀ'=>'ༀ','༘'=>'༘','༙'=>'༙','༠'=>'0','༡'=>'1','༢'=>'2','༣'=>'3','༤'=>'4','༥'=>'5','༦'=>'6','༧'=>'7','༨'=>'8','༩'=>'9','༪'=>'1/2','༫'=>'3/2','༬'=>'5/2','à¼'=>'7/2','༮'=>'9/2','༯'=>'11/2','༰'=>'13/2','༱'=>'15/2','༲'=>'17/2','༳'=>'-1/2','༵'=>'༵','༷'=>'༷','༹'=>'༹','༾'=>'༾','༿'=>'༿','ཀ'=>'ཀ','à½'=>'à½','ག'=>'ག','གྷ'=>'གྷ','ང'=>'ང','ཅ'=>'ཅ','ཆ'=>'ཆ','ཇ'=>'ཇ','ཉ'=>'ཉ','ཊ'=>'ཊ','ཋ'=>'ཋ','ཌ'=>'ཌ','à½'=>'à½','ཎ'=>'ཎ','à½'=>'à½','à½'=>'à½','ད'=>'ད','དྷ'=>'དྷ','ན'=>'ན','པ'=>'པ','ཕ'=>'ཕ','བ'=>'བ','བྷ'=>'བྷ','མ'=>'མ','ཙ'=>'ཙ','ཚ'=>'ཚ','ཛ'=>'ཛ','ཛྷ'=>'ཛྷ','à½'=>'à½','ཞ'=>'ཞ','ཟ'=>'ཟ','འ'=>'འ','ཡ'=>'ཡ','ར'=>'ར','ལ'=>'ལ','ཤ'=>'ཤ','ཥ'=>'ཥ','ས'=>'ས','ཧ'=>'ཧ','ཨ'=>'ཨ','ཀྵ'=>'ཀྵ','ཪ'=>'ཪ','ཱ'=>'ཱ','ི'=>'ི','ཱི'=>'ཱི','ུ'=>'ུ','ཱུ'=>'ཱུ','ྲྀ'=>'ྲྀ','ཷ'=>'ཷ','ླྀ'=>'ླྀ','ཹ'=>'ཹ','ེ'=>'ེ','ཻ'=>'ཻ','ོ'=>'ོ','ཽ'=>'ཽ','ཾ'=>'ཾ','ཿ'=>'ཿ','ྀ'=>'ྀ','à¾'=>'à¾','ྂ'=>'ྂ','ྃ'=>'ྃ','྄'=>'྄','྆'=>'྆','྇'=>'྇','ྈ'=>'ྈ','ྉ'=>'ྉ','ྊ'=>'ྊ','ྋ'=>'ྋ','à¾'=>'à¾','ྑ'=>'ྑ','ྒ'=>'ྒ','ྒྷ'=>'ྒྷ','ྔ'=>'ྔ','ྕ'=>'ྕ','ྖ'=>'ྖ','ྗ'=>'ྗ','ྙ'=>'ྙ','ྚ'=>'ྚ','ྛ'=>'ྛ','ྜ'=>'ྜ','à¾'=>'à¾','ྞ'=>'ྞ','ྟ'=>'ྟ','ྠ'=>'ྠ','ྡ'=>'ྡ','ྡྷ'=>'ྡྷ','ྣ'=>'ྣ','ྤ'=>'ྤ','ྥ'=>'ྥ','ྦ'=>'ྦ','ྦྷ'=>'ྦྷ','ྨ'=>'ྨ','ྩ'=>'ྩ','ྪ'=>'ྪ','ྫ'=>'ྫ','ྫྷ'=>'ྫྷ','à¾'=>'à¾','ྮ'=>'ྮ','ྯ'=>'ྯ','ྰ'=>'ྰ','ྱ'=>'ྱ','ྲ'=>'ྲ','ླ'=>'ླ','ྴ'=>'ྴ','ྵ'=>'ྵ','ྶ'=>'ྶ','ྷ'=>'ྷ','ྸ'=>'ྸ','ྐྵ'=>'ྐྵ','ྺ'=>'ྺ','ྻ'=>'ྻ','ྼ'=>'ྼ','࿆'=>'࿆');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_19.php b/phpBB/includes/utf/data/search_indexer_19.php deleted file mode 100644 index e26f7d81a0..0000000000 --- a/phpBB/includes/utf/data/search_indexer_19.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('é¾»'=>'é¾»');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_2.php b/phpBB/includes/utf/data/search_indexer_2.php deleted file mode 100644 index 751226ed22..0000000000 --- a/phpBB/includes/utf/data/search_indexer_2.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('က'=>'က','á€'=>'á€','ဂ'=>'ဂ','ဃ'=>'ဃ','င'=>'င','စ'=>'စ','ဆ'=>'ဆ','ဇ'=>'ဇ','ဈ'=>'ဈ','ဉ'=>'ဉ','ည'=>'ည','ဋ'=>'ဋ','ဌ'=>'ဌ','á€'=>'á€','ဎ'=>'ဎ','á€'=>'á€','á€'=>'á€','ထ'=>'ထ','ဒ'=>'ဒ','ဓ'=>'ဓ','န'=>'န','ပ'=>'ပ','ဖ'=>'ဖ','ဗ'=>'ဗ','ဘ'=>'ဘ','မ'=>'မ','ယ'=>'ယ','ရ'=>'ရ','လ'=>'လ','á€'=>'á€','သ'=>'သ','ဟ'=>'ဟ','ဠ'=>'ဠ','အ'=>'အ','ဣ'=>'ဣ','ဤ'=>'ဤ','ဥ'=>'ဥ','ဦ'=>'ဦ','ဧ'=>'ဧ','ဩ'=>'ဩ','ဪ'=>'ဪ','ာ'=>'ာ','á€'=>'á€','ီ'=>'ီ','ု'=>'ု','ူ'=>'ူ','ေ'=>'ေ','ဲ'=>'ဲ','ံ'=>'ံ','့'=>'့','း'=>'း','္'=>'္','á€'=>'0','á'=>'1','á‚'=>'2','áƒ'=>'3','á„'=>'4','á…'=>'5','á†'=>'6','á‡'=>'7','áˆ'=>'8','á‰'=>'9','á'=>'á','á‘'=>'á‘','á’'=>'á’','á“'=>'á“','á”'=>'á”','á•'=>'á•','á–'=>'á–','á—'=>'á—','á˜'=>'á˜','á™'=>'á™','á‚ '=>'â´€','á‚¡'=>'â´','á‚¢'=>'â´‚','á‚£'=>'â´ƒ','Ⴄ'=>'â´„','á‚¥'=>'â´…','Ⴆ'=>'â´†','á‚§'=>'â´‡','Ⴈ'=>'â´ˆ','á‚©'=>'â´‰','Ⴊ'=>'â´Š','á‚«'=>'â´‹','Ⴌ'=>'â´Œ','á‚'=>'â´','á‚®'=>'â´Ž','Ⴏ'=>'â´','á‚°'=>'â´','Ⴑ'=>'â´‘','Ⴒ'=>'â´’','Ⴓ'=>'â´“','á‚´'=>'â´”','Ⴕ'=>'â´•','á‚¶'=>'â´–','á‚·'=>'â´—','Ⴘ'=>'â´˜','Ⴙ'=>'â´™','Ⴚ'=>'â´š','á‚»'=>'â´›','Ⴜ'=>'â´œ','Ⴝ'=>'â´','Ⴞ'=>'â´ž','á‚¿'=>'â´Ÿ','Ⴠ'=>'â´ ','áƒ'=>'â´¡','Ⴢ'=>'â´¢','Ⴣ'=>'â´£','Ⴤ'=>'â´¤','Ⴥ'=>'â´¥','áƒ'=>'áƒ','ბ'=>'ბ','გ'=>'გ','დ'=>'დ','ე'=>'ე','ვ'=>'ვ','ზ'=>'ზ','თ'=>'თ','ი'=>'ი','კ'=>'კ','ლ'=>'ლ','მ'=>'მ','ნ'=>'ნ','áƒ'=>'áƒ','პ'=>'პ','ჟ'=>'ჟ','რ'=>'რ','ს'=>'ს','ტ'=>'ტ','უ'=>'უ','ფ'=>'ფ','ქ'=>'ქ','ღ'=>'ღ','ყ'=>'ყ','შ'=>'შ','ჩ'=>'ჩ','ც'=>'ც','ძ'=>'ძ','წ'=>'წ','áƒ'=>'áƒ','ხ'=>'ხ','ჯ'=>'ჯ','ჰ'=>'ჰ','ჱ'=>'ჱ','ჲ'=>'ჲ','ჳ'=>'ჳ','ჴ'=>'ჴ','ჵ'=>'ჵ','ჶ'=>'ჶ','ჷ'=>'ჷ','ჸ'=>'ჸ','ჹ'=>'ჹ','ჺ'=>'ჺ','ჼ'=>'ჼ','á„€'=>'á„€','á„'=>'á„','á„‚'=>'á„‚','ᄃ'=>'ᄃ','á„„'=>'á„„','á„…'=>'á„…','ᄆ'=>'ᄆ','ᄇ'=>'ᄇ','ᄈ'=>'ᄈ','ᄉ'=>'ᄉ','ᄊ'=>'ᄊ','á„‹'=>'á„‹','ᄌ'=>'ᄌ','á„'=>'á„','ᄎ'=>'ᄎ','á„'=>'á„','á„'=>'á„','á„‘'=>'á„‘','á„’'=>'á„’','á„“'=>'á„“','á„”'=>'á„”','á„•'=>'á„•','á„–'=>'á„–','á„—'=>'á„—','ᄘ'=>'ᄘ','á„™'=>'á„™','ᄚ'=>'ᄚ','á„›'=>'á„›','ᄜ'=>'ᄜ','á„'=>'á„','ᄞ'=>'ᄞ','ᄟ'=>'ᄟ','á„ '=>'á„ ','á„¡'=>'á„¡','á„¢'=>'á„¢','á„£'=>'á„£','ᄤ'=>'ᄤ','á„¥'=>'á„¥','ᄦ'=>'ᄦ','á„§'=>'á„§','ᄨ'=>'ᄨ','á„©'=>'á„©','ᄪ'=>'ᄪ','á„«'=>'á„«','ᄬ'=>'ᄬ','á„'=>'á„','á„®'=>'á„®','ᄯ'=>'ᄯ','á„°'=>'á„°','ᄱ'=>'ᄱ','ᄲ'=>'ᄲ','ᄳ'=>'ᄳ','á„´'=>'á„´','ᄵ'=>'ᄵ','á„¶'=>'á„¶','á„·'=>'á„·','ᄸ'=>'ᄸ','ᄹ'=>'ᄹ','ᄺ'=>'ᄺ','á„»'=>'á„»','ᄼ'=>'ᄼ','ᄽ'=>'ᄽ','ᄾ'=>'ᄾ','á„¿'=>'á„¿','á…€'=>'á…€','á…'=>'á…','á…‚'=>'á…‚','á…ƒ'=>'á…ƒ','á…„'=>'á…„','á……'=>'á……','á…†'=>'á…†','á…‡'=>'á…‡','á…ˆ'=>'á…ˆ','á…‰'=>'á…‰','á…Š'=>'á…Š','á…‹'=>'á…‹','á…Œ'=>'á…Œ','á…'=>'á…','á…Ž'=>'á…Ž','á…'=>'á…','á…'=>'á…','á…‘'=>'á…‘','á…’'=>'á…’','á…“'=>'á…“','á…”'=>'á…”','á…•'=>'á…•','á…–'=>'á…–','á…—'=>'á…—','á…˜'=>'á…˜','á…™'=>'á…™','á…Ÿ'=>'á…Ÿ','á… '=>'á… ','á…¡'=>'á…¡','á…¢'=>'á…¢','á…£'=>'á…£','á…¤'=>'á…¤','á…¥'=>'á…¥','á…¦'=>'á…¦','á…§'=>'á…§','á…¨'=>'á…¨','á…©'=>'á…©','á…ª'=>'á…ª','á…«'=>'á…«','á…¬'=>'á…¬','á…'=>'á…','á…®'=>'á…®','á…¯'=>'á…¯','á…°'=>'á…°','á…±'=>'á…±','á…²'=>'á…²','á…³'=>'á…³','á…´'=>'á…´','á…µ'=>'á…µ','á…¶'=>'á…¶','á…·'=>'á…·','á…¸'=>'á…¸','á…¹'=>'á…¹','á…º'=>'á…º','á…»'=>'á…»','á…¼'=>'á…¼','á…½'=>'á…½','á…¾'=>'á…¾','á…¿'=>'á…¿','ᆀ'=>'ᆀ','á†'=>'á†','ᆂ'=>'ᆂ','ᆃ'=>'ᆃ','ᆄ'=>'ᆄ','ᆅ'=>'ᆅ','ᆆ'=>'ᆆ','ᆇ'=>'ᆇ','ᆈ'=>'ᆈ','ᆉ'=>'ᆉ','ᆊ'=>'ᆊ','ᆋ'=>'ᆋ','ᆌ'=>'ᆌ','á†'=>'á†','ᆎ'=>'ᆎ','á†'=>'á†','á†'=>'á†','ᆑ'=>'ᆑ','ᆒ'=>'ᆒ','ᆓ'=>'ᆓ','ᆔ'=>'ᆔ','ᆕ'=>'ᆕ','ᆖ'=>'ᆖ','ᆗ'=>'ᆗ','ᆘ'=>'ᆘ','ᆙ'=>'ᆙ','ᆚ'=>'ᆚ','ᆛ'=>'ᆛ','ᆜ'=>'ᆜ','á†'=>'á†','ᆞ'=>'ᆞ','ᆟ'=>'ᆟ','ᆠ'=>'ᆠ','ᆡ'=>'ᆡ','ᆢ'=>'ᆢ','ᆨ'=>'ᆨ','ᆩ'=>'ᆩ','ᆪ'=>'ᆪ','ᆫ'=>'ᆫ','ᆬ'=>'ᆬ','á†'=>'á†','ᆮ'=>'ᆮ','ᆯ'=>'ᆯ','ᆰ'=>'ᆰ','ᆱ'=>'ᆱ','ᆲ'=>'ᆲ','ᆳ'=>'ᆳ','ᆴ'=>'ᆴ','ᆵ'=>'ᆵ','ᆶ'=>'ᆶ','ᆷ'=>'ᆷ','ᆸ'=>'ᆸ','ᆹ'=>'ᆹ','ᆺ'=>'ᆺ','ᆻ'=>'ᆻ','ᆼ'=>'ᆼ','ᆽ'=>'ᆽ','ᆾ'=>'ᆾ','ᆿ'=>'ᆿ','ᇀ'=>'ᇀ','á‡'=>'á‡','ᇂ'=>'ᇂ','ᇃ'=>'ᇃ','ᇄ'=>'ᇄ','ᇅ'=>'ᇅ','ᇆ'=>'ᇆ','ᇇ'=>'ᇇ','ᇈ'=>'ᇈ','ᇉ'=>'ᇉ','ᇊ'=>'ᇊ','ᇋ'=>'ᇋ','ᇌ'=>'ᇌ','á‡'=>'á‡','ᇎ'=>'ᇎ','á‡'=>'á‡','á‡'=>'á‡','ᇑ'=>'ᇑ','ᇒ'=>'ᇒ','ᇓ'=>'ᇓ','ᇔ'=>'ᇔ','ᇕ'=>'ᇕ','ᇖ'=>'ᇖ','ᇗ'=>'ᇗ','ᇘ'=>'ᇘ','ᇙ'=>'ᇙ','ᇚ'=>'ᇚ','ᇛ'=>'ᇛ','ᇜ'=>'ᇜ','á‡'=>'á‡','ᇞ'=>'ᇞ','ᇟ'=>'ᇟ','ᇠ'=>'ᇠ','ᇡ'=>'ᇡ','ᇢ'=>'ᇢ','ᇣ'=>'ᇣ','ᇤ'=>'ᇤ','ᇥ'=>'ᇥ','ᇦ'=>'ᇦ','ᇧ'=>'ᇧ','ᇨ'=>'ᇨ','ᇩ'=>'ᇩ','ᇪ'=>'ᇪ','ᇫ'=>'ᇫ','ᇬ'=>'ᇬ','á‡'=>'á‡','ᇮ'=>'ᇮ','ᇯ'=>'ᇯ','ᇰ'=>'ᇰ','ᇱ'=>'ᇱ','ᇲ'=>'ᇲ','ᇳ'=>'ᇳ','ᇴ'=>'ᇴ','ᇵ'=>'ᇵ','ᇶ'=>'ᇶ','ᇷ'=>'ᇷ','ᇸ'=>'ᇸ','ᇹ'=>'ᇹ','ሀ'=>'ሀ','áˆ'=>'áˆ','ሂ'=>'ሂ','ሃ'=>'ሃ','ሄ'=>'ሄ','ህ'=>'ህ','ሆ'=>'ሆ','ሇ'=>'ሇ','ለ'=>'ለ','ሉ'=>'ሉ','ሊ'=>'ሊ','ላ'=>'ላ','ሌ'=>'ሌ','áˆ'=>'áˆ','ሎ'=>'ሎ','áˆ'=>'áˆ','áˆ'=>'áˆ','ሑ'=>'ሑ','ሒ'=>'ሒ','ሓ'=>'ሓ','ሔ'=>'ሔ','ሕ'=>'ሕ','ሖ'=>'ሖ','ሗ'=>'ሗ','መ'=>'መ','ሙ'=>'ሙ','ሚ'=>'ሚ','ማ'=>'ማ','ሜ'=>'ሜ','áˆ'=>'áˆ','ሞ'=>'ሞ','ሟ'=>'ሟ','ሠ'=>'ሠ','ሡ'=>'ሡ','ሢ'=>'ሢ','ሣ'=>'ሣ','ሤ'=>'ሤ','ሥ'=>'ሥ','ሦ'=>'ሦ','ሧ'=>'ሧ','ረ'=>'ረ','ሩ'=>'ሩ','ሪ'=>'ሪ','ራ'=>'ራ','ሬ'=>'ሬ','áˆ'=>'áˆ','ሮ'=>'ሮ','ሯ'=>'ሯ','ሰ'=>'ሰ','ሱ'=>'ሱ','ሲ'=>'ሲ','ሳ'=>'ሳ','ሴ'=>'ሴ','ስ'=>'ስ','ሶ'=>'ሶ','ሷ'=>'ሷ','ሸ'=>'ሸ','ሹ'=>'ሹ','ሺ'=>'ሺ','ሻ'=>'ሻ','ሼ'=>'ሼ','ሽ'=>'ሽ','ሾ'=>'ሾ','ሿ'=>'ሿ','ቀ'=>'ቀ','á‰'=>'á‰','ቂ'=>'ቂ','ቃ'=>'ቃ','ቄ'=>'ቄ','ቅ'=>'ቅ','ቆ'=>'ቆ','ቇ'=>'ቇ','ቈ'=>'ቈ','ቊ'=>'ቊ','ቋ'=>'ቋ','ቌ'=>'ቌ','á‰'=>'á‰','á‰'=>'á‰','ቑ'=>'ቑ','ቒ'=>'ቒ','ቓ'=>'ቓ','ቔ'=>'ቔ','ቕ'=>'ቕ','ቖ'=>'ቖ','ቘ'=>'ቘ','ቚ'=>'ቚ','ቛ'=>'ቛ','ቜ'=>'ቜ','á‰'=>'á‰','በ'=>'በ','ቡ'=>'ቡ','ቢ'=>'ቢ','ባ'=>'ባ','ቤ'=>'ቤ','ብ'=>'ብ','ቦ'=>'ቦ','ቧ'=>'ቧ','ቨ'=>'ቨ','ቩ'=>'ቩ','ቪ'=>'ቪ','ቫ'=>'ቫ','ቬ'=>'ቬ','á‰'=>'á‰','ቮ'=>'ቮ','ቯ'=>'ቯ','ተ'=>'ተ','ቱ'=>'ቱ','ቲ'=>'ቲ','ታ'=>'ታ','ቴ'=>'ቴ','ት'=>'ት','ቶ'=>'ቶ','ቷ'=>'ቷ','ቸ'=>'ቸ','ቹ'=>'ቹ','ቺ'=>'ቺ','ቻ'=>'ቻ','ቼ'=>'ቼ','ች'=>'ች','ቾ'=>'ቾ','ቿ'=>'ቿ','ኀ'=>'ኀ','áŠ'=>'áŠ','ኂ'=>'ኂ','ኃ'=>'ኃ','ኄ'=>'ኄ','ኅ'=>'ኅ','ኆ'=>'ኆ','ኇ'=>'ኇ','ኈ'=>'ኈ','ኊ'=>'ኊ','ኋ'=>'ኋ','ኌ'=>'ኌ','áŠ'=>'áŠ','áŠ'=>'áŠ','ኑ'=>'ኑ','ኒ'=>'ኒ','ና'=>'ና','ኔ'=>'ኔ','ን'=>'ን','ኖ'=>'ኖ','ኗ'=>'ኗ','ኘ'=>'ኘ','ኙ'=>'ኙ','ኚ'=>'ኚ','ኛ'=>'ኛ','ኜ'=>'ኜ','áŠ'=>'áŠ','ኞ'=>'ኞ','ኟ'=>'ኟ','አ'=>'አ','ኡ'=>'ኡ','ኢ'=>'ኢ','ኣ'=>'ኣ','ኤ'=>'ኤ','እ'=>'እ','ኦ'=>'ኦ','ኧ'=>'ኧ','ከ'=>'ከ','ኩ'=>'ኩ','ኪ'=>'ኪ','ካ'=>'ካ','ኬ'=>'ኬ','áŠ'=>'áŠ','ኮ'=>'ኮ','ኯ'=>'ኯ','ኰ'=>'ኰ','ኲ'=>'ኲ','ኳ'=>'ኳ','ኴ'=>'ኴ','ኵ'=>'ኵ','ኸ'=>'ኸ','ኹ'=>'ኹ','ኺ'=>'ኺ','ኻ'=>'ኻ','ኼ'=>'ኼ','ኽ'=>'ኽ','ኾ'=>'ኾ','á‹€'=>'á‹€','á‹‚'=>'á‹‚','ዃ'=>'ዃ','á‹„'=>'á‹„','á‹…'=>'á‹…','ወ'=>'ወ','ዉ'=>'ዉ','ዊ'=>'ዊ','á‹‹'=>'á‹‹','ዌ'=>'ዌ','á‹'=>'á‹','ዎ'=>'ዎ','á‹'=>'á‹','á‹'=>'á‹','á‹‘'=>'á‹‘','á‹’'=>'á‹’','á‹“'=>'á‹“','á‹”'=>'á‹”','á‹•'=>'á‹•','á‹–'=>'á‹–','ዘ'=>'ዘ','á‹™'=>'á‹™','ዚ'=>'ዚ','á‹›'=>'á‹›','ዜ'=>'ዜ','á‹'=>'á‹','ዞ'=>'ዞ','ዟ'=>'ዟ','á‹ '=>'á‹ ','á‹¡'=>'á‹¡','á‹¢'=>'á‹¢','á‹£'=>'á‹£','ዤ'=>'ዤ','á‹¥'=>'á‹¥','ዦ'=>'ዦ','á‹§'=>'á‹§','የ'=>'የ','á‹©'=>'á‹©','ዪ'=>'ዪ','á‹«'=>'á‹«','ዬ'=>'ዬ','á‹'=>'á‹','á‹®'=>'á‹®','ዯ'=>'ዯ','á‹°'=>'á‹°','ዱ'=>'ዱ','ዲ'=>'ዲ','ዳ'=>'ዳ','á‹´'=>'á‹´','ድ'=>'ድ','á‹¶'=>'á‹¶','á‹·'=>'á‹·','ዸ'=>'ዸ','ዹ'=>'ዹ','ዺ'=>'ዺ','á‹»'=>'á‹»','ዼ'=>'ዼ','ዽ'=>'ዽ','ዾ'=>'ዾ','á‹¿'=>'á‹¿','ጀ'=>'ጀ','áŒ'=>'áŒ','ጂ'=>'ጂ','ጃ'=>'ጃ','ጄ'=>'ጄ','ጅ'=>'ጅ','ጆ'=>'ጆ','ጇ'=>'ጇ','ገ'=>'ገ','ጉ'=>'ጉ','ጊ'=>'ጊ','ጋ'=>'ጋ','ጌ'=>'ጌ','áŒ'=>'áŒ','ጎ'=>'ጎ','áŒ'=>'áŒ','áŒ'=>'áŒ','ጒ'=>'ጒ','ጓ'=>'ጓ','ጔ'=>'ጔ','ጕ'=>'ጕ','ጘ'=>'ጘ','ጙ'=>'ጙ','ጚ'=>'ጚ','ጛ'=>'ጛ','ጜ'=>'ጜ','áŒ'=>'áŒ','ጞ'=>'ጞ','ጟ'=>'ጟ','ጠ'=>'ጠ','ጡ'=>'ጡ','ጢ'=>'ጢ','ጣ'=>'ጣ','ጤ'=>'ጤ','ጥ'=>'ጥ','ጦ'=>'ጦ','ጧ'=>'ጧ','ጨ'=>'ጨ','ጩ'=>'ጩ','ጪ'=>'ጪ','ጫ'=>'ጫ','ጬ'=>'ጬ','áŒ'=>'áŒ','ጮ'=>'ጮ','ጯ'=>'ጯ','ጰ'=>'ጰ','ጱ'=>'ጱ','ጲ'=>'ጲ','ጳ'=>'ጳ','ጴ'=>'ጴ','ጵ'=>'ጵ','ጶ'=>'ጶ','ጷ'=>'ጷ','ጸ'=>'ጸ','ጹ'=>'ጹ','ጺ'=>'ጺ','ጻ'=>'ጻ','ጼ'=>'ጼ','ጽ'=>'ጽ','ጾ'=>'ጾ','ጿ'=>'ጿ','á€'=>'á€','á'=>'á','á‚'=>'á‚','áƒ'=>'áƒ','á„'=>'á„','á…'=>'á…','á†'=>'á†','á‡'=>'á‡','áˆ'=>'áˆ','á‰'=>'á‰','áŠ'=>'áŠ','á‹'=>'á‹','áŒ'=>'áŒ','á'=>'á','áŽ'=>'áŽ','á'=>'á','á'=>'á','á‘'=>'á‘','á’'=>'á’','á“'=>'á“','á”'=>'á”','á•'=>'á•','á–'=>'á–','á—'=>'á—','á˜'=>'á˜','á™'=>'á™','áš'=>'áš','áŸ'=>'áŸ','á©'=>'1','áª'=>'2','á«'=>'3','á¬'=>'4','á'=>'5','á®'=>'6','á¯'=>'7','á°'=>'8','á±'=>'9','á²'=>'10','á³'=>'20','á´'=>'30','áµ'=>'40','á¶'=>'50','á·'=>'60','á¸'=>'70','á¹'=>'80','áº'=>'90','á»'=>'100','á¼'=>'10000','ᎀ'=>'ᎀ','áŽ'=>'áŽ','ᎂ'=>'ᎂ','ᎃ'=>'ᎃ','ᎄ'=>'ᎄ','ᎅ'=>'ᎅ','ᎆ'=>'ᎆ','ᎇ'=>'ᎇ','ᎈ'=>'ᎈ','ᎉ'=>'ᎉ','ᎊ'=>'ᎊ','ᎋ'=>'ᎋ','ᎌ'=>'ᎌ','áŽ'=>'áŽ','ᎎ'=>'ᎎ','áŽ'=>'áŽ','Ꭰ'=>'Ꭰ','Ꭱ'=>'Ꭱ','Ꭲ'=>'Ꭲ','Ꭳ'=>'Ꭳ','Ꭴ'=>'Ꭴ','Ꭵ'=>'Ꭵ','Ꭶ'=>'Ꭶ','Ꭷ'=>'Ꭷ','Ꭸ'=>'Ꭸ','Ꭹ'=>'Ꭹ','Ꭺ'=>'Ꭺ','Ꭻ'=>'Ꭻ','Ꭼ'=>'Ꭼ','áŽ'=>'áŽ','Ꭾ'=>'Ꭾ','Ꭿ'=>'Ꭿ','Ꮀ'=>'Ꮀ','Ꮁ'=>'Ꮁ','Ꮂ'=>'Ꮂ','Ꮃ'=>'Ꮃ','Ꮄ'=>'Ꮄ','Ꮅ'=>'Ꮅ','Ꮆ'=>'Ꮆ','Ꮇ'=>'Ꮇ','Ꮈ'=>'Ꮈ','Ꮉ'=>'Ꮉ','Ꮊ'=>'Ꮊ','Ꮋ'=>'Ꮋ','Ꮌ'=>'Ꮌ','Ꮍ'=>'Ꮍ','Ꮎ'=>'Ꮎ','Ꮏ'=>'Ꮏ','á€'=>'á€','á'=>'á','á‚'=>'á‚','áƒ'=>'áƒ','á„'=>'á„','á…'=>'á…','á†'=>'á†','á‡'=>'á‡','áˆ'=>'áˆ','á‰'=>'á‰','áŠ'=>'áŠ','á‹'=>'á‹','áŒ'=>'áŒ','á'=>'á','áŽ'=>'áŽ','á'=>'á','á'=>'á','á‘'=>'á‘','á’'=>'á’','á“'=>'á“','á”'=>'á”','á•'=>'á•','á–'=>'á–','á—'=>'á—','á˜'=>'á˜','á™'=>'á™','áš'=>'áš','á›'=>'á›','áœ'=>'áœ','á'=>'á','áž'=>'áž','áŸ'=>'áŸ','á '=>'á ','á¡'=>'á¡','á¢'=>'á¢','á£'=>'á£','á¤'=>'á¤','á¥'=>'á¥','á¦'=>'á¦','á§'=>'á§','á¨'=>'á¨','á©'=>'á©','áª'=>'áª','á«'=>'á«','á¬'=>'á¬','á'=>'á','á®'=>'á®','á¯'=>'á¯','á°'=>'á°','á±'=>'á±','á²'=>'á²','á³'=>'á³','á´'=>'á´','á'=>'á','á‚'=>'á‚','áƒ'=>'áƒ','á„'=>'á„','á…'=>'á…','á†'=>'á†','á‡'=>'á‡','áˆ'=>'áˆ','á‰'=>'á‰','áŠ'=>'áŠ','á‹'=>'á‹','áŒ'=>'áŒ','á'=>'á','áŽ'=>'áŽ','á'=>'á','á'=>'á','á‘'=>'á‘','á’'=>'á’','á“'=>'á“','á”'=>'á”','á•'=>'á•','á–'=>'á–','á—'=>'á—','á˜'=>'á˜','á™'=>'á™','áš'=>'áš','á›'=>'á›','áœ'=>'áœ','á'=>'á','áž'=>'áž','áŸ'=>'áŸ','á '=>'á ','á¡'=>'á¡','á¢'=>'á¢','á£'=>'á£','á¤'=>'á¤','á¥'=>'á¥','á¦'=>'á¦','á§'=>'á§','á¨'=>'á¨','á©'=>'á©','áª'=>'áª','á«'=>'á«','á¬'=>'á¬','á'=>'á','á®'=>'á®','á¯'=>'á¯','á°'=>'á°','á±'=>'á±','á²'=>'á²','á³'=>'á³','á´'=>'á´','áµ'=>'áµ','á¶'=>'á¶','á·'=>'á·','á¸'=>'á¸','á¹'=>'á¹','áº'=>'áº','á»'=>'á»','á¼'=>'á¼','á½'=>'á½','á¾'=>'á¾','á¿'=>'á¿','á‘€'=>'á‘€','á‘'=>'á‘','á‘‚'=>'á‘‚','ᑃ'=>'ᑃ','á‘„'=>'á‘„','á‘…'=>'á‘…','ᑆ'=>'ᑆ','ᑇ'=>'ᑇ','ᑈ'=>'ᑈ','ᑉ'=>'ᑉ','ᑊ'=>'ᑊ','á‘‹'=>'á‘‹','ᑌ'=>'ᑌ','á‘'=>'á‘','ᑎ'=>'ᑎ','á‘'=>'á‘','á‘'=>'á‘','á‘‘'=>'á‘‘','á‘’'=>'á‘’','á‘“'=>'á‘“','á‘”'=>'á‘”','á‘•'=>'á‘•','á‘–'=>'á‘–','á‘—'=>'á‘—','ᑘ'=>'ᑘ','á‘™'=>'á‘™','ᑚ'=>'ᑚ','á‘›'=>'á‘›','ᑜ'=>'ᑜ','á‘'=>'á‘','ᑞ'=>'ᑞ','ᑟ'=>'ᑟ','á‘ '=>'á‘ ','á‘¡'=>'á‘¡','á‘¢'=>'á‘¢','á‘£'=>'á‘£','ᑤ'=>'ᑤ','á‘¥'=>'á‘¥','ᑦ'=>'ᑦ','á‘§'=>'á‘§','ᑨ'=>'ᑨ','á‘©'=>'á‘©','ᑪ'=>'ᑪ','á‘«'=>'á‘«','ᑬ'=>'ᑬ','á‘'=>'á‘','á‘®'=>'á‘®','ᑯ'=>'ᑯ','á‘°'=>'á‘°','ᑱ'=>'ᑱ','ᑲ'=>'ᑲ','ᑳ'=>'ᑳ','á‘´'=>'á‘´','ᑵ'=>'ᑵ','á‘¶'=>'á‘¶','á‘·'=>'á‘·','ᑸ'=>'ᑸ','ᑹ'=>'ᑹ','ᑺ'=>'ᑺ','á‘»'=>'á‘»','ᑼ'=>'ᑼ','ᑽ'=>'ᑽ','ᑾ'=>'ᑾ','á‘¿'=>'á‘¿','á’€'=>'á’€','á’'=>'á’','á’‚'=>'á’‚','á’ƒ'=>'á’ƒ','á’„'=>'á’„','á’…'=>'á’…','á’†'=>'á’†','á’‡'=>'á’‡','á’ˆ'=>'á’ˆ','á’‰'=>'á’‰','á’Š'=>'á’Š','á’‹'=>'á’‹','á’Œ'=>'á’Œ','á’'=>'á’','á’Ž'=>'á’Ž','á’'=>'á’','á’'=>'á’','á’‘'=>'á’‘','á’’'=>'á’’','á’“'=>'á’“','á’”'=>'á’”','á’•'=>'á’•','á’–'=>'á’–','á’—'=>'á’—','á’˜'=>'á’˜','á’™'=>'á’™','á’š'=>'á’š','á’›'=>'á’›','á’œ'=>'á’œ','á’'=>'á’','á’ž'=>'á’ž','á’Ÿ'=>'á’Ÿ','á’ '=>'á’ ','á’¡'=>'á’¡','á’¢'=>'á’¢','á’£'=>'á’£','á’¤'=>'á’¤','á’¥'=>'á’¥','á’¦'=>'á’¦','á’§'=>'á’§','á’¨'=>'á’¨','á’©'=>'á’©','á’ª'=>'á’ª','á’«'=>'á’«','á’¬'=>'á’¬','á’'=>'á’','á’®'=>'á’®','á’¯'=>'á’¯','á’°'=>'á’°','á’±'=>'á’±','á’²'=>'á’²','á’³'=>'á’³','á’´'=>'á’´','á’µ'=>'á’µ','á’¶'=>'á’¶','á’·'=>'á’·','á’¸'=>'á’¸','á’¹'=>'á’¹','á’º'=>'á’º','á’»'=>'á’»','á’¼'=>'á’¼','á’½'=>'á’½','á’¾'=>'á’¾','á’¿'=>'á’¿','á“€'=>'á“€','á“'=>'á“','á“‚'=>'á“‚','ᓃ'=>'ᓃ','á“„'=>'á“„','á“…'=>'á“…','ᓆ'=>'ᓆ','ᓇ'=>'ᓇ','ᓈ'=>'ᓈ','ᓉ'=>'ᓉ','ᓊ'=>'ᓊ','á“‹'=>'á“‹','ᓌ'=>'ᓌ','á“'=>'á“','ᓎ'=>'ᓎ','á“'=>'á“','á“'=>'á“','á“‘'=>'á“‘','á“’'=>'á“’','á““'=>'á““','á“”'=>'á“”','á“•'=>'á“•','á“–'=>'á“–','á“—'=>'á“—','ᓘ'=>'ᓘ','á“™'=>'á“™','ᓚ'=>'ᓚ','á“›'=>'á“›','ᓜ'=>'ᓜ','á“'=>'á“','ᓞ'=>'ᓞ','ᓟ'=>'ᓟ','á“ '=>'á“ ','á“¡'=>'á“¡','á“¢'=>'á“¢','á“£'=>'á“£','ᓤ'=>'ᓤ','á“¥'=>'á“¥','ᓦ'=>'ᓦ','á“§'=>'á“§','ᓨ'=>'ᓨ','á“©'=>'á“©','ᓪ'=>'ᓪ','á“«'=>'á“«','ᓬ'=>'ᓬ','á“'=>'á“','á“®'=>'á“®','ᓯ'=>'ᓯ','á“°'=>'á“°','ᓱ'=>'ᓱ','ᓲ'=>'ᓲ','ᓳ'=>'ᓳ','á“´'=>'á“´','ᓵ'=>'ᓵ','á“¶'=>'á“¶','á“·'=>'á“·','ᓸ'=>'ᓸ','ᓹ'=>'ᓹ','ᓺ'=>'ᓺ','á“»'=>'á“»','ᓼ'=>'ᓼ','ᓽ'=>'ᓽ','ᓾ'=>'ᓾ','á“¿'=>'á“¿','ᔀ'=>'ᔀ','á”'=>'á”','ᔂ'=>'ᔂ','ᔃ'=>'ᔃ','ᔄ'=>'ᔄ','á”…'=>'á”…','ᔆ'=>'ᔆ','ᔇ'=>'ᔇ','ᔈ'=>'ᔈ','ᔉ'=>'ᔉ','ᔊ'=>'ᔊ','ᔋ'=>'ᔋ','ᔌ'=>'ᔌ','á”'=>'á”','ᔎ'=>'ᔎ','á”'=>'á”','á”'=>'á”','ᔑ'=>'ᔑ','á”’'=>'á”’','ᔓ'=>'ᔓ','á””'=>'á””','ᔕ'=>'ᔕ','á”–'=>'á”–','á”—'=>'á”—','ᔘ'=>'ᔘ','á”™'=>'á”™','ᔚ'=>'ᔚ','á”›'=>'á”›','ᔜ'=>'ᔜ','á”'=>'á”','ᔞ'=>'ᔞ','ᔟ'=>'ᔟ','á” '=>'á” ','ᔡ'=>'ᔡ','ᔢ'=>'ᔢ','ᔣ'=>'ᔣ','ᔤ'=>'ᔤ','ᔥ'=>'ᔥ','ᔦ'=>'ᔦ','á”§'=>'á”§','ᔨ'=>'ᔨ','ᔩ'=>'ᔩ','ᔪ'=>'ᔪ','ᔫ'=>'ᔫ','ᔬ'=>'ᔬ','á”'=>'á”','á”®'=>'á”®','ᔯ'=>'ᔯ','á”°'=>'á”°','á”±'=>'á”±','ᔲ'=>'ᔲ','ᔳ'=>'ᔳ','á”´'=>'á”´','ᔵ'=>'ᔵ','á”¶'=>'á”¶','á”·'=>'á”·','ᔸ'=>'ᔸ','ᔹ'=>'ᔹ','ᔺ'=>'ᔺ','á”»'=>'á”»','ᔼ'=>'ᔼ','ᔽ'=>'ᔽ','ᔾ'=>'ᔾ','ᔿ'=>'ᔿ','á•€'=>'á•€','á•'=>'á•','á•‚'=>'á•‚','ᕃ'=>'ᕃ','á•„'=>'á•„','á•…'=>'á•…','ᕆ'=>'ᕆ','ᕇ'=>'ᕇ','ᕈ'=>'ᕈ','ᕉ'=>'ᕉ','ᕊ'=>'ᕊ','á•‹'=>'á•‹','ᕌ'=>'ᕌ','á•'=>'á•','ᕎ'=>'ᕎ','á•'=>'á•','á•'=>'á•','á•‘'=>'á•‘','á•’'=>'á•’','á•“'=>'á•“','á•”'=>'á•”','á••'=>'á••','á•–'=>'á•–','á•—'=>'á•—','ᕘ'=>'ᕘ','á•™'=>'á•™','ᕚ'=>'ᕚ','á•›'=>'á•›','ᕜ'=>'ᕜ','á•'=>'á•','ᕞ'=>'ᕞ','ᕟ'=>'ᕟ','á• '=>'á• ','á•¡'=>'á•¡','á•¢'=>'á•¢','á•£'=>'á•£','ᕤ'=>'ᕤ','á•¥'=>'á•¥','ᕦ'=>'ᕦ','á•§'=>'á•§','ᕨ'=>'ᕨ','á•©'=>'á•©','ᕪ'=>'ᕪ','á•«'=>'á•«','ᕬ'=>'ᕬ','á•'=>'á•','á•®'=>'á•®','ᕯ'=>'ᕯ','á•°'=>'á•°','ᕱ'=>'ᕱ','ᕲ'=>'ᕲ','ᕳ'=>'ᕳ','á•´'=>'á•´','ᕵ'=>'ᕵ','á•¶'=>'á•¶','á•·'=>'á•·','ᕸ'=>'ᕸ','ᕹ'=>'ᕹ','ᕺ'=>'ᕺ','á•»'=>'á•»','ᕼ'=>'ᕼ','ᕽ'=>'ᕽ','ᕾ'=>'ᕾ','á•¿'=>'á•¿','á–€'=>'á–€','á–'=>'á–','á–‚'=>'á–‚','á–ƒ'=>'á–ƒ','á–„'=>'á–„','á–…'=>'á–…','á–†'=>'á–†','á–‡'=>'á–‡','á–ˆ'=>'á–ˆ','á–‰'=>'á–‰','á–Š'=>'á–Š','á–‹'=>'á–‹','á–Œ'=>'á–Œ','á–'=>'á–','á–Ž'=>'á–Ž','á–'=>'á–','á–'=>'á–','á–‘'=>'á–‘','á–’'=>'á–’','á–“'=>'á–“','á–”'=>'á–”','á–•'=>'á–•','á––'=>'á––','á–—'=>'á–—','á–˜'=>'á–˜','á–™'=>'á–™','á–š'=>'á–š','á–›'=>'á–›','á–œ'=>'á–œ','á–'=>'á–','á–ž'=>'á–ž','á–Ÿ'=>'á–Ÿ','á– '=>'á– ','á–¡'=>'á–¡','á–¢'=>'á–¢','á–£'=>'á–£','á–¤'=>'á–¤','á–¥'=>'á–¥','á–¦'=>'á–¦','á–§'=>'á–§','á–¨'=>'á–¨','á–©'=>'á–©','á–ª'=>'á–ª','á–«'=>'á–«','á–¬'=>'á–¬','á–'=>'á–','á–®'=>'á–®','á–¯'=>'á–¯','á–°'=>'á–°','á–±'=>'á–±','á–²'=>'á–²','á–³'=>'á–³','á–´'=>'á–´','á–µ'=>'á–µ','á–¶'=>'á–¶','á–·'=>'á–·','á–¸'=>'á–¸','á–¹'=>'á–¹','á–º'=>'á–º','á–»'=>'á–»','á–¼'=>'á–¼','á–½'=>'á–½','á–¾'=>'á–¾','á–¿'=>'á–¿','á—€'=>'á—€','á—'=>'á—','á—‚'=>'á—‚','á—ƒ'=>'á—ƒ','á—„'=>'á—„','á—…'=>'á—…','á—†'=>'á—†','á—‡'=>'á—‡','á—ˆ'=>'á—ˆ','á—‰'=>'á—‰','á—Š'=>'á—Š','á—‹'=>'á—‹','á—Œ'=>'á—Œ','á—'=>'á—','á—Ž'=>'á—Ž','á—'=>'á—','á—'=>'á—','á—‘'=>'á—‘','á—’'=>'á—’','á—“'=>'á—“','á—”'=>'á—”','á—•'=>'á—•','á—–'=>'á—–','á——'=>'á——','á—˜'=>'á—˜','á—™'=>'á—™','á—š'=>'á—š','á—›'=>'á—›','á—œ'=>'á—œ','á—'=>'á—','á—ž'=>'á—ž','á—Ÿ'=>'á—Ÿ','á— '=>'á— ','á—¡'=>'á—¡','á—¢'=>'á—¢','á—£'=>'á—£','á—¤'=>'á—¤','á—¥'=>'á—¥','á—¦'=>'á—¦','á—§'=>'á—§','á—¨'=>'á—¨','á—©'=>'á—©','á—ª'=>'á—ª','á—«'=>'á—«','á—¬'=>'á—¬','á—'=>'á—','á—®'=>'á—®','á—¯'=>'á—¯','á—°'=>'á—°','á—±'=>'á—±','á—²'=>'á—²','á—³'=>'á—³','á—´'=>'á—´','á—µ'=>'á—µ','á—¶'=>'á—¶','á—·'=>'á—·','á—¸'=>'á—¸','á—¹'=>'á—¹','á—º'=>'á—º','á—»'=>'á—»','á—¼'=>'á—¼','á—½'=>'á—½','á—¾'=>'á—¾','á—¿'=>'á—¿','ᘀ'=>'ᘀ','á˜'=>'á˜','ᘂ'=>'ᘂ','ᘃ'=>'ᘃ','ᘄ'=>'ᘄ','ᘅ'=>'ᘅ','ᘆ'=>'ᘆ','ᘇ'=>'ᘇ','ᘈ'=>'ᘈ','ᘉ'=>'ᘉ','ᘊ'=>'ᘊ','ᘋ'=>'ᘋ','ᘌ'=>'ᘌ','á˜'=>'á˜','ᘎ'=>'ᘎ','á˜'=>'á˜','á˜'=>'á˜','ᘑ'=>'ᘑ','ᘒ'=>'ᘒ','ᘓ'=>'ᘓ','ᘔ'=>'ᘔ','ᘕ'=>'ᘕ','ᘖ'=>'ᘖ','ᘗ'=>'ᘗ','ᘘ'=>'ᘘ','ᘙ'=>'ᘙ','ᘚ'=>'ᘚ','ᘛ'=>'ᘛ','ᘜ'=>'ᘜ','á˜'=>'á˜','ᘞ'=>'ᘞ','ᘟ'=>'ᘟ','ᘠ'=>'ᘠ','ᘡ'=>'ᘡ','ᘢ'=>'ᘢ','ᘣ'=>'ᘣ','ᘤ'=>'ᘤ','ᘥ'=>'ᘥ','ᘦ'=>'ᘦ','ᘧ'=>'ᘧ','ᘨ'=>'ᘨ','ᘩ'=>'ᘩ','ᘪ'=>'ᘪ','ᘫ'=>'ᘫ','ᘬ'=>'ᘬ','á˜'=>'á˜','ᘮ'=>'ᘮ','ᘯ'=>'ᘯ','ᘰ'=>'ᘰ','ᘱ'=>'ᘱ','ᘲ'=>'ᘲ','ᘳ'=>'ᘳ','ᘴ'=>'ᘴ','ᘵ'=>'ᘵ','ᘶ'=>'ᘶ','ᘷ'=>'ᘷ','ᘸ'=>'ᘸ','ᘹ'=>'ᘹ','ᘺ'=>'ᘺ','ᘻ'=>'ᘻ','ᘼ'=>'ᘼ','ᘽ'=>'ᘽ','ᘾ'=>'ᘾ','ᘿ'=>'ᘿ','ᙀ'=>'ᙀ','á™'=>'á™','ᙂ'=>'ᙂ','ᙃ'=>'ᙃ','ᙄ'=>'ᙄ','á™…'=>'á™…','ᙆ'=>'ᙆ','ᙇ'=>'ᙇ','ᙈ'=>'ᙈ','ᙉ'=>'ᙉ','ᙊ'=>'ᙊ','ᙋ'=>'ᙋ','ᙌ'=>'ᙌ','á™'=>'á™','ᙎ'=>'ᙎ','á™'=>'á™','á™'=>'á™','ᙑ'=>'ᙑ','á™’'=>'á™’','ᙓ'=>'ᙓ','á™”'=>'á™”','ᙕ'=>'ᙕ','á™–'=>'á™–','á™—'=>'á™—','ᙘ'=>'ᙘ','á™™'=>'á™™','ᙚ'=>'ᙚ','á™›'=>'á™›','ᙜ'=>'ᙜ','á™'=>'á™','ᙞ'=>'ᙞ','ᙟ'=>'ᙟ','á™ '=>'á™ ','ᙡ'=>'ᙡ','ᙢ'=>'ᙢ','ᙣ'=>'ᙣ','ᙤ'=>'ᙤ','ᙥ'=>'ᙥ','ᙦ'=>'ᙦ','á™§'=>'á™§','ᙨ'=>'ᙨ','ᙩ'=>'ᙩ','ᙪ'=>'ᙪ','ᙫ'=>'ᙫ','ᙬ'=>'ᙬ','ᙯ'=>'ᙯ','á™°'=>'á™°','á™±'=>'á™±','ᙲ'=>'ᙲ','ᙳ'=>'ᙳ','á™´'=>'á™´','ᙵ'=>'ᙵ','á™¶'=>'á™¶','áš'=>'áš','áš‚'=>'áš‚','ᚃ'=>'ᚃ','áš„'=>'áš„','áš…'=>'áš…','ᚆ'=>'ᚆ','ᚇ'=>'ᚇ','ᚈ'=>'ᚈ','ᚉ'=>'ᚉ','ᚊ'=>'ᚊ','áš‹'=>'áš‹','ᚌ'=>'ᚌ','áš'=>'áš','ᚎ'=>'ᚎ','áš'=>'áš','áš'=>'áš','áš‘'=>'áš‘','áš’'=>'áš’','áš“'=>'áš“','áš”'=>'áš”','áš•'=>'áš•','áš–'=>'áš–','áš—'=>'áš—','ᚘ'=>'ᚘ','áš™'=>'áš™','ášš'=>'ášš','áš '=>'áš ','áš¡'=>'áš¡','ᚢ'=>'ᚢ','ᚣ'=>'ᚣ','ᚤ'=>'ᚤ','ᚥ'=>'ᚥ','ᚦ'=>'ᚦ','áš§'=>'áš§','ᚨ'=>'ᚨ','áš©'=>'áš©','ᚪ'=>'ᚪ','áš«'=>'áš«','ᚬ'=>'ᚬ','áš'=>'áš','áš®'=>'áš®','ᚯ'=>'ᚯ','áš°'=>'áš°','áš±'=>'áš±','áš²'=>'áš²','áš³'=>'áš³','áš´'=>'áš´','ášµ'=>'ášµ','áš¶'=>'áš¶','áš·'=>'áš·','ᚸ'=>'ᚸ','áš¹'=>'áš¹','ᚺ'=>'ᚺ','áš»'=>'áš»','áš¼'=>'áš¼','áš½'=>'áš½','áš¾'=>'áš¾','áš¿'=>'áš¿','ᛀ'=>'ᛀ','á›'=>'á›','ᛂ'=>'ᛂ','ᛃ'=>'ᛃ','ᛄ'=>'ᛄ','á›…'=>'á›…','ᛆ'=>'ᛆ','ᛇ'=>'ᛇ','ᛈ'=>'ᛈ','ᛉ'=>'ᛉ','ᛊ'=>'ᛊ','ᛋ'=>'ᛋ','ᛌ'=>'ᛌ','á›'=>'á›','ᛎ'=>'ᛎ','á›'=>'á›','á›'=>'á›','ᛑ'=>'ᛑ','á›’'=>'á›’','ᛓ'=>'ᛓ','á›”'=>'á›”','ᛕ'=>'ᛕ','á›–'=>'á›–','á›—'=>'á›—','ᛘ'=>'ᛘ','á›™'=>'á›™','ᛚ'=>'ᛚ','á››'=>'á››','ᛜ'=>'ᛜ','á›'=>'á›','ᛞ'=>'ᛞ','ᛟ'=>'ᛟ','á› '=>'á› ','ᛡ'=>'ᛡ','ᛢ'=>'ᛢ','ᛣ'=>'ᛣ','ᛤ'=>'ᛤ','ᛥ'=>'ᛥ','ᛦ'=>'ᛦ','á›§'=>'á›§','ᛨ'=>'ᛨ','ᛩ'=>'ᛩ','ᛪ'=>'ᛪ','á›®'=>'17','ᛯ'=>'18','á›°'=>'19','ᜀ'=>'ᜀ','áœ'=>'áœ','ᜂ'=>'ᜂ','ᜃ'=>'ᜃ','ᜄ'=>'ᜄ','ᜅ'=>'ᜅ','ᜆ'=>'ᜆ','ᜇ'=>'ᜇ','ᜈ'=>'ᜈ','ᜉ'=>'ᜉ','ᜊ'=>'ᜊ','ᜋ'=>'ᜋ','ᜌ'=>'ᜌ','ᜎ'=>'ᜎ','áœ'=>'áœ','áœ'=>'áœ','ᜑ'=>'ᜑ','ᜒ'=>'ᜒ','ᜓ'=>'ᜓ','᜔'=>'᜔','ᜠ'=>'ᜠ','ᜡ'=>'ᜡ','ᜢ'=>'ᜢ','ᜣ'=>'ᜣ','ᜤ'=>'ᜤ','ᜥ'=>'ᜥ','ᜦ'=>'ᜦ','ᜧ'=>'ᜧ','ᜨ'=>'ᜨ','ᜩ'=>'ᜩ','ᜪ'=>'ᜪ','ᜫ'=>'ᜫ','ᜬ'=>'ᜬ','áœ'=>'áœ','ᜮ'=>'ᜮ','ᜯ'=>'ᜯ','ᜰ'=>'ᜰ','ᜱ'=>'ᜱ','ᜲ'=>'ᜲ','ᜳ'=>'ᜳ','᜴'=>'᜴','á€'=>'á€','á'=>'á','á‚'=>'á‚','áƒ'=>'áƒ','á„'=>'á„','á…'=>'á…','á†'=>'á†','á‡'=>'á‡','áˆ'=>'áˆ','á‰'=>'á‰','áŠ'=>'áŠ','á‹'=>'á‹','áŒ'=>'áŒ','á'=>'á','áŽ'=>'áŽ','á'=>'á','á'=>'á','á‘'=>'á‘','á’'=>'á’','á“'=>'á“','á '=>'á ','á¡'=>'á¡','á¢'=>'á¢','á£'=>'á£','á¤'=>'á¤','á¥'=>'á¥','á¦'=>'á¦','á§'=>'á§','á¨'=>'á¨','á©'=>'á©','áª'=>'áª','á«'=>'á«','á¬'=>'á¬','á®'=>'á®','á¯'=>'á¯','á°'=>'á°','á²'=>'á²','á³'=>'á³','ក'=>'ក','áž'=>'áž','áž‚'=>'áž‚','ឃ'=>'ឃ','áž„'=>'áž„','áž…'=>'áž…','ឆ'=>'ឆ','ជ'=>'ជ','ឈ'=>'ឈ','ញ'=>'ញ','ដ'=>'ដ','áž‹'=>'áž‹','ឌ'=>'ឌ','áž'=>'áž','ណ'=>'ណ','áž'=>'áž','áž'=>'áž','áž‘'=>'áž‘','áž’'=>'áž’','áž“'=>'áž“','áž”'=>'áž”','áž•'=>'áž•','áž–'=>'áž–','áž—'=>'áž—','ម'=>'ម','áž™'=>'áž™','ážš'=>'ážš','áž›'=>'áž›','ážœ'=>'ážœ','áž'=>'áž','ážž'=>'ážž','ស'=>'ស','áž '=>'áž ','áž¡'=>'áž¡','អ'=>'អ','ឣ'=>'ឣ','ឤ'=>'ឤ','ឥ'=>'ឥ','ឦ'=>'ឦ','áž§'=>'áž§','ឨ'=>'ឨ','áž©'=>'áž©','ឪ'=>'ឪ','áž«'=>'áž«','ឬ'=>'ឬ','áž'=>'áž','áž®'=>'áž®','ឯ'=>'ឯ','áž°'=>'áž°','áž±'=>'áž±','áž²'=>'áž²','áž³'=>'áž³','áž¶'=>'áž¶','áž·'=>'áž·','ី'=>'ី','áž¹'=>'áž¹','ឺ'=>'ឺ','áž»'=>'áž»','áž¼'=>'áž¼','áž½'=>'áž½','áž¾'=>'áž¾','áž¿'=>'áž¿','ៀ'=>'ៀ','áŸ'=>'áŸ','ែ'=>'ែ','ៃ'=>'ៃ','ោ'=>'ោ','ៅ'=>'ៅ','ំ'=>'ំ','ះ'=>'ះ','ៈ'=>'ៈ','៉'=>'៉','៊'=>'៊','់'=>'់','៌'=>'៌','áŸ'=>'áŸ','៎'=>'៎','áŸ'=>'áŸ','áŸ'=>'áŸ','៑'=>'៑','្'=>'្','៓'=>'៓','ៗ'=>'ៗ','ៜ'=>'ៜ','áŸ'=>'áŸ','០'=>'0','១'=>'1','២'=>'2','៣'=>'3','៤'=>'4','៥'=>'5','៦'=>'6','៧'=>'7','៨'=>'8','៩'=>'9','៰'=>'0','៱'=>'1','៲'=>'2','៳'=>'3','៴'=>'4','៵'=>'5','៶'=>'6','៷'=>'7','៸'=>'8','៹'=>'9');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_20.php b/phpBB/includes/utf/data/search_indexer_20.php deleted file mode 100644 index caab3c540b..0000000000 --- a/phpBB/includes/utf/data/search_indexer_20.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('ꀀ'=>'ꀀ','ê€'=>'ê€','ꀂ'=>'ꀂ','ꀃ'=>'ꀃ','ꀄ'=>'ꀄ','ꀅ'=>'ꀅ','ꀆ'=>'ꀆ','ꀇ'=>'ꀇ','ꀈ'=>'ꀈ','ꀉ'=>'ꀉ','ꀊ'=>'ꀊ','ꀋ'=>'ꀋ','ꀌ'=>'ꀌ','ê€'=>'ê€','ꀎ'=>'ꀎ','ê€'=>'ê€','ê€'=>'ê€','ꀑ'=>'ꀑ','ꀒ'=>'ꀒ','ꀓ'=>'ꀓ','ꀔ'=>'ꀔ','ꀕ'=>'ꀕ','ꀖ'=>'ꀖ','ꀗ'=>'ꀗ','ꀘ'=>'ꀘ','ꀙ'=>'ꀙ','ꀚ'=>'ꀚ','ꀛ'=>'ꀛ','ꀜ'=>'ꀜ','ê€'=>'ê€','ꀞ'=>'ꀞ','ꀟ'=>'ꀟ','ê€ '=>'ê€ ','ꀡ'=>'ꀡ','ꀢ'=>'ꀢ','ꀣ'=>'ꀣ','ꀤ'=>'ꀤ','ꀥ'=>'ꀥ','ꀦ'=>'ꀦ','ꀧ'=>'ꀧ','ꀨ'=>'ꀨ','ꀩ'=>'ꀩ','ꀪ'=>'ꀪ','ꀫ'=>'ꀫ','ꀬ'=>'ꀬ','ê€'=>'ê€','ꀮ'=>'ꀮ','ꀯ'=>'ꀯ','ꀰ'=>'ꀰ','ꀱ'=>'ꀱ','ꀲ'=>'ꀲ','ꀳ'=>'ꀳ','ꀴ'=>'ꀴ','ꀵ'=>'ꀵ','ꀶ'=>'ꀶ','ꀷ'=>'ꀷ','ꀸ'=>'ꀸ','ꀹ'=>'ꀹ','ꀺ'=>'ꀺ','ꀻ'=>'ꀻ','ꀼ'=>'ꀼ','ꀽ'=>'ꀽ','ꀾ'=>'ꀾ','ꀿ'=>'ꀿ','ê€'=>'ê€','ê'=>'ê','ê‚'=>'ê‚','êƒ'=>'êƒ','ê„'=>'ê„','ê…'=>'ê…','ê†'=>'ê†','ê‡'=>'ê‡','êˆ'=>'êˆ','ê‰'=>'ê‰','êŠ'=>'êŠ','ê‹'=>'ê‹','êŒ'=>'êŒ','ê'=>'ê','êŽ'=>'êŽ','ê'=>'ê','ê'=>'ê','ê‘'=>'ê‘','ê’'=>'ê’','ê“'=>'ê“','ê”'=>'ê”','ê•'=>'ê•','ê–'=>'ê–','ê—'=>'ê—','ê˜'=>'ê˜','ê™'=>'ê™','êš'=>'êš','ê›'=>'ê›','êœ'=>'êœ','ê'=>'ê','êž'=>'êž','êŸ'=>'êŸ','ê '=>'ê ','ê¡'=>'ê¡','ê¢'=>'ê¢','ê£'=>'ê£','ê¤'=>'ê¤','ê¥'=>'ê¥','ê¦'=>'ê¦','ê§'=>'ê§','ê¨'=>'ê¨','ê©'=>'ê©','êª'=>'êª','ê«'=>'ê«','ê¬'=>'ê¬','ê'=>'ê','ê®'=>'ê®','ê¯'=>'ê¯','ê°'=>'ê°','ê±'=>'ê±','ê²'=>'ê²','ê³'=>'ê³','ê´'=>'ê´','êµ'=>'êµ','ê¶'=>'ê¶','ê·'=>'ê·','ê¸'=>'ê¸','ê¹'=>'ê¹','êº'=>'êº','ê»'=>'ê»','ê¼'=>'ê¼','ê½'=>'ê½','ê¾'=>'ê¾','ê¿'=>'ê¿','ê‚€'=>'ê‚€','ê‚'=>'ê‚','ê‚‚'=>'ê‚‚','ꂃ'=>'ꂃ','ê‚„'=>'ê‚„','ê‚…'=>'ê‚…','ꂆ'=>'ꂆ','ꂇ'=>'ꂇ','ꂈ'=>'ꂈ','ꂉ'=>'ꂉ','ꂊ'=>'ꂊ','ê‚‹'=>'ê‚‹','ꂌ'=>'ꂌ','ê‚'=>'ê‚','ꂎ'=>'ꂎ','ê‚'=>'ê‚','ê‚'=>'ê‚','ê‚‘'=>'ê‚‘','ê‚’'=>'ê‚’','ê‚“'=>'ê‚“','ê‚”'=>'ê‚”','ê‚•'=>'ê‚•','ê‚–'=>'ê‚–','ê‚—'=>'ê‚—','ꂘ'=>'ꂘ','ê‚™'=>'ê‚™','ꂚ'=>'ꂚ','ê‚›'=>'ê‚›','ꂜ'=>'ꂜ','ê‚'=>'ê‚','ꂞ'=>'ꂞ','ꂟ'=>'ꂟ','ê‚ '=>'ê‚ ','ê‚¡'=>'ê‚¡','ê‚¢'=>'ê‚¢','ê‚£'=>'ê‚£','ꂤ'=>'ꂤ','ê‚¥'=>'ê‚¥','ꂦ'=>'ꂦ','ê‚§'=>'ê‚§','ꂨ'=>'ꂨ','ê‚©'=>'ê‚©','ꂪ'=>'ꂪ','ê‚«'=>'ê‚«','ꂬ'=>'ꂬ','ê‚'=>'ê‚','ê‚®'=>'ê‚®','ꂯ'=>'ꂯ','ê‚°'=>'ê‚°','ꂱ'=>'ꂱ','ꂲ'=>'ꂲ','ꂳ'=>'ꂳ','ê‚´'=>'ê‚´','ꂵ'=>'ꂵ','ê‚¶'=>'ê‚¶','ê‚·'=>'ê‚·','ꂸ'=>'ꂸ','ꂹ'=>'ꂹ','ꂺ'=>'ꂺ','ê‚»'=>'ê‚»','ꂼ'=>'ꂼ','ꂽ'=>'ꂽ','ꂾ'=>'ꂾ','ê‚¿'=>'ê‚¿','ꃀ'=>'ꃀ','êƒ'=>'êƒ','ꃂ'=>'ꃂ','ꃃ'=>'ꃃ','ꃄ'=>'ꃄ','ꃅ'=>'ꃅ','ꃆ'=>'ꃆ','ꃇ'=>'ꃇ','ꃈ'=>'ꃈ','ꃉ'=>'ꃉ','ꃊ'=>'ꃊ','ꃋ'=>'ꃋ','ꃌ'=>'ꃌ','êƒ'=>'êƒ','ꃎ'=>'ꃎ','êƒ'=>'êƒ','êƒ'=>'êƒ','ꃑ'=>'ꃑ','ꃒ'=>'ꃒ','ꃓ'=>'ꃓ','ꃔ'=>'ꃔ','ꃕ'=>'ꃕ','ꃖ'=>'ꃖ','ꃗ'=>'ꃗ','ꃘ'=>'ꃘ','ꃙ'=>'ꃙ','ꃚ'=>'ꃚ','ꃛ'=>'ꃛ','ꃜ'=>'ꃜ','êƒ'=>'êƒ','ꃞ'=>'ꃞ','ꃟ'=>'ꃟ','êƒ '=>'êƒ ','ꃡ'=>'ꃡ','ꃢ'=>'ꃢ','ꃣ'=>'ꃣ','ꃤ'=>'ꃤ','ꃥ'=>'ꃥ','ꃦ'=>'ꃦ','ꃧ'=>'ꃧ','ꃨ'=>'ꃨ','ꃩ'=>'ꃩ','ꃪ'=>'ꃪ','ꃫ'=>'ꃫ','ꃬ'=>'ꃬ','êƒ'=>'êƒ','ꃮ'=>'ꃮ','ꃯ'=>'ꃯ','ꃰ'=>'ꃰ','ꃱ'=>'ꃱ','ꃲ'=>'ꃲ','ꃳ'=>'ꃳ','ꃴ'=>'ꃴ','ꃵ'=>'ꃵ','ꃶ'=>'ꃶ','ꃷ'=>'ꃷ','ꃸ'=>'ꃸ','ꃹ'=>'ꃹ','ꃺ'=>'ꃺ','ꃻ'=>'ꃻ','ꃼ'=>'ꃼ','ꃽ'=>'ꃽ','ꃾ'=>'ꃾ','ꃿ'=>'ꃿ','ê„€'=>'ê„€','ê„'=>'ê„','ê„‚'=>'ê„‚','ꄃ'=>'ꄃ','ê„„'=>'ê„„','ê„…'=>'ê„…','ꄆ'=>'ꄆ','ꄇ'=>'ꄇ','ꄈ'=>'ꄈ','ꄉ'=>'ꄉ','ꄊ'=>'ꄊ','ê„‹'=>'ê„‹','ꄌ'=>'ꄌ','ê„'=>'ê„','ꄎ'=>'ꄎ','ê„'=>'ê„','ê„'=>'ê„','ê„‘'=>'ê„‘','ê„’'=>'ê„’','ê„“'=>'ê„“','ê„”'=>'ê„”','ê„•'=>'ê„•','ê„–'=>'ê„–','ê„—'=>'ê„—','ꄘ'=>'ꄘ','ê„™'=>'ê„™','ꄚ'=>'ꄚ','ê„›'=>'ê„›','ꄜ'=>'ꄜ','ê„'=>'ê„','ꄞ'=>'ꄞ','ꄟ'=>'ꄟ','ê„ '=>'ê„ ','ê„¡'=>'ê„¡','ê„¢'=>'ê„¢','ê„£'=>'ê„£','ꄤ'=>'ꄤ','ê„¥'=>'ê„¥','ꄦ'=>'ꄦ','ê„§'=>'ê„§','ꄨ'=>'ꄨ','ê„©'=>'ê„©','ꄪ'=>'ꄪ','ê„«'=>'ê„«','ꄬ'=>'ꄬ','ê„'=>'ê„','ê„®'=>'ê„®','ꄯ'=>'ꄯ','ê„°'=>'ê„°','ꄱ'=>'ꄱ','ꄲ'=>'ꄲ','ꄳ'=>'ꄳ','ê„´'=>'ê„´','ꄵ'=>'ꄵ','ê„¶'=>'ê„¶','ê„·'=>'ê„·','ꄸ'=>'ꄸ','ꄹ'=>'ꄹ','ꄺ'=>'ꄺ','ê„»'=>'ê„»','ꄼ'=>'ꄼ','ꄽ'=>'ꄽ','ꄾ'=>'ꄾ','ê„¿'=>'ê„¿','ê…€'=>'ê…€','ê…'=>'ê…','ê…‚'=>'ê…‚','ê…ƒ'=>'ê…ƒ','ê…„'=>'ê…„','ê……'=>'ê……','ê…†'=>'ê…†','ê…‡'=>'ê…‡','ê…ˆ'=>'ê…ˆ','ê…‰'=>'ê…‰','ê…Š'=>'ê…Š','ê…‹'=>'ê…‹','ê…Œ'=>'ê…Œ','ê…'=>'ê…','ê…Ž'=>'ê…Ž','ê…'=>'ê…','ê…'=>'ê…','ê…‘'=>'ê…‘','ê…’'=>'ê…’','ê…“'=>'ê…“','ê…”'=>'ê…”','ê…•'=>'ê…•','ê…–'=>'ê…–','ê…—'=>'ê…—','ê…˜'=>'ê…˜','ê…™'=>'ê…™','ê…š'=>'ê…š','ê…›'=>'ê…›','ê…œ'=>'ê…œ','ê…'=>'ê…','ê…ž'=>'ê…ž','ê…Ÿ'=>'ê…Ÿ','ê… '=>'ê… ','ê…¡'=>'ê…¡','ê…¢'=>'ê…¢','ê…£'=>'ê…£','ê…¤'=>'ê…¤','ê…¥'=>'ê…¥','ê…¦'=>'ê…¦','ê…§'=>'ê…§','ê…¨'=>'ê…¨','ê…©'=>'ê…©','ê…ª'=>'ê…ª','ê…«'=>'ê…«','ê…¬'=>'ê…¬','ê…'=>'ê…','ê…®'=>'ê…®','ê…¯'=>'ê…¯','ê…°'=>'ê…°','ê…±'=>'ê…±','ê…²'=>'ê…²','ê…³'=>'ê…³','ê…´'=>'ê…´','ê…µ'=>'ê…µ','ê…¶'=>'ê…¶','ê…·'=>'ê…·','ê…¸'=>'ê…¸','ê…¹'=>'ê…¹','ê…º'=>'ê…º','ê…»'=>'ê…»','ê…¼'=>'ê…¼','ê…½'=>'ê…½','ê…¾'=>'ê…¾','ê…¿'=>'ê…¿','ꆀ'=>'ꆀ','ê†'=>'ê†','ꆂ'=>'ꆂ','ꆃ'=>'ꆃ','ꆄ'=>'ꆄ','ꆅ'=>'ꆅ','ꆆ'=>'ꆆ','ꆇ'=>'ꆇ','ꆈ'=>'ꆈ','ꆉ'=>'ꆉ','ꆊ'=>'ꆊ','ꆋ'=>'ꆋ','ꆌ'=>'ꆌ','ê†'=>'ê†','ꆎ'=>'ꆎ','ê†'=>'ê†','ê†'=>'ê†','ꆑ'=>'ꆑ','ꆒ'=>'ꆒ','ꆓ'=>'ꆓ','ꆔ'=>'ꆔ','ꆕ'=>'ꆕ','ꆖ'=>'ꆖ','ꆗ'=>'ꆗ','ꆘ'=>'ꆘ','ꆙ'=>'ꆙ','ꆚ'=>'ꆚ','ꆛ'=>'ꆛ','ꆜ'=>'ꆜ','ê†'=>'ê†','ꆞ'=>'ꆞ','ꆟ'=>'ꆟ','ê† '=>'ê† ','ꆡ'=>'ꆡ','ꆢ'=>'ꆢ','ꆣ'=>'ꆣ','ꆤ'=>'ꆤ','ꆥ'=>'ꆥ','ꆦ'=>'ꆦ','ꆧ'=>'ꆧ','ꆨ'=>'ꆨ','ꆩ'=>'ꆩ','ꆪ'=>'ꆪ','ꆫ'=>'ꆫ','ꆬ'=>'ꆬ','ê†'=>'ê†','ꆮ'=>'ꆮ','ꆯ'=>'ꆯ','ꆰ'=>'ꆰ','ꆱ'=>'ꆱ','ꆲ'=>'ꆲ','ꆳ'=>'ꆳ','ꆴ'=>'ꆴ','ꆵ'=>'ꆵ','ꆶ'=>'ꆶ','ꆷ'=>'ꆷ','ꆸ'=>'ꆸ','ꆹ'=>'ꆹ','ꆺ'=>'ꆺ','ꆻ'=>'ꆻ','ꆼ'=>'ꆼ','ꆽ'=>'ꆽ','ꆾ'=>'ꆾ','ꆿ'=>'ꆿ','ꇀ'=>'ꇀ','ê‡'=>'ê‡','ꇂ'=>'ꇂ','ꇃ'=>'ꇃ','ꇄ'=>'ꇄ','ꇅ'=>'ꇅ','ꇆ'=>'ꇆ','ꇇ'=>'ꇇ','ꇈ'=>'ꇈ','ꇉ'=>'ꇉ','ꇊ'=>'ꇊ','ꇋ'=>'ꇋ','ꇌ'=>'ꇌ','ê‡'=>'ê‡','ꇎ'=>'ꇎ','ê‡'=>'ê‡','ê‡'=>'ê‡','ꇑ'=>'ꇑ','ꇒ'=>'ꇒ','ꇓ'=>'ꇓ','ꇔ'=>'ꇔ','ꇕ'=>'ꇕ','ꇖ'=>'ꇖ','ꇗ'=>'ꇗ','ꇘ'=>'ꇘ','ꇙ'=>'ꇙ','ꇚ'=>'ꇚ','ꇛ'=>'ꇛ','ꇜ'=>'ꇜ','ê‡'=>'ê‡','ꇞ'=>'ꇞ','ꇟ'=>'ꇟ','ê‡ '=>'ê‡ ','ꇡ'=>'ꇡ','ꇢ'=>'ꇢ','ꇣ'=>'ꇣ','ꇤ'=>'ꇤ','ꇥ'=>'ꇥ','ꇦ'=>'ꇦ','ꇧ'=>'ꇧ','ꇨ'=>'ꇨ','ꇩ'=>'ꇩ','ꇪ'=>'ꇪ','ꇫ'=>'ꇫ','ꇬ'=>'ꇬ','ê‡'=>'ê‡','ꇮ'=>'ꇮ','ꇯ'=>'ꇯ','ꇰ'=>'ꇰ','ꇱ'=>'ꇱ','ꇲ'=>'ꇲ','ꇳ'=>'ꇳ','ꇴ'=>'ꇴ','ꇵ'=>'ꇵ','ꇶ'=>'ꇶ','ꇷ'=>'ꇷ','ꇸ'=>'ꇸ','ꇹ'=>'ꇹ','ꇺ'=>'ꇺ','ꇻ'=>'ꇻ','ꇼ'=>'ꇼ','ꇽ'=>'ꇽ','ꇾ'=>'ꇾ','ꇿ'=>'ꇿ','ꈀ'=>'ꈀ','êˆ'=>'êˆ','ꈂ'=>'ꈂ','ꈃ'=>'ꈃ','ꈄ'=>'ꈄ','ꈅ'=>'ꈅ','ꈆ'=>'ꈆ','ꈇ'=>'ꈇ','ꈈ'=>'ꈈ','ꈉ'=>'ꈉ','ꈊ'=>'ꈊ','ꈋ'=>'ꈋ','ꈌ'=>'ꈌ','êˆ'=>'êˆ','ꈎ'=>'ꈎ','êˆ'=>'êˆ','êˆ'=>'êˆ','ꈑ'=>'ꈑ','ꈒ'=>'ꈒ','ꈓ'=>'ꈓ','ꈔ'=>'ꈔ','ꈕ'=>'ꈕ','ꈖ'=>'ꈖ','ꈗ'=>'ꈗ','ꈘ'=>'ꈘ','ꈙ'=>'ꈙ','ꈚ'=>'ꈚ','ꈛ'=>'ꈛ','ꈜ'=>'ꈜ','êˆ'=>'êˆ','ꈞ'=>'ꈞ','ꈟ'=>'ꈟ','êˆ '=>'êˆ ','ꈡ'=>'ꈡ','ꈢ'=>'ꈢ','ꈣ'=>'ꈣ','ꈤ'=>'ꈤ','ꈥ'=>'ꈥ','ꈦ'=>'ꈦ','ꈧ'=>'ꈧ','ꈨ'=>'ꈨ','ꈩ'=>'ꈩ','ꈪ'=>'ꈪ','ꈫ'=>'ꈫ','ꈬ'=>'ꈬ','êˆ'=>'êˆ','ꈮ'=>'ꈮ','ꈯ'=>'ꈯ','ꈰ'=>'ꈰ','ꈱ'=>'ꈱ','ꈲ'=>'ꈲ','ꈳ'=>'ꈳ','ꈴ'=>'ꈴ','ꈵ'=>'ꈵ','ꈶ'=>'ꈶ','ꈷ'=>'ꈷ','ꈸ'=>'ꈸ','ꈹ'=>'ꈹ','ꈺ'=>'ꈺ','ꈻ'=>'ꈻ','ꈼ'=>'ꈼ','ꈽ'=>'ꈽ','ꈾ'=>'ꈾ','ꈿ'=>'ꈿ','ꉀ'=>'ꉀ','ê‰'=>'ê‰','ꉂ'=>'ꉂ','ꉃ'=>'ꉃ','ꉄ'=>'ꉄ','ꉅ'=>'ꉅ','ꉆ'=>'ꉆ','ꉇ'=>'ꉇ','ꉈ'=>'ꉈ','ꉉ'=>'ꉉ','ꉊ'=>'ꉊ','ꉋ'=>'ꉋ','ꉌ'=>'ꉌ','ê‰'=>'ê‰','ꉎ'=>'ꉎ','ê‰'=>'ê‰','ê‰'=>'ê‰','ꉑ'=>'ꉑ','ꉒ'=>'ꉒ','ꉓ'=>'ꉓ','ꉔ'=>'ꉔ','ꉕ'=>'ꉕ','ꉖ'=>'ꉖ','ꉗ'=>'ꉗ','ꉘ'=>'ꉘ','ꉙ'=>'ꉙ','ꉚ'=>'ꉚ','ꉛ'=>'ꉛ','ꉜ'=>'ꉜ','ê‰'=>'ê‰','ꉞ'=>'ꉞ','ꉟ'=>'ꉟ','ê‰ '=>'ê‰ ','ꉡ'=>'ꉡ','ꉢ'=>'ꉢ','ꉣ'=>'ꉣ','ꉤ'=>'ꉤ','ꉥ'=>'ꉥ','ꉦ'=>'ꉦ','ꉧ'=>'ꉧ','ꉨ'=>'ꉨ','ꉩ'=>'ꉩ','ꉪ'=>'ꉪ','ꉫ'=>'ꉫ','ꉬ'=>'ꉬ','ê‰'=>'ê‰','ꉮ'=>'ꉮ','ꉯ'=>'ꉯ','ꉰ'=>'ꉰ','ꉱ'=>'ꉱ','ꉲ'=>'ꉲ','ꉳ'=>'ꉳ','ꉴ'=>'ꉴ','ꉵ'=>'ꉵ','ꉶ'=>'ꉶ','ꉷ'=>'ꉷ','ꉸ'=>'ꉸ','ꉹ'=>'ꉹ','ꉺ'=>'ꉺ','ꉻ'=>'ꉻ','ꉼ'=>'ꉼ','ꉽ'=>'ꉽ','ꉾ'=>'ꉾ','ꉿ'=>'ꉿ','ꊀ'=>'ꊀ','êŠ'=>'êŠ','ꊂ'=>'ꊂ','ꊃ'=>'ꊃ','ꊄ'=>'ꊄ','ꊅ'=>'ꊅ','ꊆ'=>'ꊆ','ꊇ'=>'ꊇ','ꊈ'=>'ꊈ','ꊉ'=>'ꊉ','ꊊ'=>'ꊊ','ꊋ'=>'ꊋ','ꊌ'=>'ꊌ','êŠ'=>'êŠ','ꊎ'=>'ꊎ','êŠ'=>'êŠ','êŠ'=>'êŠ','ꊑ'=>'ꊑ','ꊒ'=>'ꊒ','ꊓ'=>'ꊓ','ꊔ'=>'ꊔ','ꊕ'=>'ꊕ','ꊖ'=>'ꊖ','ꊗ'=>'ꊗ','ꊘ'=>'ꊘ','ꊙ'=>'ꊙ','ꊚ'=>'ꊚ','ꊛ'=>'ꊛ','ꊜ'=>'ꊜ','êŠ'=>'êŠ','ꊞ'=>'ꊞ','ꊟ'=>'ꊟ','êŠ '=>'êŠ ','ꊡ'=>'ꊡ','ꊢ'=>'ꊢ','ꊣ'=>'ꊣ','ꊤ'=>'ꊤ','ꊥ'=>'ꊥ','ꊦ'=>'ꊦ','ꊧ'=>'ꊧ','ꊨ'=>'ꊨ','ꊩ'=>'ꊩ','ꊪ'=>'ꊪ','ꊫ'=>'ꊫ','ꊬ'=>'ꊬ','êŠ'=>'êŠ','ꊮ'=>'ꊮ','ꊯ'=>'ꊯ','ꊰ'=>'ꊰ','ꊱ'=>'ꊱ','ꊲ'=>'ꊲ','ꊳ'=>'ꊳ','ꊴ'=>'ꊴ','ꊵ'=>'ꊵ','ꊶ'=>'ꊶ','ꊷ'=>'ꊷ','ꊸ'=>'ꊸ','ꊹ'=>'ꊹ','ꊺ'=>'ꊺ','ꊻ'=>'ꊻ','ꊼ'=>'ꊼ','ꊽ'=>'ꊽ','ꊾ'=>'ꊾ','ꊿ'=>'ꊿ','ê‹€'=>'ê‹€','ê‹'=>'ê‹','ê‹‚'=>'ê‹‚','ꋃ'=>'ꋃ','ê‹„'=>'ê‹„','ê‹…'=>'ê‹…','ꋆ'=>'ꋆ','ꋇ'=>'ꋇ','ꋈ'=>'ꋈ','ꋉ'=>'ꋉ','ꋊ'=>'ꋊ','ê‹‹'=>'ê‹‹','ꋌ'=>'ꋌ','ê‹'=>'ê‹','ꋎ'=>'ꋎ','ê‹'=>'ê‹','ê‹'=>'ê‹','ê‹‘'=>'ê‹‘','ê‹’'=>'ê‹’','ê‹“'=>'ê‹“','ê‹”'=>'ê‹”','ê‹•'=>'ê‹•','ê‹–'=>'ê‹–','ê‹—'=>'ê‹—','ꋘ'=>'ꋘ','ê‹™'=>'ê‹™','ꋚ'=>'ꋚ','ê‹›'=>'ê‹›','ꋜ'=>'ꋜ','ê‹'=>'ê‹','ꋞ'=>'ꋞ','ꋟ'=>'ꋟ','ê‹ '=>'ê‹ ','ê‹¡'=>'ê‹¡','ê‹¢'=>'ê‹¢','ê‹£'=>'ê‹£','ꋤ'=>'ꋤ','ê‹¥'=>'ê‹¥','ꋦ'=>'ꋦ','ê‹§'=>'ê‹§','ꋨ'=>'ꋨ','ê‹©'=>'ê‹©','ꋪ'=>'ꋪ','ê‹«'=>'ê‹«','ꋬ'=>'ꋬ','ê‹'=>'ê‹','ê‹®'=>'ê‹®','ꋯ'=>'ꋯ','ê‹°'=>'ê‹°','ꋱ'=>'ꋱ','ꋲ'=>'ꋲ','ꋳ'=>'ꋳ','ê‹´'=>'ê‹´','ꋵ'=>'ꋵ','ê‹¶'=>'ê‹¶','ê‹·'=>'ê‹·','ꋸ'=>'ꋸ','ꋹ'=>'ꋹ','ꋺ'=>'ꋺ','ê‹»'=>'ê‹»','ꋼ'=>'ꋼ','ꋽ'=>'ꋽ','ꋾ'=>'ꋾ','ê‹¿'=>'ê‹¿','ꌀ'=>'ꌀ','êŒ'=>'êŒ','ꌂ'=>'ꌂ','ꌃ'=>'ꌃ','ꌄ'=>'ꌄ','ꌅ'=>'ꌅ','ꌆ'=>'ꌆ','ꌇ'=>'ꌇ','ꌈ'=>'ꌈ','ꌉ'=>'ꌉ','ꌊ'=>'ꌊ','ꌋ'=>'ꌋ','ꌌ'=>'ꌌ','êŒ'=>'êŒ','ꌎ'=>'ꌎ','êŒ'=>'êŒ','êŒ'=>'êŒ','ꌑ'=>'ꌑ','ꌒ'=>'ꌒ','ꌓ'=>'ꌓ','ꌔ'=>'ꌔ','ꌕ'=>'ꌕ','ꌖ'=>'ꌖ','ꌗ'=>'ꌗ','ꌘ'=>'ꌘ','ꌙ'=>'ꌙ','ꌚ'=>'ꌚ','ꌛ'=>'ꌛ','ꌜ'=>'ꌜ','êŒ'=>'êŒ','ꌞ'=>'ꌞ','ꌟ'=>'ꌟ','êŒ '=>'êŒ ','ꌡ'=>'ꌡ','ꌢ'=>'ꌢ','ꌣ'=>'ꌣ','ꌤ'=>'ꌤ','ꌥ'=>'ꌥ','ꌦ'=>'ꌦ','ꌧ'=>'ꌧ','ꌨ'=>'ꌨ','ꌩ'=>'ꌩ','ꌪ'=>'ꌪ','ꌫ'=>'ꌫ','ꌬ'=>'ꌬ','êŒ'=>'êŒ','ꌮ'=>'ꌮ','ꌯ'=>'ꌯ','ꌰ'=>'ꌰ','ꌱ'=>'ꌱ','ꌲ'=>'ꌲ','ꌳ'=>'ꌳ','ꌴ'=>'ꌴ','ꌵ'=>'ꌵ','ꌶ'=>'ꌶ','ꌷ'=>'ꌷ','ꌸ'=>'ꌸ','ꌹ'=>'ꌹ','ꌺ'=>'ꌺ','ꌻ'=>'ꌻ','ꌼ'=>'ꌼ','ꌽ'=>'ꌽ','ꌾ'=>'ꌾ','ꌿ'=>'ꌿ','ê€'=>'ê€','ê'=>'ê','ê‚'=>'ê‚','êƒ'=>'êƒ','ê„'=>'ê„','ê…'=>'ê…','ê†'=>'ê†','ê‡'=>'ê‡','êˆ'=>'êˆ','ê‰'=>'ê‰','êŠ'=>'êŠ','ê‹'=>'ê‹','êŒ'=>'êŒ','ê'=>'ê','êŽ'=>'êŽ','ê'=>'ê','ê'=>'ê','ê‘'=>'ê‘','ê’'=>'ê’','ê“'=>'ê“','ê”'=>'ê”','ê•'=>'ê•','ê–'=>'ê–','ê—'=>'ê—','ê˜'=>'ê˜','ê™'=>'ê™','êš'=>'êš','ê›'=>'ê›','êœ'=>'êœ','ê'=>'ê','êž'=>'êž','êŸ'=>'êŸ','ê '=>'ê ','ê¡'=>'ê¡','ê¢'=>'ê¢','ê£'=>'ê£','ê¤'=>'ê¤','ê¥'=>'ê¥','ê¦'=>'ê¦','ê§'=>'ê§','ê¨'=>'ê¨','ê©'=>'ê©','êª'=>'êª','ê«'=>'ê«','ê¬'=>'ê¬','ê'=>'ê','ê®'=>'ê®','ê¯'=>'ê¯','ê°'=>'ê°','ê±'=>'ê±','ê²'=>'ê²','ê³'=>'ê³','ê´'=>'ê´','êµ'=>'êµ','ê¶'=>'ê¶','ê·'=>'ê·','ê¸'=>'ê¸','ê¹'=>'ê¹','êº'=>'êº','ê»'=>'ê»','ê¼'=>'ê¼','ê½'=>'ê½','ê¾'=>'ê¾','ê¿'=>'ê¿','ꎀ'=>'ꎀ','êŽ'=>'êŽ','ꎂ'=>'ꎂ','ꎃ'=>'ꎃ','ꎄ'=>'ꎄ','ꎅ'=>'ꎅ','ꎆ'=>'ꎆ','ꎇ'=>'ꎇ','ꎈ'=>'ꎈ','ꎉ'=>'ꎉ','ꎊ'=>'ꎊ','ꎋ'=>'ꎋ','ꎌ'=>'ꎌ','êŽ'=>'êŽ','ꎎ'=>'ꎎ','êŽ'=>'êŽ','êŽ'=>'êŽ','ꎑ'=>'ꎑ','ꎒ'=>'ꎒ','ꎓ'=>'ꎓ','ꎔ'=>'ꎔ','ꎕ'=>'ꎕ','ꎖ'=>'ꎖ','ꎗ'=>'ꎗ','ꎘ'=>'ꎘ','ꎙ'=>'ꎙ','ꎚ'=>'ꎚ','ꎛ'=>'ꎛ','ꎜ'=>'ꎜ','êŽ'=>'êŽ','ꎞ'=>'ꎞ','ꎟ'=>'ꎟ','êŽ '=>'êŽ ','ꎡ'=>'ꎡ','ꎢ'=>'ꎢ','ꎣ'=>'ꎣ','ꎤ'=>'ꎤ','ꎥ'=>'ꎥ','ꎦ'=>'ꎦ','ꎧ'=>'ꎧ','ꎨ'=>'ꎨ','ꎩ'=>'ꎩ','ꎪ'=>'ꎪ','ꎫ'=>'ꎫ','ꎬ'=>'ꎬ','êŽ'=>'êŽ','ꎮ'=>'ꎮ','ꎯ'=>'ꎯ','ꎰ'=>'ꎰ','ꎱ'=>'ꎱ','ꎲ'=>'ꎲ','ꎳ'=>'ꎳ','ꎴ'=>'ꎴ','ꎵ'=>'ꎵ','ꎶ'=>'ꎶ','ꎷ'=>'ꎷ','ꎸ'=>'ꎸ','ꎹ'=>'ꎹ','ꎺ'=>'ꎺ','ꎻ'=>'ꎻ','ꎼ'=>'ꎼ','ꎽ'=>'ꎽ','ꎾ'=>'ꎾ','ꎿ'=>'ꎿ','ê€'=>'ê€','ê'=>'ê','ê‚'=>'ê‚','êƒ'=>'êƒ','ê„'=>'ê„','ê…'=>'ê…','ê†'=>'ê†','ê‡'=>'ê‡','êˆ'=>'êˆ','ê‰'=>'ê‰','êŠ'=>'êŠ','ê‹'=>'ê‹','êŒ'=>'êŒ','ê'=>'ê','êŽ'=>'êŽ','ê'=>'ê','ê'=>'ê','ê‘'=>'ê‘','ê’'=>'ê’','ê“'=>'ê“','ê”'=>'ê”','ê•'=>'ê•','ê–'=>'ê–','ê—'=>'ê—','ê˜'=>'ê˜','ê™'=>'ê™','êš'=>'êš','ê›'=>'ê›','êœ'=>'êœ','ê'=>'ê','êž'=>'êž','êŸ'=>'êŸ','ê '=>'ê ','ê¡'=>'ê¡','ê¢'=>'ê¢','ê£'=>'ê£','ê¤'=>'ê¤','ê¥'=>'ê¥','ê¦'=>'ê¦','ê§'=>'ê§','ê¨'=>'ê¨','ê©'=>'ê©','êª'=>'êª','ê«'=>'ê«','ê¬'=>'ê¬','ê'=>'ê','ê®'=>'ê®','ê¯'=>'ê¯','ê°'=>'ê°','ê±'=>'ê±','ê²'=>'ê²','ê³'=>'ê³','ê´'=>'ê´','êµ'=>'êµ','ê¶'=>'ê¶','ê·'=>'ê·','ê¸'=>'ê¸','ê¹'=>'ê¹','êº'=>'êº','ê»'=>'ê»','ê¼'=>'ê¼','ê½'=>'ê½','ê¾'=>'ê¾','ê¿'=>'ê¿','ê€'=>'ê€','ê'=>'ê','ê‚'=>'ê‚','êƒ'=>'êƒ','ê„'=>'ê„','ê…'=>'ê…','ê†'=>'ê†','ê‡'=>'ê‡','êˆ'=>'êˆ','ê‰'=>'ê‰','êŠ'=>'êŠ','ê‹'=>'ê‹','êŒ'=>'êŒ','ê'=>'ê','êŽ'=>'êŽ','ê'=>'ê','ê'=>'ê','ê‘'=>'ê‘','ê’'=>'ê’','ê“'=>'ê“','ê”'=>'ê”','ê•'=>'ê•','ê–'=>'ê–','ê—'=>'ê—','ê˜'=>'ê˜','ê™'=>'ê™','êš'=>'êš','ê›'=>'ê›','êœ'=>'êœ','ê'=>'ê','êž'=>'êž','êŸ'=>'êŸ','ê '=>'ê ','ê¡'=>'ê¡','ê¢'=>'ê¢','ê£'=>'ê£','ê¤'=>'ê¤','ê¥'=>'ê¥','ê¦'=>'ê¦','ê§'=>'ê§','ê¨'=>'ê¨','ê©'=>'ê©','êª'=>'êª','ê«'=>'ê«','ê¬'=>'ê¬','ê'=>'ê','ê®'=>'ê®','ê¯'=>'ê¯','ê°'=>'ê°','ê±'=>'ê±','ê²'=>'ê²','ê³'=>'ê³','ê´'=>'ê´','êµ'=>'êµ','ê¶'=>'ê¶','ê·'=>'ê·','ê¸'=>'ê¸','ê¹'=>'ê¹','êº'=>'êº','ê»'=>'ê»','ê¼'=>'ê¼','ê½'=>'ê½','ê¾'=>'ê¾','ê¿'=>'ê¿','ê‘€'=>'ê‘€','ê‘'=>'ê‘','ê‘‚'=>'ê‘‚','ꑃ'=>'ꑃ','ê‘„'=>'ê‘„','ê‘…'=>'ê‘…','ꑆ'=>'ꑆ','ꑇ'=>'ꑇ','ꑈ'=>'ꑈ','ꑉ'=>'ꑉ','ꑊ'=>'ꑊ','ê‘‹'=>'ê‘‹','ꑌ'=>'ꑌ','ê‘'=>'ê‘','ꑎ'=>'ꑎ','ê‘'=>'ê‘','ê‘'=>'ê‘','ê‘‘'=>'ê‘‘','ê‘’'=>'ê‘’','ê‘“'=>'ê‘“','ê‘”'=>'ê‘”','ê‘•'=>'ê‘•','ê‘–'=>'ê‘–','ê‘—'=>'ê‘—','ꑘ'=>'ꑘ','ê‘™'=>'ê‘™','ꑚ'=>'ꑚ','ê‘›'=>'ê‘›','ꑜ'=>'ꑜ','ê‘'=>'ê‘','ꑞ'=>'ꑞ','ꑟ'=>'ꑟ','ê‘ '=>'ê‘ ','ê‘¡'=>'ê‘¡','ê‘¢'=>'ê‘¢','ê‘£'=>'ê‘£','ꑤ'=>'ꑤ','ê‘¥'=>'ê‘¥','ꑦ'=>'ꑦ','ê‘§'=>'ê‘§','ꑨ'=>'ꑨ','ê‘©'=>'ê‘©','ꑪ'=>'ꑪ','ê‘«'=>'ê‘«','ꑬ'=>'ꑬ','ê‘'=>'ê‘','ê‘®'=>'ê‘®','ꑯ'=>'ꑯ','ê‘°'=>'ê‘°','ꑱ'=>'ꑱ','ꑲ'=>'ꑲ','ꑳ'=>'ꑳ','ê‘´'=>'ê‘´','ꑵ'=>'ꑵ','ê‘¶'=>'ê‘¶','ê‘·'=>'ê‘·','ꑸ'=>'ꑸ','ꑹ'=>'ꑹ','ꑺ'=>'ꑺ','ê‘»'=>'ê‘»','ꑼ'=>'ꑼ','ꑽ'=>'ꑽ','ꑾ'=>'ꑾ','ê‘¿'=>'ê‘¿','ê’€'=>'ê’€','ê’'=>'ê’','ê’‚'=>'ê’‚','ê’ƒ'=>'ê’ƒ','ê’„'=>'ê’„','ê’…'=>'ê’…','ê’†'=>'ê’†','ê’‡'=>'ê’‡','ê’ˆ'=>'ê’ˆ','ê’‰'=>'ê’‰','ê’Š'=>'ê’Š','ê’‹'=>'ê’‹','ê’Œ'=>'ê’Œ','ꜗ'=>'ꜗ','ꜘ'=>'ꜘ','ꜙ'=>'ꜙ','ꜚ'=>'ꜚ');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_21.php b/phpBB/includes/utf/data/search_indexer_21.php deleted file mode 100644 index 7fc3e4dc09..0000000000 --- a/phpBB/includes/utf/data/search_indexer_21.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('ê €'=>'ê €','ê '=>'ê ','ê ‚'=>'ê ‚','ê ƒ'=>'ê ƒ','ê „'=>'ê „','ê …'=>'ê …','ê †'=>'ê †','ê ‡'=>'ê ‡','ê ˆ'=>'ê ˆ','ê ‰'=>'ê ‰','ê Š'=>'ê Š','ê ‹'=>'ê ‹','ê Œ'=>'ê Œ','ê '=>'ê ','ê Ž'=>'ê Ž','ê '=>'ê ','ê '=>'ê ','ê ‘'=>'ê ‘','ê ’'=>'ê ’','ê “'=>'ê “','ê ”'=>'ê ”','ê •'=>'ê •','ê –'=>'ê –','ê —'=>'ê —','ê ˜'=>'ê ˜','ê ™'=>'ê ™','ê š'=>'ê š','ê ›'=>'ê ›','ê œ'=>'ê œ','ê '=>'ê ','ê ž'=>'ê ž','ê Ÿ'=>'ê Ÿ','ê '=>'ê ','ê ¡'=>'ê ¡','ê ¢'=>'ê ¢','ê £'=>'ê £','ê ¤'=>'ê ¤','ê ¥'=>'ê ¥','ê ¦'=>'ê ¦','ê §'=>'ê §','ê¡€'=>'ê¡€','ê¡'=>'ê¡','ê¡‚'=>'ê¡‚','ꡃ'=>'ꡃ','ê¡„'=>'ê¡„','ê¡…'=>'ê¡…','ꡆ'=>'ꡆ','ꡇ'=>'ꡇ','ꡈ'=>'ꡈ','ꡉ'=>'ꡉ','ꡊ'=>'ꡊ','ê¡‹'=>'ê¡‹','ꡌ'=>'ꡌ','ê¡'=>'ê¡','ꡎ'=>'ꡎ','ê¡'=>'ê¡','ê¡'=>'ê¡','ê¡‘'=>'ê¡‘','ê¡’'=>'ê¡’','ê¡“'=>'ê¡“','ê¡”'=>'ê¡”','ê¡•'=>'ê¡•','ê¡–'=>'ê¡–','ê¡—'=>'ê¡—','ꡘ'=>'ꡘ','ê¡™'=>'ê¡™','ꡚ'=>'ꡚ','ê¡›'=>'ê¡›','ꡜ'=>'ꡜ','ê¡'=>'ê¡','ꡞ'=>'ꡞ','ꡟ'=>'ꡟ','ê¡ '=>'ê¡ ','ê¡¡'=>'ê¡¡','ê¡¢'=>'ê¡¢','ê¡£'=>'ê¡£','ꡤ'=>'ꡤ','ê¡¥'=>'ê¡¥','ꡦ'=>'ꡦ','ê¡§'=>'ê¡§','ꡨ'=>'ꡨ','ê¡©'=>'ê¡©','ꡪ'=>'ꡪ','ê¡«'=>'ê¡«','ꡬ'=>'ꡬ','ê¡'=>'ê¡','ê¡®'=>'ê¡®','ꡯ'=>'ꡯ','ê¡°'=>'ê¡°','ꡱ'=>'ꡱ','ꡲ'=>'ꡲ','ꡳ'=>'ꡳ','ê°€'=>'ê°€');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_26.php b/phpBB/includes/utf/data/search_indexer_26.php deleted file mode 100644 index b8718bd608..0000000000 --- a/phpBB/includes/utf/data/search_indexer_26.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('힣'=>'힣');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_3.php b/phpBB/includes/utf/data/search_indexer_3.php deleted file mode 100644 index 41798c9e86..0000000000 --- a/phpBB/includes/utf/data/search_indexer_3.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('á ‹'=>'á ‹','á Œ'=>'á Œ','á '=>'á ','á '=>'0','á ‘'=>'1','á ’'=>'2','á “'=>'3','á ”'=>'4','á •'=>'5','á –'=>'6','á —'=>'7','á ˜'=>'8','á ™'=>'9','á '=>'á ','á ¡'=>'á ¡','á ¢'=>'á ¢','á £'=>'á £','á ¤'=>'á ¤','á ¥'=>'á ¥','á ¦'=>'á ¦','á §'=>'á §','á ¨'=>'á ¨','á ©'=>'á ©','á ª'=>'á ª','á «'=>'á «','á ¬'=>'á ¬','á '=>'á ','á ®'=>'á ®','á ¯'=>'á ¯','á °'=>'á °','á ±'=>'á ±','á ²'=>'á ²','á ³'=>'á ³','á ´'=>'á ´','á µ'=>'á µ','á ¶'=>'á ¶','á ·'=>'á ·','á ¸'=>'á ¸','á ¹'=>'á ¹','á º'=>'á º','á »'=>'á »','á ¼'=>'á ¼','á ½'=>'á ½','á ¾'=>'á ¾','á ¿'=>'á ¿','á¡€'=>'á¡€','á¡'=>'á¡','á¡‚'=>'á¡‚','ᡃ'=>'ᡃ','á¡„'=>'á¡„','á¡…'=>'á¡…','ᡆ'=>'ᡆ','ᡇ'=>'ᡇ','ᡈ'=>'ᡈ','ᡉ'=>'ᡉ','ᡊ'=>'ᡊ','á¡‹'=>'á¡‹','ᡌ'=>'ᡌ','á¡'=>'á¡','ᡎ'=>'ᡎ','á¡'=>'á¡','á¡'=>'á¡','á¡‘'=>'á¡‘','á¡’'=>'á¡’','á¡“'=>'á¡“','á¡”'=>'á¡”','á¡•'=>'á¡•','á¡–'=>'á¡–','á¡—'=>'á¡—','ᡘ'=>'ᡘ','á¡™'=>'á¡™','ᡚ'=>'ᡚ','á¡›'=>'á¡›','ᡜ'=>'ᡜ','á¡'=>'á¡','ᡞ'=>'ᡞ','ᡟ'=>'ᡟ','á¡ '=>'á¡ ','á¡¡'=>'á¡¡','á¡¢'=>'á¡¢','á¡£'=>'á¡£','ᡤ'=>'ᡤ','á¡¥'=>'á¡¥','ᡦ'=>'ᡦ','á¡§'=>'á¡§','ᡨ'=>'ᡨ','á¡©'=>'á¡©','ᡪ'=>'ᡪ','á¡«'=>'á¡«','ᡬ'=>'ᡬ','á¡'=>'á¡','á¡®'=>'á¡®','ᡯ'=>'ᡯ','á¡°'=>'á¡°','ᡱ'=>'ᡱ','ᡲ'=>'ᡲ','ᡳ'=>'ᡳ','á¡´'=>'á¡´','ᡵ'=>'ᡵ','á¡¶'=>'á¡¶','á¡·'=>'á¡·','ᢀ'=>'ᢀ','á¢'=>'á¢','ᢂ'=>'ᢂ','ᢃ'=>'ᢃ','ᢄ'=>'ᢄ','ᢅ'=>'ᢅ','ᢆ'=>'ᢆ','ᢇ'=>'ᢇ','ᢈ'=>'ᢈ','ᢉ'=>'ᢉ','ᢊ'=>'ᢊ','ᢋ'=>'ᢋ','ᢌ'=>'ᢌ','á¢'=>'á¢','ᢎ'=>'ᢎ','á¢'=>'á¢','á¢'=>'á¢','ᢑ'=>'ᢑ','ᢒ'=>'ᢒ','ᢓ'=>'ᢓ','ᢔ'=>'ᢔ','ᢕ'=>'ᢕ','ᢖ'=>'ᢖ','ᢗ'=>'ᢗ','ᢘ'=>'ᢘ','ᢙ'=>'ᢙ','ᢚ'=>'ᢚ','ᢛ'=>'ᢛ','ᢜ'=>'ᢜ','á¢'=>'á¢','ᢞ'=>'ᢞ','ᢟ'=>'ᢟ','ᢠ'=>'ᢠ','ᢡ'=>'ᢡ','ᢢ'=>'ᢢ','ᢣ'=>'ᢣ','ᢤ'=>'ᢤ','ᢥ'=>'ᢥ','ᢦ'=>'ᢦ','ᢧ'=>'ᢧ','ᢨ'=>'ᢨ','ᢩ'=>'ᢩ','ᤀ'=>'ᤀ','á¤'=>'á¤','ᤂ'=>'ᤂ','ᤃ'=>'ᤃ','ᤄ'=>'ᤄ','ᤅ'=>'ᤅ','ᤆ'=>'ᤆ','ᤇ'=>'ᤇ','ᤈ'=>'ᤈ','ᤉ'=>'ᤉ','ᤊ'=>'ᤊ','ᤋ'=>'ᤋ','ᤌ'=>'ᤌ','á¤'=>'á¤','ᤎ'=>'ᤎ','á¤'=>'á¤','á¤'=>'á¤','ᤑ'=>'ᤑ','ᤒ'=>'ᤒ','ᤓ'=>'ᤓ','ᤔ'=>'ᤔ','ᤕ'=>'ᤕ','ᤖ'=>'ᤖ','ᤗ'=>'ᤗ','ᤘ'=>'ᤘ','ᤙ'=>'ᤙ','ᤚ'=>'ᤚ','ᤛ'=>'ᤛ','ᤜ'=>'ᤜ','ᤠ'=>'ᤠ','ᤡ'=>'ᤡ','ᤢ'=>'ᤢ','ᤣ'=>'ᤣ','ᤤ'=>'ᤤ','ᤥ'=>'ᤥ','ᤦ'=>'ᤦ','ᤧ'=>'ᤧ','ᤨ'=>'ᤨ','ᤩ'=>'ᤩ','ᤪ'=>'ᤪ','ᤫ'=>'ᤫ','ᤰ'=>'ᤰ','ᤱ'=>'ᤱ','ᤲ'=>'ᤲ','ᤳ'=>'ᤳ','ᤴ'=>'ᤴ','ᤵ'=>'ᤵ','ᤶ'=>'ᤶ','ᤷ'=>'ᤷ','ᤸ'=>'ᤸ','᤹'=>'᤹','᤺'=>'᤺','᤻'=>'᤻','᥆'=>'0','᥇'=>'1','᥈'=>'2','᥉'=>'3','᥊'=>'4','᥋'=>'5','᥌'=>'6','á¥'=>'7','᥎'=>'8','á¥'=>'9','á¥'=>'á¥','ᥑ'=>'ᥑ','ᥒ'=>'ᥒ','ᥓ'=>'ᥓ','ᥔ'=>'ᥔ','ᥕ'=>'ᥕ','ᥖ'=>'ᥖ','ᥗ'=>'ᥗ','ᥘ'=>'ᥘ','ᥙ'=>'ᥙ','ᥚ'=>'ᥚ','ᥛ'=>'ᥛ','ᥜ'=>'ᥜ','á¥'=>'á¥','ᥞ'=>'ᥞ','ᥟ'=>'ᥟ','ᥠ'=>'ᥠ','ᥡ'=>'ᥡ','ᥢ'=>'ᥢ','ᥣ'=>'ᥣ','ᥤ'=>'ᥤ','ᥥ'=>'ᥥ','ᥦ'=>'ᥦ','ᥧ'=>'ᥧ','ᥨ'=>'ᥨ','ᥩ'=>'ᥩ','ᥪ'=>'ᥪ','ᥫ'=>'ᥫ','ᥬ'=>'ᥬ','á¥'=>'á¥','ᥰ'=>'ᥰ','ᥱ'=>'ᥱ','ᥲ'=>'ᥲ','ᥳ'=>'ᥳ','ᥴ'=>'ᥴ','ᦀ'=>'ᦀ','á¦'=>'á¦','ᦂ'=>'ᦂ','ᦃ'=>'ᦃ','ᦄ'=>'ᦄ','ᦅ'=>'ᦅ','ᦆ'=>'ᦆ','ᦇ'=>'ᦇ','ᦈ'=>'ᦈ','ᦉ'=>'ᦉ','ᦊ'=>'ᦊ','ᦋ'=>'ᦋ','ᦌ'=>'ᦌ','á¦'=>'á¦','ᦎ'=>'ᦎ','á¦'=>'á¦','á¦'=>'á¦','ᦑ'=>'ᦑ','ᦒ'=>'ᦒ','ᦓ'=>'ᦓ','ᦔ'=>'ᦔ','ᦕ'=>'ᦕ','ᦖ'=>'ᦖ','ᦗ'=>'ᦗ','ᦘ'=>'ᦘ','ᦙ'=>'ᦙ','ᦚ'=>'ᦚ','ᦛ'=>'ᦛ','ᦜ'=>'ᦜ','á¦'=>'á¦','ᦞ'=>'ᦞ','ᦟ'=>'ᦟ','ᦠ'=>'ᦠ','ᦡ'=>'ᦡ','ᦢ'=>'ᦢ','ᦣ'=>'ᦣ','ᦤ'=>'ᦤ','ᦥ'=>'ᦥ','ᦦ'=>'ᦦ','ᦧ'=>'ᦧ','ᦨ'=>'ᦨ','ᦩ'=>'ᦩ','ᦰ'=>'ᦰ','ᦱ'=>'ᦱ','ᦲ'=>'ᦲ','ᦳ'=>'ᦳ','ᦴ'=>'ᦴ','ᦵ'=>'ᦵ','ᦶ'=>'ᦶ','ᦷ'=>'ᦷ','ᦸ'=>'ᦸ','ᦹ'=>'ᦹ','ᦺ'=>'ᦺ','ᦻ'=>'ᦻ','ᦼ'=>'ᦼ','ᦽ'=>'ᦽ','ᦾ'=>'ᦾ','ᦿ'=>'ᦿ','á§€'=>'á§€','á§'=>'á§','á§‚'=>'á§‚','ᧃ'=>'ᧃ','á§„'=>'á§„','á§…'=>'á§…','ᧆ'=>'ᧆ','ᧇ'=>'ᧇ','ᧈ'=>'ᧈ','ᧉ'=>'ᧉ','á§'=>'0','á§‘'=>'1','á§’'=>'2','á§“'=>'3','á§”'=>'4','á§•'=>'5','á§–'=>'6','á§—'=>'7','᧘'=>'8','á§™'=>'9','ᨀ'=>'ᨀ','á¨'=>'á¨','ᨂ'=>'ᨂ','ᨃ'=>'ᨃ','ᨄ'=>'ᨄ','ᨅ'=>'ᨅ','ᨆ'=>'ᨆ','ᨇ'=>'ᨇ','ᨈ'=>'ᨈ','ᨉ'=>'ᨉ','ᨊ'=>'ᨊ','ᨋ'=>'ᨋ','ᨌ'=>'ᨌ','á¨'=>'á¨','ᨎ'=>'ᨎ','á¨'=>'á¨','á¨'=>'á¨','ᨑ'=>'ᨑ','ᨒ'=>'ᨒ','ᨓ'=>'ᨓ','ᨔ'=>'ᨔ','ᨕ'=>'ᨕ','ᨖ'=>'ᨖ','ᨗ'=>'ᨗ','ᨘ'=>'ᨘ','ᨙ'=>'ᨙ','ᨚ'=>'ᨚ','ᨛ'=>'ᨛ','ᬀ'=>'ᬀ','á¬'=>'á¬','ᬂ'=>'ᬂ','ᬃ'=>'ᬃ','ᬄ'=>'ᬄ','ᬅ'=>'ᬅ','ᬆ'=>'ᬆ','ᬇ'=>'ᬇ','ᬈ'=>'ᬈ','ᬉ'=>'ᬉ','ᬊ'=>'ᬊ','ᬋ'=>'ᬋ','ᬌ'=>'ᬌ','á¬'=>'á¬','ᬎ'=>'ᬎ','á¬'=>'á¬','á¬'=>'á¬','ᬑ'=>'ᬑ','ᬒ'=>'ᬒ','ᬓ'=>'ᬓ','ᬔ'=>'ᬔ','ᬕ'=>'ᬕ','ᬖ'=>'ᬖ','ᬗ'=>'ᬗ','ᬘ'=>'ᬘ','ᬙ'=>'ᬙ','ᬚ'=>'ᬚ','ᬛ'=>'ᬛ','ᬜ'=>'ᬜ','á¬'=>'á¬','ᬞ'=>'ᬞ','ᬟ'=>'ᬟ','ᬠ'=>'ᬠ','ᬡ'=>'ᬡ','ᬢ'=>'ᬢ','ᬣ'=>'ᬣ','ᬤ'=>'ᬤ','ᬥ'=>'ᬥ','ᬦ'=>'ᬦ','ᬧ'=>'ᬧ','ᬨ'=>'ᬨ','ᬩ'=>'ᬩ','ᬪ'=>'ᬪ','ᬫ'=>'ᬫ','ᬬ'=>'ᬬ','á¬'=>'á¬','ᬮ'=>'ᬮ','ᬯ'=>'ᬯ','ᬰ'=>'ᬰ','ᬱ'=>'ᬱ','ᬲ'=>'ᬲ','ᬳ'=>'ᬳ','᬴'=>'᬴','ᬵ'=>'ᬵ','ᬶ'=>'ᬶ','ᬷ'=>'ᬷ','ᬸ'=>'ᬸ','ᬹ'=>'ᬹ','ᬺ'=>'ᬺ','ᬻ'=>'ᬻ','ᬼ'=>'ᬼ','ᬽ'=>'ᬽ','ᬾ'=>'ᬾ','ᬿ'=>'ᬿ','á€'=>'á€','á'=>'á','á‚'=>'á‚','áƒ'=>'áƒ','á„'=>'á„','á…'=>'á…','á†'=>'á†','á‡'=>'á‡','áˆ'=>'áˆ','á‰'=>'á‰','áŠ'=>'áŠ','á‹'=>'á‹','á'=>'0','á‘'=>'1','á’'=>'2','á“'=>'3','á”'=>'4','á•'=>'5','á–'=>'6','á—'=>'7','á˜'=>'8','á™'=>'9','á«'=>'á«','á¬'=>'á¬','á'=>'á','á®'=>'á®','á¯'=>'á¯','á°'=>'á°','á±'=>'á±','á²'=>'á²','á³'=>'á³','á´€'=>'á´€','á´'=>'á´','á´‚'=>'á´‚','á´ƒ'=>'á´ƒ','á´„'=>'á´„','á´…'=>'á´…','á´†'=>'á´†','á´‡'=>'á´‡','á´ˆ'=>'á´ˆ','á´‰'=>'á´‰','á´Š'=>'á´Š','á´‹'=>'á´‹','á´Œ'=>'á´Œ','á´'=>'á´','á´Ž'=>'á´Ž','á´'=>'á´','á´'=>'á´','á´‘'=>'á´‘','á´’'=>'á´’','á´“'=>'á´“','á´”'=>'á´”','á´•'=>'á´•','á´–'=>'á´–','á´—'=>'á´—','á´˜'=>'á´˜','á´™'=>'á´™','á´š'=>'á´š','á´›'=>'á´›','á´œ'=>'á´œ','á´'=>'á´','á´ž'=>'á´ž','á´Ÿ'=>'á´Ÿ','á´ '=>'á´ ','á´¡'=>'á´¡','á´¢'=>'á´¢','á´£'=>'á´£','á´¤'=>'á´¤','á´¥'=>'á´¥','á´¦'=>'á´¦','á´§'=>'á´§','á´¨'=>'á´¨','á´©'=>'á´©','á´ª'=>'á´ª','á´«'=>'á´«','á´¬'=>'á´¬','á´'=>'á´','á´®'=>'á´®','á´¯'=>'á´¯','á´°'=>'á´°','á´±'=>'á´±','á´²'=>'á´²','á´³'=>'á´³','á´´'=>'á´´','á´µ'=>'á´µ','á´¶'=>'á´¶','á´·'=>'á´·','á´¸'=>'á´¸','á´¹'=>'á´¹','á´º'=>'á´º','á´»'=>'á´»','á´¼'=>'á´¼','á´½'=>'á´½','á´¾'=>'á´¾','á´¿'=>'á´¿','áµ€'=>'áµ€','áµ'=>'áµ','ᵂ'=>'ᵂ','ᵃ'=>'ᵃ','ᵄ'=>'ᵄ','áµ…'=>'áµ…','ᵆ'=>'ᵆ','ᵇ'=>'ᵇ','ᵈ'=>'ᵈ','ᵉ'=>'ᵉ','ᵊ'=>'ᵊ','ᵋ'=>'ᵋ','ᵌ'=>'ᵌ','áµ'=>'áµ','ᵎ'=>'ᵎ','áµ'=>'áµ','áµ'=>'áµ','ᵑ'=>'ᵑ','áµ’'=>'áµ’','ᵓ'=>'ᵓ','áµ”'=>'áµ”','ᵕ'=>'ᵕ','áµ–'=>'áµ–','áµ—'=>'áµ—','ᵘ'=>'ᵘ','áµ™'=>'áµ™','ᵚ'=>'ᵚ','áµ›'=>'áµ›','ᵜ'=>'ᵜ','áµ'=>'áµ','ᵞ'=>'ᵞ','ᵟ'=>'ᵟ','áµ '=>'áµ ','ᵡ'=>'ᵡ','áµ¢'=>'áµ¢','áµ£'=>'áµ£','ᵤ'=>'ᵤ','áµ¥'=>'áµ¥','ᵦ'=>'ᵦ','áµ§'=>'áµ§','ᵨ'=>'ᵨ','ᵩ'=>'ᵩ','ᵪ'=>'ᵪ','ᵫ'=>'ue','ᵬ'=>'ᵬ','áµ'=>'áµ','áµ®'=>'áµ®','ᵯ'=>'ᵯ','áµ°'=>'áµ°','áµ±'=>'áµ±','áµ²'=>'áµ²','áµ³'=>'áµ³','áµ´'=>'áµ´','áµµ'=>'áµµ','áµ¶'=>'áµ¶','áµ·'=>'áµ·','ᵸ'=>'ᵸ','áµ¹'=>'áµ¹','ᵺ'=>'ᵺ','áµ»'=>'áµ»','áµ¼'=>'áµ¼','áµ½'=>'áµ½','áµ¾'=>'áµ¾','ᵿ'=>'ᵿ','á¶€'=>'á¶€','á¶'=>'á¶','á¶‚'=>'á¶‚','ᶃ'=>'ᶃ','á¶„'=>'á¶„','á¶…'=>'á¶…','ᶆ'=>'ᶆ','ᶇ'=>'ᶇ','ᶈ'=>'ᶈ','ᶉ'=>'ᶉ','á¶Š'=>'á¶Š','á¶‹'=>'á¶‹','á¶Œ'=>'á¶Œ','á¶'=>'á¶','á¶Ž'=>'á¶Ž','á¶'=>'á¶','á¶'=>'á¶','á¶‘'=>'á¶‘','á¶’'=>'á¶’','á¶“'=>'á¶“','á¶”'=>'á¶”','á¶•'=>'á¶•','á¶–'=>'á¶–','á¶—'=>'á¶—','ᶘ'=>'ᶘ','á¶™'=>'á¶™','á¶š'=>'á¶š','á¶›'=>'á¶›','á¶œ'=>'á¶œ','á¶'=>'á¶','á¶ž'=>'á¶ž','á¶Ÿ'=>'á¶Ÿ','á¶ '=>'á¶ ','á¶¡'=>'á¶¡','á¶¢'=>'á¶¢','á¶£'=>'á¶£','ᶤ'=>'ᶤ','á¶¥'=>'á¶¥','ᶦ'=>'ᶦ','á¶§'=>'á¶§','ᶨ'=>'ᶨ','á¶©'=>'á¶©','ᶪ'=>'ᶪ','á¶«'=>'á¶«','ᶬ'=>'ᶬ','á¶'=>'á¶','á¶®'=>'á¶®','ᶯ'=>'ᶯ','á¶°'=>'á¶°','á¶±'=>'á¶±','á¶²'=>'á¶²','á¶³'=>'á¶³','á¶´'=>'á¶´','á¶µ'=>'á¶µ','á¶¶'=>'á¶¶','á¶·'=>'á¶·','ᶸ'=>'ᶸ','á¶¹'=>'á¶¹','ᶺ'=>'ᶺ','á¶»'=>'á¶»','á¶¼'=>'á¶¼','á¶½'=>'á¶½','á¶¾'=>'á¶¾','á¶¿'=>'á¶¿','á·€'=>'á·€','á·'=>'á·','á·‚'=>'á·‚','á·ƒ'=>'á·ƒ','á·„'=>'á·„','á·…'=>'á·…','á·†'=>'á·†','á·‡'=>'á·‡','á·ˆ'=>'á·ˆ','á·‰'=>'á·‰','á·Š'=>'á·Š','á·¾'=>'á·¾','á·¿'=>'á·¿','Ḁ'=>'á¸','á¸'=>'á¸','Ḃ'=>'ḃ','ḃ'=>'ḃ','Ḅ'=>'ḅ','ḅ'=>'ḅ','Ḇ'=>'ḇ','ḇ'=>'ḇ','Ḉ'=>'ḉ','ḉ'=>'ḉ','Ḋ'=>'ḋ','ḋ'=>'ḋ','Ḍ'=>'á¸','á¸'=>'á¸','Ḏ'=>'á¸','á¸'=>'á¸','á¸'=>'ḑ','ḑ'=>'ḑ','Ḓ'=>'ḓ','ḓ'=>'ḓ','Ḕ'=>'ḕ','ḕ'=>'ḕ','Ḗ'=>'ḗ','ḗ'=>'ḗ','Ḙ'=>'ḙ','ḙ'=>'ḙ','Ḛ'=>'ḛ','ḛ'=>'ḛ','Ḝ'=>'á¸','á¸'=>'á¸','Ḟ'=>'ḟ','ḟ'=>'ḟ','Ḡ'=>'ḡ','ḡ'=>'ḡ','Ḣ'=>'ḣ','ḣ'=>'ḣ','Ḥ'=>'ḥ','ḥ'=>'ḥ','Ḧ'=>'ḧ','ḧ'=>'ḧ','Ḩ'=>'ḩ','ḩ'=>'ḩ','Ḫ'=>'ḫ','ḫ'=>'ḫ','Ḭ'=>'á¸','á¸'=>'á¸','Ḯ'=>'ḯ','ḯ'=>'ḯ','Ḱ'=>'ḱ','ḱ'=>'ḱ','Ḳ'=>'ḳ','ḳ'=>'ḳ','Ḵ'=>'ḵ','ḵ'=>'ḵ','Ḷ'=>'ḷ','ḷ'=>'ḷ','Ḹ'=>'ḹ','ḹ'=>'ḹ','Ḻ'=>'ḻ','ḻ'=>'ḻ','Ḽ'=>'ḽ','ḽ'=>'ḽ','Ḿ'=>'ḿ','ḿ'=>'ḿ','á¹€'=>'á¹','á¹'=>'á¹','Ṃ'=>'ṃ','ṃ'=>'ṃ','Ṅ'=>'á¹…','á¹…'=>'á¹…','Ṇ'=>'ṇ','ṇ'=>'ṇ','Ṉ'=>'ṉ','ṉ'=>'ṉ','Ṋ'=>'ṋ','ṋ'=>'ṋ','Ṍ'=>'á¹','á¹'=>'á¹','Ṏ'=>'á¹','á¹'=>'á¹','á¹'=>'ṑ','ṑ'=>'ṑ','á¹’'=>'ṓ','ṓ'=>'ṓ','á¹”'=>'ṕ','ṕ'=>'ṕ','á¹–'=>'á¹—','á¹—'=>'á¹—','Ṙ'=>'á¹™','á¹™'=>'á¹™','Ṛ'=>'á¹›','á¹›'=>'á¹›','Ṝ'=>'á¹','á¹'=>'á¹','Ṟ'=>'ṟ','ṟ'=>'ṟ','á¹ '=>'ṡ','ṡ'=>'ṡ','á¹¢'=>'á¹£','á¹£'=>'á¹£','Ṥ'=>'á¹¥','á¹¥'=>'á¹¥','Ṧ'=>'á¹§','á¹§'=>'á¹§','Ṩ'=>'ṩ','ṩ'=>'ṩ','Ṫ'=>'ṫ','ṫ'=>'ṫ','Ṭ'=>'á¹','á¹'=>'á¹','á¹®'=>'ṯ','ṯ'=>'ṯ','á¹°'=>'á¹±','á¹±'=>'á¹±','á¹²'=>'á¹³','á¹³'=>'á¹³','á¹´'=>'á¹µ','á¹µ'=>'á¹µ','á¹¶'=>'á¹·','á¹·'=>'á¹·','Ṹ'=>'á¹¹','á¹¹'=>'á¹¹','Ṻ'=>'á¹»','á¹»'=>'á¹»','á¹¼'=>'á¹½','á¹½'=>'á¹½','á¹¾'=>'ṿ','ṿ'=>'ṿ','Ẁ'=>'áº','áº'=>'áº','Ẃ'=>'ẃ','ẃ'=>'ẃ','Ẅ'=>'ẅ','ẅ'=>'ẅ','Ẇ'=>'ẇ','ẇ'=>'ẇ','Ẉ'=>'ẉ','ẉ'=>'ẉ','Ẋ'=>'ẋ','ẋ'=>'ẋ','Ẍ'=>'áº','áº'=>'áº','Ẏ'=>'áº','áº'=>'áº','áº'=>'ẑ','ẑ'=>'ẑ','Ẓ'=>'ẓ','ẓ'=>'ẓ','Ẕ'=>'ẕ','ẕ'=>'ẕ','ẖ'=>'ẖ','ẗ'=>'ẗ','ẘ'=>'ẘ','ẙ'=>'ẙ','ẚ'=>'ẚ','ẛ'=>'ẛ','Ạ'=>'ạ','ạ'=>'ạ','Ả'=>'ả','ả'=>'ả','Ấ'=>'ấ','ấ'=>'ấ','Ầ'=>'ầ','ầ'=>'ầ','Ẩ'=>'ẩ','ẩ'=>'ẩ','Ẫ'=>'ẫ','ẫ'=>'ẫ','Ậ'=>'áº','áº'=>'áº','Ắ'=>'ắ','ắ'=>'ắ','Ằ'=>'ằ','ằ'=>'ằ','Ẳ'=>'ẳ','ẳ'=>'ẳ','Ẵ'=>'ẵ','ẵ'=>'ẵ','Ặ'=>'ặ','ặ'=>'ặ','Ẹ'=>'ẹ','ẹ'=>'ẹ','Ẻ'=>'ẻ','ẻ'=>'ẻ','Ẽ'=>'ẽ','ẽ'=>'ẽ','Ế'=>'ế','ế'=>'ế','Ề'=>'á»','á»'=>'á»','Ể'=>'ể','ể'=>'ể','Ễ'=>'á»…','á»…'=>'á»…','Ệ'=>'ệ','ệ'=>'ệ','Ỉ'=>'ỉ','ỉ'=>'ỉ','Ị'=>'ị','ị'=>'ị','Ọ'=>'á»','á»'=>'á»','Ỏ'=>'á»','á»'=>'á»','á»'=>'ố','ố'=>'ố','á»’'=>'ồ','ồ'=>'ồ','á»”'=>'ổ','ổ'=>'ổ','á»–'=>'á»—','á»—'=>'á»—','Ộ'=>'á»™','á»™'=>'á»™','Ớ'=>'á»›','á»›'=>'á»›','Ờ'=>'á»','á»'=>'á»','Ở'=>'ở','ở'=>'ở','á» '=>'ỡ','ỡ'=>'ỡ','Ợ'=>'ợ','ợ'=>'ợ','Ụ'=>'ụ','ụ'=>'ụ','Ủ'=>'á»§','á»§'=>'á»§','Ứ'=>'ứ','ứ'=>'ứ','Ừ'=>'ừ','ừ'=>'ừ','Ử'=>'á»','á»'=>'á»','á»®'=>'ữ','ữ'=>'ữ','á»°'=>'á»±','á»±'=>'á»±','Ỳ'=>'ỳ','ỳ'=>'ỳ','á»´'=>'ỵ','ỵ'=>'ỵ','á»¶'=>'á»·','á»·'=>'á»·','Ỹ'=>'ỹ','ỹ'=>'ỹ','á¼€'=>'á¼€','á¼'=>'á¼','ἂ'=>'ἂ','ἃ'=>'ἃ','ἄ'=>'ἄ','á¼…'=>'á¼…','ἆ'=>'ἆ','ἇ'=>'ἇ','Ἀ'=>'á¼€','Ἁ'=>'á¼','Ἂ'=>'ἂ','Ἃ'=>'ἃ','Ἄ'=>'ἄ','á¼'=>'á¼…','Ἆ'=>'ἆ','á¼'=>'ἇ','á¼'=>'á¼','ἑ'=>'ἑ','á¼’'=>'á¼’','ἓ'=>'ἓ','á¼”'=>'á¼”','ἕ'=>'ἕ','Ἐ'=>'á¼','á¼™'=>'ἑ','Ἒ'=>'á¼’','á¼›'=>'ἓ','Ἔ'=>'á¼”','á¼'=>'ἕ','á¼ '=>'á¼ ','ἡ'=>'ἡ','á¼¢'=>'á¼¢','á¼£'=>'á¼£','ἤ'=>'ἤ','á¼¥'=>'á¼¥','ἦ'=>'ἦ','á¼§'=>'á¼§','Ἠ'=>'á¼ ','Ἡ'=>'ἡ','Ἢ'=>'á¼¢','Ἣ'=>'á¼£','Ἤ'=>'ἤ','á¼'=>'á¼¥','á¼®'=>'ἦ','Ἧ'=>'á¼§','á¼°'=>'á¼°','á¼±'=>'á¼±','á¼²'=>'á¼²','á¼³'=>'á¼³','á¼´'=>'á¼´','á¼µ'=>'á¼µ','á¼¶'=>'á¼¶','á¼·'=>'á¼·','Ἰ'=>'á¼°','á¼¹'=>'á¼±','Ἲ'=>'á¼²','á¼»'=>'á¼³','á¼¼'=>'á¼´','á¼½'=>'á¼µ','á¼¾'=>'á¼¶','Ἷ'=>'á¼·','á½€'=>'á½€','á½'=>'á½','ὂ'=>'ὂ','ὃ'=>'ὃ','ὄ'=>'ὄ','á½…'=>'á½…','Ὀ'=>'á½€','Ὁ'=>'á½','Ὂ'=>'ὂ','Ὃ'=>'ὃ','Ὄ'=>'ὄ','á½'=>'á½…','á½'=>'á½','ὑ'=>'ὑ','á½’'=>'á½’','ὓ'=>'ὓ','á½”'=>'á½”','ὕ'=>'ὕ','á½–'=>'á½–','á½—'=>'á½—','á½™'=>'ὑ','á½›'=>'ὓ','á½'=>'ὕ','Ὗ'=>'á½—','á½ '=>'á½ ','ὡ'=>'ὡ','á½¢'=>'á½¢','á½£'=>'á½£','ὤ'=>'ὤ','á½¥'=>'á½¥','ὦ'=>'ὦ','á½§'=>'á½§','Ὠ'=>'á½ ','Ὡ'=>'ὡ','Ὢ'=>'á½¢','Ὣ'=>'á½£','Ὤ'=>'ὤ','á½'=>'á½¥','á½®'=>'ὦ','Ὧ'=>'á½§','á½°'=>'á½°','á½±'=>'á½±','á½²'=>'á½²','á½³'=>'á½³','á½´'=>'á½´','á½µ'=>'á½µ','á½¶'=>'á½¶','á½·'=>'á½·','ὸ'=>'ὸ','á½¹'=>'á½¹','ὺ'=>'ὺ','á½»'=>'á½»','á½¼'=>'á½¼','á½½'=>'á½½','á¾€'=>'á¾€','á¾'=>'á¾','ᾂ'=>'ᾂ','ᾃ'=>'ᾃ','ᾄ'=>'ᾄ','á¾…'=>'á¾…','ᾆ'=>'ᾆ','ᾇ'=>'ᾇ','ᾈ'=>'á¾€','ᾉ'=>'á¾','ᾊ'=>'ᾂ','ᾋ'=>'ᾃ','ᾌ'=>'ᾄ','á¾'=>'á¾…','ᾎ'=>'ᾆ','á¾'=>'ᾇ','á¾'=>'á¾','ᾑ'=>'ᾑ','á¾’'=>'á¾’','ᾓ'=>'ᾓ','á¾”'=>'á¾”','ᾕ'=>'ᾕ','á¾–'=>'á¾–','á¾—'=>'á¾—','ᾘ'=>'á¾','á¾™'=>'ᾑ','ᾚ'=>'á¾’','á¾›'=>'ᾓ','ᾜ'=>'á¾”','á¾'=>'ᾕ','ᾞ'=>'á¾–','ᾟ'=>'á¾—','á¾ '=>'á¾ ','ᾡ'=>'ᾡ','á¾¢'=>'á¾¢','á¾£'=>'á¾£','ᾤ'=>'ᾤ','á¾¥'=>'á¾¥','ᾦ'=>'ᾦ','á¾§'=>'á¾§','ᾨ'=>'á¾ ','ᾩ'=>'ᾡ','ᾪ'=>'á¾¢','ᾫ'=>'á¾£','ᾬ'=>'ᾤ','á¾'=>'á¾¥','á¾®'=>'ᾦ','ᾯ'=>'á¾§','á¾°'=>'á¾°','á¾±'=>'á¾±','á¾²'=>'á¾²','á¾³'=>'á¾³','á¾´'=>'á¾´','á¾¶'=>'á¾¶','á¾·'=>'á¾·','Ᾰ'=>'á¾°','á¾¹'=>'á¾±','Ὰ'=>'á½°','á¾»'=>'á½±','á¾¼'=>'á¾³','á¾¾'=>'á¾¾','á¿‚'=>'á¿‚','ῃ'=>'ῃ','á¿„'=>'á¿„','ῆ'=>'ῆ','ῇ'=>'ῇ','Ὲ'=>'á½²','Έ'=>'á½³','Ὴ'=>'á½´','á¿‹'=>'á½µ','ῌ'=>'ῃ','á¿'=>'á¿','á¿‘'=>'á¿‘','á¿’'=>'á¿’','á¿“'=>'á¿“','á¿–'=>'á¿–','á¿—'=>'á¿—','Ῐ'=>'á¿','á¿™'=>'á¿‘','Ὶ'=>'á½¶','á¿›'=>'á½·','á¿ '=>'á¿ ','á¿¡'=>'á¿¡','á¿¢'=>'á¿¢','á¿£'=>'á¿£','ῤ'=>'ῤ','á¿¥'=>'á¿¥','ῦ'=>'ῦ','á¿§'=>'á¿§','Ῠ'=>'á¿ ','á¿©'=>'á¿¡','Ὺ'=>'ὺ','á¿«'=>'á½»','Ῥ'=>'á¿¥','ῲ'=>'ῲ','ῳ'=>'ῳ','á¿´'=>'á¿´','á¿¶'=>'á¿¶','á¿·'=>'á¿·','Ὸ'=>'ὸ','Ό'=>'á½¹','Ὼ'=>'á½¼','á¿»'=>'á½½','ῼ'=>'ῳ');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_31.php b/phpBB/includes/utf/data/search_indexer_31.php deleted file mode 100644 index 191365a313..0000000000 --- a/phpBB/includes/utf/data/search_indexer_31.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('豈'=>'豈','ï¤'=>'ï¤','車'=>'車','賈'=>'賈','滑'=>'滑','串'=>'串','句'=>'句','龜'=>'龜','龜'=>'龜','契'=>'契','金'=>'金','喇'=>'喇','奈'=>'奈','ï¤'=>'ï¤','癩'=>'癩','ï¤'=>'ï¤','ï¤'=>'ï¤','螺'=>'螺','裸'=>'裸','邏'=>'邏','樂'=>'樂','洛'=>'洛','烙'=>'烙','珞'=>'珞','落'=>'落','酪'=>'酪','駱'=>'駱','亂'=>'亂','卵'=>'卵','ï¤'=>'ï¤','爛'=>'爛','蘭'=>'蘭','ï¤ '=>'ï¤ ','嵐'=>'嵐','濫'=>'濫','藍'=>'藍','襤'=>'襤','拉'=>'拉','臘'=>'臘','蠟'=>'蠟','廊'=>'廊','朗'=>'朗','浪'=>'浪','狼'=>'狼','郎'=>'郎','ï¤'=>'ï¤','冷'=>'冷','勞'=>'勞','擄'=>'擄','櫓'=>'櫓','爐'=>'爐','盧'=>'盧','老'=>'老','蘆'=>'蘆','虜'=>'虜','路'=>'路','露'=>'露','魯'=>'魯','鷺'=>'鷺','碌'=>'碌','祿'=>'祿','綠'=>'綠','菉'=>'菉','錄'=>'錄','鹿'=>'鹿','ï¥'=>'ï¥','壟'=>'壟','弄'=>'弄','籠'=>'籠','聾'=>'聾','牢'=>'牢','磊'=>'磊','賂'=>'賂','雷'=>'雷','壘'=>'壘','屢'=>'屢','樓'=>'樓','ï¥'=>'ï¥','漏'=>'漏','ï¥'=>'ï¥','ï¥'=>'ï¥','陋'=>'陋','勒'=>'勒','肋'=>'肋','凜'=>'凜','凌'=>'凌','稜'=>'稜','綾'=>'綾','菱'=>'菱','陵'=>'陵','讀'=>'讀','拏'=>'拏','樂'=>'樂','ï¥'=>'ï¥','丹'=>'丹','寧'=>'寧','ï¥ '=>'ï¥ ','率'=>'率','異'=>'異','北'=>'北','磻'=>'磻','便'=>'便','復'=>'復','不'=>'不','泌'=>'泌','數'=>'數','索'=>'索','參'=>'參','塞'=>'塞','ï¥'=>'ï¥','葉'=>'葉','說'=>'說','殺'=>'殺','辰'=>'辰','沈'=>'沈','拾'=>'拾','若'=>'若','掠'=>'掠','略'=>'略','亮'=>'亮','兩'=>'兩','凉'=>'凉','梁'=>'梁','糧'=>'糧','良'=>'良','諒'=>'諒','量'=>'量','勵'=>'勵','呂'=>'呂','ï¦'=>'ï¦','廬'=>'廬','旅'=>'旅','濾'=>'濾','礪'=>'礪','閭'=>'閭','驪'=>'驪','麗'=>'麗','黎'=>'黎','力'=>'力','曆'=>'曆','歷'=>'歷','ï¦'=>'ï¦','年'=>'年','ï¦'=>'ï¦','ï¦'=>'ï¦','撚'=>'撚','漣'=>'漣','煉'=>'煉','璉'=>'璉','秊'=>'秊','練'=>'練','聯'=>'聯','輦'=>'輦','蓮'=>'蓮','連'=>'連','鍊'=>'鍊','列'=>'列','ï¦'=>'ï¦','咽'=>'咽','烈'=>'烈','ï¦ '=>'ï¦ ','說'=>'說','廉'=>'廉','念'=>'念','捻'=>'捻','殮'=>'殮','簾'=>'簾','獵'=>'獵','令'=>'令','囹'=>'囹','寧'=>'寧','嶺'=>'嶺','怜'=>'怜','ï¦'=>'ï¦','瑩'=>'瑩','羚'=>'羚','聆'=>'聆','鈴'=>'鈴','零'=>'零','靈'=>'靈','領'=>'領','例'=>'例','禮'=>'禮','醴'=>'醴','隸'=>'隸','惡'=>'惡','了'=>'了','僚'=>'僚','寮'=>'寮','尿'=>'尿','料'=>'料','樂'=>'樂','ï§€'=>'ï§€','ï§'=>'ï§','ï§‚'=>'ï§‚','遼'=>'遼','ï§„'=>'ï§„','ï§…'=>'ï§…','阮'=>'阮','劉'=>'劉','杻'=>'杻','柳'=>'柳','ï§Š'=>'ï§Š','ï§‹'=>'ï§‹','ï§Œ'=>'ï§Œ','ï§'=>'ï§','ï§Ž'=>'ï§Ž','ï§'=>'ï§','ï§'=>'ï§','ï§‘'=>'ï§‘','ï§’'=>'ï§’','ï§“'=>'ï§“','ï§”'=>'ï§”','ï§•'=>'ï§•','ï§–'=>'ï§–','ï§—'=>'ï§—','律'=>'律','ï§™'=>'ï§™','ï§š'=>'ï§š','ï§›'=>'ï§›','ï§œ'=>'ï§œ','ï§'=>'ï§','ï§ž'=>'ï§ž','ï§Ÿ'=>'ï§Ÿ','ï§ '=>'ï§ ','ï§¡'=>'ï§¡','ï§¢'=>'ï§¢','ï§£'=>'ï§£','理'=>'理','ï§¥'=>'ï§¥','罹'=>'罹','ï§§'=>'ï§§','裡'=>'裡','ï§©'=>'ï§©','離'=>'離','ï§«'=>'ï§«','溺'=>'溺','ï§'=>'ï§','ï§®'=>'ï§®','璘'=>'璘','ï§°'=>'ï§°','ï§±'=>'ï§±','ï§²'=>'ï§²','ï§³'=>'ï§³','ï§´'=>'ï§´','ï§µ'=>'ï§µ','ï§¶'=>'ï§¶','ï§·'=>'ï§·','笠'=>'笠','ï§¹'=>'ï§¹','狀'=>'狀','ï§»'=>'ï§»','ï§¼'=>'ï§¼','ï§½'=>'ï§½','ï§¾'=>'ï§¾','ï§¿'=>'ï§¿','切'=>'切','ï¨'=>'ï¨','拓'=>'拓','糖'=>'糖','宅'=>'宅','洞'=>'洞','暴'=>'暴','輻'=>'輻','行'=>'行','降'=>'降','見'=>'見','廓'=>'廓','兀'=>'兀','ï¨'=>'ï¨','﨎'=>'﨎','ï¨'=>'ï¨','ï¨'=>'ï¨','﨑'=>'﨑','晴'=>'晴','﨓'=>'﨓','﨔'=>'﨔','凞'=>'凞','猪'=>'猪','益'=>'益','礼'=>'礼','神'=>'神','祥'=>'祥','福'=>'福','靖'=>'靖','ï¨'=>'ï¨','羽'=>'羽','﨟'=>'﨟','ï¨ '=>'ï¨ ','﨡'=>'﨡','諸'=>'諸','﨣'=>'﨣','﨤'=>'﨤','逸'=>'逸','都'=>'都','﨧'=>'﨧','﨨'=>'﨨','﨩'=>'﨩','飯'=>'飯','飼'=>'飼','館'=>'館','ï¨'=>'ï¨','侮'=>'侮','僧'=>'僧','免'=>'免','勉'=>'勉','勤'=>'勤','卑'=>'卑','喝'=>'喝','嘆'=>'嘆','器'=>'器','塀'=>'塀','墨'=>'墨','層'=>'層','屮'=>'屮','悔'=>'悔','慨'=>'慨','憎'=>'憎','ï©€'=>'ï©€','ï©'=>'ï©','ï©‚'=>'ï©‚','暑'=>'暑','ï©„'=>'ï©„','ï©…'=>'ï©…','渚'=>'渚','漢'=>'漢','煮'=>'煮','爫'=>'爫','琢'=>'琢','ï©‹'=>'ï©‹','社'=>'社','ï©'=>'ï©','祈'=>'祈','ï©'=>'ï©','ï©'=>'ï©','ï©‘'=>'ï©‘','ï©’'=>'ï©’','ï©“'=>'ï©“','ï©”'=>'ï©”','ï©•'=>'ï©•','ï©–'=>'ï©–','ï©—'=>'ï©—','縉'=>'縉','ï©™'=>'ï©™','署'=>'署','ï©›'=>'ï©›','臭'=>'臭','ï©'=>'ï©','艹'=>'艹','著'=>'著','ï© '=>'ï© ','ï©¡'=>'ï©¡','ï©¢'=>'ï©¢','ï©£'=>'ï©£','賓'=>'賓','ï©¥'=>'ï©¥','辶'=>'辶','ï©§'=>'ï©§','難'=>'難','ï©©'=>'ï©©','頻'=>'頻','ï©°'=>'ï©°','况'=>'况','全'=>'全','侀'=>'侀','ï©´'=>'ï©´','冀'=>'冀','ï©¶'=>'ï©¶','ï©·'=>'ï©·','喝'=>'喝','啕'=>'啕','喙'=>'喙','ï©»'=>'ï©»','塚'=>'塚','墳'=>'墳','奄'=>'奄','ï©¿'=>'ï©¿','婢'=>'婢','ïª'=>'ïª','廒'=>'廒','廙'=>'廙','彩'=>'彩','徭'=>'徭','惘'=>'惘','慎'=>'慎','愈'=>'愈','憎'=>'憎','慠'=>'慠','懲'=>'懲','戴'=>'戴','ïª'=>'ïª','搜'=>'搜','ïª'=>'ïª','ïª'=>'ïª','晴'=>'晴','朗'=>'朗','望'=>'望','杖'=>'杖','歹'=>'歹','殺'=>'殺','流'=>'流','滛'=>'滛','滋'=>'滋','漢'=>'漢','瀞'=>'瀞','煮'=>'煮','ïª'=>'ïª','爵'=>'爵','犯'=>'犯','ïª '=>'ïª ','瑱'=>'瑱','甆'=>'甆','画'=>'画','瘝'=>'瘝','瘟'=>'瘟','益'=>'益','盛'=>'盛','直'=>'直','睊'=>'睊','着'=>'着','磌'=>'磌','窱'=>'窱','ïª'=>'ïª','类'=>'类','絛'=>'絛','練'=>'練','缾'=>'缾','者'=>'者','荒'=>'荒','華'=>'華','蝹'=>'蝹','襁'=>'襁','覆'=>'覆','視'=>'視','調'=>'調','諸'=>'諸','請'=>'請','謁'=>'謁','諾'=>'諾','諭'=>'諭','謹'=>'謹','ï«€'=>'ï«€','ï«'=>'ï«','ï«‚'=>'ï«‚','遲'=>'遲','ï«„'=>'ï«„','ï«…'=>'ï«…','陼'=>'陼','難'=>'難','靖'=>'靖','韛'=>'韛','響'=>'響','ï«‹'=>'ï«‹','頻'=>'頻','ï«'=>'ï«','龜'=>'龜','ï«'=>'ï«','ï«'=>'ï«','ï«‘'=>'ï«‘','ï«’'=>'ï«’','ï«“'=>'ï«“','ï«”'=>'ï«”','ï«•'=>'ï«•','ï«–'=>'ï«–','ï«—'=>'ï«—','齃'=>'齃','ï«™'=>'ï«™','ff'=>'ff','ï¬'=>'fi','fl'=>'fl','ffi'=>'ffi','ffl'=>'ffl','ſt'=>'ſt','st'=>'st','ﬓ'=>'ﬓ','ﬔ'=>'ﬔ','ﬕ'=>'ﬕ','ﬖ'=>'ﬖ','ﬗ'=>'ﬗ','ï¬'=>'ï¬','ﬞ'=>'ﬞ','ײַ'=>'ײַ','ï¬ '=>'ï¬ ','ﬡ'=>'ﬡ','ﬢ'=>'ﬢ','ﬣ'=>'ﬣ','ﬤ'=>'ﬤ','ﬥ'=>'ﬥ','ﬦ'=>'ﬦ','ﬧ'=>'ﬧ','ﬨ'=>'ﬨ','שׁ'=>'שׁ','שׂ'=>'שׂ','שּׁ'=>'שּׁ','ï¬'=>'ï¬','אַ'=>'אַ','אָ'=>'אָ','אּ'=>'אּ','בּ'=>'בּ','גּ'=>'גּ','דּ'=>'דּ','הּ'=>'הּ','וּ'=>'וּ','זּ'=>'זּ','טּ'=>'טּ','יּ'=>'יּ','ךּ'=>'ךּ','כּ'=>'כּ','לּ'=>'לּ','מּ'=>'מּ','ï€'=>'ï€','ï'=>'ï','ïƒ'=>'ïƒ','ï„'=>'ï„','ï†'=>'ï†','ï‡'=>'ï‡','ïˆ'=>'ïˆ','ï‰'=>'ï‰','ïŠ'=>'ïŠ','ï‹'=>'ï‹','ïŒ'=>'ïŒ','ï'=>'ï','ïŽ'=>'ïŽ','ï'=>'ï','ï'=>'ï','ï‘'=>'ï‘','ï’'=>'ï’','ï“'=>'ï“','ï”'=>'ï”','ï•'=>'ï•','ï–'=>'ï–','ï—'=>'ï—','ï˜'=>'ï˜','ï™'=>'ï™','ïš'=>'ïš','ï›'=>'ï›','ïœ'=>'ïœ','ï'=>'ï','ïž'=>'ïž','ïŸ'=>'ïŸ','ï '=>'ï ','ï¡'=>'ï¡','ï¢'=>'ï¢','ï£'=>'ï£','ï¤'=>'ï¤','ï¥'=>'ï¥','ï¦'=>'ï¦','ï§'=>'ï§','ï¨'=>'ï¨','ï©'=>'ï©','ïª'=>'ïª','ï«'=>'ï«','ï¬'=>'ï¬','ï'=>'ï','ï®'=>'ï®','ï¯'=>'ï¯','ï°'=>'ï°','ï±'=>'ï±','ï²'=>'ï²','ï³'=>'ï³','ï´'=>'ï´','ïµ'=>'ïµ','ï¶'=>'ï¶','ï·'=>'ï·','ï¸'=>'ï¸','ï¹'=>'ï¹','ïº'=>'ïº','ï»'=>'ï»','ï¼'=>'ï¼','ï½'=>'ï½','ï¾'=>'ï¾','ï¿'=>'ï¿','ﮀ'=>'ﮀ','ï®'=>'ï®','ﮂ'=>'ﮂ','ﮃ'=>'ﮃ','ﮄ'=>'ﮄ','ï®…'=>'ï®…','ﮆ'=>'ﮆ','ﮇ'=>'ﮇ','ﮈ'=>'ﮈ','ﮉ'=>'ﮉ','ﮊ'=>'ﮊ','ﮋ'=>'ﮋ','ﮌ'=>'ﮌ','ï®'=>'ï®','ﮎ'=>'ﮎ','ï®'=>'ï®','ï®'=>'ï®','ﮑ'=>'ﮑ','ï®’'=>'ï®’','ﮓ'=>'ﮓ','ï®”'=>'ï®”','ﮕ'=>'ﮕ','ï®–'=>'ï®–','ï®—'=>'ï®—','ﮘ'=>'ﮘ','ï®™'=>'ï®™','ﮚ'=>'ﮚ','ï®›'=>'ï®›','ﮜ'=>'ﮜ','ï®'=>'ï®','ﮞ'=>'ﮞ','ﮟ'=>'ﮟ','ï® '=>'ï® ','ﮡ'=>'ﮡ','ﮢ'=>'ﮢ','ﮣ'=>'ﮣ','ﮤ'=>'ﮤ','ﮥ'=>'ﮥ','ﮦ'=>'ﮦ','ï®§'=>'ï®§','ﮨ'=>'ﮨ','ﮩ'=>'ﮩ','ﮪ'=>'ﮪ','ﮫ'=>'ﮫ','ﮬ'=>'ﮬ','ï®'=>'ï®','ï®®'=>'ï®®','ﮯ'=>'ﮯ','ï®°'=>'ï®°','ï®±'=>'ï®±','ﯓ'=>'ﯓ','ﯔ'=>'ﯔ','ﯕ'=>'ﯕ','ﯖ'=>'ﯖ','ﯗ'=>'ﯗ','ﯘ'=>'ﯘ','ﯙ'=>'ﯙ','ﯚ'=>'ﯚ','ﯛ'=>'ﯛ','ﯜ'=>'ﯜ','ï¯'=>'ï¯','ﯞ'=>'ﯞ','ﯟ'=>'ﯟ','ï¯ '=>'ï¯ ','ﯡ'=>'ﯡ','ﯢ'=>'ﯢ','ﯣ'=>'ﯣ','ﯤ'=>'ﯤ','ﯥ'=>'ﯥ','ﯦ'=>'ﯦ','ﯧ'=>'ﯧ','ﯨ'=>'ﯨ','ﯩ'=>'ﯩ','ﯪ'=>'ﯪ','ﯫ'=>'ﯫ','ﯬ'=>'ﯬ','ï¯'=>'ï¯','ﯮ'=>'ﯮ','ﯯ'=>'ﯯ','ﯰ'=>'ﯰ','ﯱ'=>'ﯱ','ﯲ'=>'ﯲ','ﯳ'=>'ﯳ','ﯴ'=>'ﯴ','ﯵ'=>'ﯵ','ﯶ'=>'ﯶ','ﯷ'=>'ﯷ','ﯸ'=>'ﯸ','ﯹ'=>'ﯹ','ﯺ'=>'ﯺ','ﯻ'=>'ﯻ','ﯼ'=>'ﯼ','ﯽ'=>'ﯽ','ﯾ'=>'ﯾ','ﯿ'=>'ﯿ','ï°€'=>'ï°€','ï°'=>'ï°','ï°‚'=>'ï°‚','ï°ƒ'=>'ï°ƒ','ï°„'=>'ï°„','ï°…'=>'ï°…','ï°†'=>'ï°†','ï°‡'=>'ï°‡','ï°ˆ'=>'ï°ˆ','ï°‰'=>'ï°‰','ï°Š'=>'ï°Š','ï°‹'=>'ï°‹','ï°Œ'=>'ï°Œ','ï°'=>'ï°','ï°Ž'=>'ï°Ž','ï°'=>'ï°','ï°'=>'ï°','ï°‘'=>'ï°‘','ï°’'=>'ï°’','ï°“'=>'ï°“','ï°”'=>'ï°”','ï°•'=>'ï°•','ï°–'=>'ï°–','ï°—'=>'ï°—','ï°˜'=>'ï°˜','ï°™'=>'ï°™','ï°š'=>'ï°š','ï°›'=>'ï°›','ï°œ'=>'ï°œ','ï°'=>'ï°','ï°ž'=>'ï°ž','ï°Ÿ'=>'ï°Ÿ','ï° '=>'ï° ','ï°¡'=>'ï°¡','ï°¢'=>'ï°¢','ï°£'=>'ï°£','ï°¤'=>'ï°¤','ï°¥'=>'ï°¥','ï°¦'=>'ï°¦','ï°§'=>'ï°§','ï°¨'=>'ï°¨','ï°©'=>'ï°©','ï°ª'=>'ï°ª','ï°«'=>'ï°«','ï°¬'=>'ï°¬','ï°'=>'ï°','ï°®'=>'ï°®','ï°¯'=>'ï°¯','ï°°'=>'ï°°','ï°±'=>'ï°±','ï°²'=>'ï°²','ï°³'=>'ï°³','ï°´'=>'ï°´','ï°µ'=>'ï°µ','ï°¶'=>'ï°¶','ï°·'=>'ï°·','ï°¸'=>'ï°¸','ï°¹'=>'ï°¹','ï°º'=>'ï°º','ï°»'=>'ï°»','ï°¼'=>'ï°¼','ï°½'=>'ï°½','ï°¾'=>'ï°¾','ï°¿'=>'ï°¿','ï±€'=>'ï±€','ï±'=>'ï±','ﱂ'=>'ﱂ','ﱃ'=>'ﱃ','ﱄ'=>'ﱄ','ï±…'=>'ï±…','ﱆ'=>'ﱆ','ﱇ'=>'ﱇ','ﱈ'=>'ﱈ','ﱉ'=>'ﱉ','ﱊ'=>'ﱊ','ﱋ'=>'ﱋ','ﱌ'=>'ﱌ','ï±'=>'ï±','ﱎ'=>'ﱎ','ï±'=>'ï±','ï±'=>'ï±','ﱑ'=>'ﱑ','ï±’'=>'ï±’','ﱓ'=>'ﱓ','ï±”'=>'ï±”','ﱕ'=>'ﱕ','ï±–'=>'ï±–','ï±—'=>'ï±—','ﱘ'=>'ﱘ','ï±™'=>'ï±™','ﱚ'=>'ﱚ','ï±›'=>'ï±›','ﱜ'=>'ﱜ','ï±'=>'ï±','ﱞ'=>'ﱞ','ﱟ'=>'ﱟ','ï± '=>'ï± ','ﱡ'=>'ﱡ','ï±¢'=>'ï±¢','ï±£'=>'ï±£','ﱤ'=>'ﱤ','ï±¥'=>'ï±¥','ﱦ'=>'ﱦ','ï±§'=>'ï±§','ﱨ'=>'ﱨ','ﱩ'=>'ﱩ','ﱪ'=>'ﱪ','ﱫ'=>'ﱫ','ﱬ'=>'ﱬ','ï±'=>'ï±','ï±®'=>'ï±®','ﱯ'=>'ﱯ','ï±°'=>'ï±°','ï±±'=>'ï±±','ï±²'=>'ï±²','ï±³'=>'ï±³','ï±´'=>'ï±´','ï±µ'=>'ï±µ','ï±¶'=>'ï±¶','ï±·'=>'ï±·','ﱸ'=>'ﱸ','ï±¹'=>'ï±¹','ﱺ'=>'ﱺ','ï±»'=>'ï±»','ï±¼'=>'ï±¼','ï±½'=>'ï±½','ï±¾'=>'ï±¾','ﱿ'=>'ﱿ','ï²€'=>'ï²€','ï²'=>'ï²','ﲂ'=>'ﲂ','ﲃ'=>'ﲃ','ﲄ'=>'ﲄ','ï²…'=>'ï²…','ﲆ'=>'ﲆ','ﲇ'=>'ﲇ','ﲈ'=>'ﲈ','ﲉ'=>'ﲉ','ﲊ'=>'ﲊ','ﲋ'=>'ﲋ','ﲌ'=>'ﲌ','ï²'=>'ï²','ﲎ'=>'ﲎ','ï²'=>'ï²','ï²'=>'ï²','ﲑ'=>'ﲑ','ï²’'=>'ï²’','ﲓ'=>'ﲓ','ï²”'=>'ï²”','ﲕ'=>'ﲕ','ï²–'=>'ï²–','ï²—'=>'ï²—','ﲘ'=>'ﲘ','ï²™'=>'ï²™','ﲚ'=>'ﲚ','ï²›'=>'ï²›','ﲜ'=>'ﲜ','ï²'=>'ï²','ﲞ'=>'ﲞ','ﲟ'=>'ﲟ','ï² '=>'ï² ','ﲡ'=>'ﲡ','ï²¢'=>'ï²¢','ï²£'=>'ï²£','ﲤ'=>'ﲤ','ï²¥'=>'ï²¥','ﲦ'=>'ﲦ','ï²§'=>'ï²§','ﲨ'=>'ﲨ','ﲩ'=>'ﲩ','ﲪ'=>'ﲪ','ﲫ'=>'ﲫ','ﲬ'=>'ﲬ','ï²'=>'ï²','ï²®'=>'ï²®','ﲯ'=>'ﲯ','ï²°'=>'ï²°','ï²±'=>'ï²±','ï²²'=>'ï²²','ï²³'=>'ï²³','ï²´'=>'ï²´','ï²µ'=>'ï²µ','ï²¶'=>'ï²¶','ï²·'=>'ï²·','ﲸ'=>'ﲸ','ï²¹'=>'ï²¹','ﲺ'=>'ﲺ','ï²»'=>'ï²»','ï²¼'=>'ï²¼','ï²½'=>'ï²½','ï²¾'=>'ï²¾','ﲿ'=>'ﲿ','ï³€'=>'ï³€','ï³'=>'ï³','ﳂ'=>'ﳂ','ﳃ'=>'ﳃ','ﳄ'=>'ﳄ','ï³…'=>'ï³…','ﳆ'=>'ﳆ','ﳇ'=>'ﳇ','ﳈ'=>'ﳈ','ﳉ'=>'ﳉ','ﳊ'=>'ﳊ','ﳋ'=>'ﳋ','ﳌ'=>'ﳌ','ï³'=>'ï³','ﳎ'=>'ﳎ','ï³'=>'ï³','ï³'=>'ï³','ﳑ'=>'ﳑ','ï³’'=>'ï³’','ﳓ'=>'ﳓ','ï³”'=>'ï³”','ﳕ'=>'ﳕ','ï³–'=>'ï³–','ï³—'=>'ï³—','ﳘ'=>'ﳘ','ï³™'=>'ï³™','ﳚ'=>'ﳚ','ï³›'=>'ï³›','ﳜ'=>'ﳜ','ï³'=>'ï³','ﳞ'=>'ﳞ','ﳟ'=>'ﳟ','ï³ '=>'ï³ ','ﳡ'=>'ﳡ','ï³¢'=>'ï³¢','ï³£'=>'ï³£','ﳤ'=>'ﳤ','ï³¥'=>'ï³¥','ﳦ'=>'ﳦ','ï³§'=>'ï³§','ﳨ'=>'ﳨ','ﳩ'=>'ﳩ','ﳪ'=>'ﳪ','ﳫ'=>'ﳫ','ﳬ'=>'ﳬ','ï³'=>'ï³','ï³®'=>'ï³®','ﳯ'=>'ﳯ','ï³°'=>'ï³°','ï³±'=>'ï³±','ï³²'=>'ï³²','ï³³'=>'ï³³','ï³´'=>'ï³´','ï³µ'=>'ï³µ','ï³¶'=>'ï³¶','ï³·'=>'ï³·','ﳸ'=>'ﳸ','ï³¹'=>'ï³¹','ﳺ'=>'ﳺ','ï³»'=>'ï³»','ï³¼'=>'ï³¼','ï³½'=>'ï³½','ï³¾'=>'ï³¾','ﳿ'=>'ﳿ','ï´€'=>'ï´€','ï´'=>'ï´','ï´‚'=>'ï´‚','ï´ƒ'=>'ï´ƒ','ï´„'=>'ï´„','ï´…'=>'ï´…','ï´†'=>'ï´†','ï´‡'=>'ï´‡','ï´ˆ'=>'ï´ˆ','ï´‰'=>'ï´‰','ï´Š'=>'ï´Š','ï´‹'=>'ï´‹','ï´Œ'=>'ï´Œ','ï´'=>'ï´','ï´Ž'=>'ï´Ž','ï´'=>'ï´','ï´'=>'ï´','ï´‘'=>'ï´‘','ï´’'=>'ï´’','ï´“'=>'ï´“','ï´”'=>'ï´”','ï´•'=>'ï´•','ï´–'=>'ï´–','ï´—'=>'ï´—','ï´˜'=>'ï´˜','ï´™'=>'ï´™','ï´š'=>'ï´š','ï´›'=>'ï´›','ï´œ'=>'ï´œ','ï´'=>'ï´','ï´ž'=>'ï´ž','ï´Ÿ'=>'ï´Ÿ','ï´ '=>'ï´ ','ï´¡'=>'ï´¡','ï´¢'=>'ï´¢','ï´£'=>'ï´£','ï´¤'=>'ï´¤','ï´¥'=>'ï´¥','ï´¦'=>'ï´¦','ï´§'=>'ï´§','ï´¨'=>'ï´¨','ï´©'=>'ï´©','ï´ª'=>'ï´ª','ï´«'=>'ï´«','ï´¬'=>'ï´¬','ï´'=>'ï´','ï´®'=>'ï´®','ï´¯'=>'ï´¯','ï´°'=>'ï´°','ï´±'=>'ï´±','ï´²'=>'ï´²','ï´³'=>'ï´³','ï´´'=>'ï´´','ï´µ'=>'ï´µ','ï´¶'=>'ï´¶','ï´·'=>'ï´·','ï´¸'=>'ï´¸','ï´¹'=>'ï´¹','ï´º'=>'ï´º','ï´»'=>'ï´»','ï´¼'=>'ï´¼','ï´½'=>'ï´½','ïµ'=>'ïµ','ﵑ'=>'ﵑ','ïµ’'=>'ïµ’','ﵓ'=>'ﵓ','ïµ”'=>'ïµ”','ﵕ'=>'ﵕ','ïµ–'=>'ïµ–','ïµ—'=>'ïµ—','ﵘ'=>'ﵘ','ïµ™'=>'ïµ™','ﵚ'=>'ﵚ','ïµ›'=>'ïµ›','ﵜ'=>'ﵜ','ïµ'=>'ïµ','ﵞ'=>'ﵞ','ﵟ'=>'ﵟ','ïµ '=>'ïµ ','ﵡ'=>'ﵡ','ïµ¢'=>'ïµ¢','ïµ£'=>'ïµ£','ﵤ'=>'ﵤ','ïµ¥'=>'ïµ¥','ﵦ'=>'ﵦ','ïµ§'=>'ïµ§','ﵨ'=>'ﵨ','ﵩ'=>'ﵩ','ﵪ'=>'ﵪ','ﵫ'=>'ﵫ','ﵬ'=>'ﵬ','ïµ'=>'ïµ','ïµ®'=>'ïµ®','ﵯ'=>'ﵯ','ïµ°'=>'ïµ°','ïµ±'=>'ïµ±','ïµ²'=>'ïµ²','ïµ³'=>'ïµ³','ïµ´'=>'ïµ´','ïµµ'=>'ïµµ','ïµ¶'=>'ïµ¶','ïµ·'=>'ïµ·','ﵸ'=>'ﵸ','ïµ¹'=>'ïµ¹','ﵺ'=>'ﵺ','ïµ»'=>'ïµ»','ïµ¼'=>'ïµ¼','ïµ½'=>'ïµ½','ïµ¾'=>'ïµ¾','ﵿ'=>'ﵿ','ï¶€'=>'ï¶€','ï¶'=>'ï¶','ï¶‚'=>'ï¶‚','ﶃ'=>'ﶃ','ï¶„'=>'ï¶„','ï¶…'=>'ï¶…','ﶆ'=>'ﶆ','ﶇ'=>'ﶇ','ﶈ'=>'ﶈ','ﶉ'=>'ﶉ','ï¶Š'=>'ï¶Š','ï¶‹'=>'ï¶‹','ï¶Œ'=>'ï¶Œ','ï¶'=>'ï¶','ï¶Ž'=>'ï¶Ž','ï¶'=>'ï¶','ï¶’'=>'ï¶’','ï¶“'=>'ï¶“','ï¶”'=>'ï¶”','ï¶•'=>'ï¶•','ï¶–'=>'ï¶–','ï¶—'=>'ï¶—','ﶘ'=>'ﶘ','ï¶™'=>'ï¶™','ï¶š'=>'ï¶š','ï¶›'=>'ï¶›','ï¶œ'=>'ï¶œ','ï¶'=>'ï¶','ï¶ž'=>'ï¶ž','ï¶Ÿ'=>'ï¶Ÿ','ï¶ '=>'ï¶ ','ï¶¡'=>'ï¶¡','ï¶¢'=>'ï¶¢','ï¶£'=>'ï¶£','ﶤ'=>'ﶤ','ï¶¥'=>'ï¶¥','ﶦ'=>'ﶦ','ï¶§'=>'ï¶§','ﶨ'=>'ﶨ','ï¶©'=>'ï¶©','ﶪ'=>'ﶪ','ï¶«'=>'ï¶«','ﶬ'=>'ﶬ','ï¶'=>'ï¶','ï¶®'=>'ï¶®','ﶯ'=>'ﶯ','ï¶°'=>'ï¶°','ï¶±'=>'ï¶±','ï¶²'=>'ï¶²','ï¶³'=>'ï¶³','ï¶´'=>'ï¶´','ï¶µ'=>'ï¶µ','ï¶¶'=>'ï¶¶','ï¶·'=>'ï¶·','ﶸ'=>'ﶸ','ï¶¹'=>'ï¶¹','ﶺ'=>'ﶺ','ï¶»'=>'ï¶»','ï¶¼'=>'ï¶¼','ï¶½'=>'ï¶½','ï¶¾'=>'ï¶¾','ï¶¿'=>'ï¶¿','ï·€'=>'ï·€','ï·'=>'ï·','ï·‚'=>'ï·‚','ï·ƒ'=>'ï·ƒ','ï·„'=>'ï·„','ï·…'=>'ï·…','ï·†'=>'ï·†','ï·‡'=>'ï·‡','ï·°'=>'ï·°','ï·±'=>'ï·±','ï·²'=>'ï·²','ï·³'=>'ï·³','ï·´'=>'ï·´','ï·µ'=>'ï·µ','ï·¶'=>'ï·¶','ï··'=>'ï··','ï·¸'=>'ï·¸','ï·¹'=>'ï·¹','ï·º'=>'ï·º','ï·»'=>'ï·»','︀'=>'︀','ï¸'=>'ï¸','︂'=>'︂','︃'=>'︃','︄'=>'︄','︅'=>'︅','︆'=>'︆','︇'=>'︇','︈'=>'︈','︉'=>'︉','︊'=>'︊','︋'=>'︋','︌'=>'︌','ï¸'=>'ï¸','︎'=>'︎','ï¸'=>'ï¸','ï¸ '=>'ï¸ ','︡'=>'︡','︢'=>'︢','︣'=>'︣','ï¹°'=>'ï¹°','ï¹±'=>'ï¹±','ï¹²'=>'ï¹²','ï¹³'=>'ï¹³','ï¹´'=>'ï¹´','ï¹¶'=>'ï¹¶','ï¹·'=>'ï¹·','ﹸ'=>'ﹸ','ï¹¹'=>'ï¹¹','ﹺ'=>'ﹺ','ï¹»'=>'ï¹»','ï¹¼'=>'ï¹¼','ï¹½'=>'ï¹½','ï¹¾'=>'ï¹¾','ﹿ'=>'ﹿ','ﺀ'=>'ﺀ','ïº'=>'ïº','ﺂ'=>'ﺂ','ﺃ'=>'ﺃ','ﺄ'=>'ﺄ','ﺅ'=>'ﺅ','ﺆ'=>'ﺆ','ﺇ'=>'ﺇ','ﺈ'=>'ﺈ','ﺉ'=>'ﺉ','ﺊ'=>'ﺊ','ﺋ'=>'ﺋ','ﺌ'=>'ﺌ','ïº'=>'ïº','ﺎ'=>'ﺎ','ïº'=>'ïº','ïº'=>'ïº','ﺑ'=>'ﺑ','ﺒ'=>'ﺒ','ﺓ'=>'ﺓ','ﺔ'=>'ﺔ','ﺕ'=>'ﺕ','ﺖ'=>'ﺖ','ﺗ'=>'ﺗ','ﺘ'=>'ﺘ','ﺙ'=>'ﺙ','ﺚ'=>'ﺚ','ﺛ'=>'ﺛ','ﺜ'=>'ﺜ','ïº'=>'ïº','ﺞ'=>'ﺞ','ﺟ'=>'ﺟ','ïº '=>'ïº ','ﺡ'=>'ﺡ','ﺢ'=>'ﺢ','ﺣ'=>'ﺣ','ﺤ'=>'ﺤ','ﺥ'=>'ﺥ','ﺦ'=>'ﺦ','ﺧ'=>'ﺧ','ﺨ'=>'ﺨ','ﺩ'=>'ﺩ','ﺪ'=>'ﺪ','ﺫ'=>'ﺫ','ﺬ'=>'ﺬ','ïº'=>'ïº','ﺮ'=>'ﺮ','ﺯ'=>'ﺯ','ﺰ'=>'ﺰ','ﺱ'=>'ﺱ','ﺲ'=>'ﺲ','ﺳ'=>'ﺳ','ﺴ'=>'ﺴ','ﺵ'=>'ﺵ','ﺶ'=>'ﺶ','ﺷ'=>'ﺷ','ﺸ'=>'ﺸ','ﺹ'=>'ﺹ','ﺺ'=>'ﺺ','ﺻ'=>'ﺻ','ﺼ'=>'ﺼ','ﺽ'=>'ﺽ','ﺾ'=>'ﺾ','ﺿ'=>'ﺿ','ﻀ'=>'ﻀ','ï»'=>'ï»','ﻂ'=>'ﻂ','ﻃ'=>'ﻃ','ﻄ'=>'ﻄ','ï»…'=>'ï»…','ﻆ'=>'ﻆ','ﻇ'=>'ﻇ','ﻈ'=>'ﻈ','ﻉ'=>'ﻉ','ﻊ'=>'ﻊ','ﻋ'=>'ﻋ','ﻌ'=>'ﻌ','ï»'=>'ï»','ﻎ'=>'ﻎ','ï»'=>'ï»','ï»'=>'ï»','ﻑ'=>'ﻑ','ï»’'=>'ï»’','ﻓ'=>'ﻓ','ï»”'=>'ï»”','ﻕ'=>'ﻕ','ï»–'=>'ï»–','ï»—'=>'ï»—','ﻘ'=>'ﻘ','ï»™'=>'ï»™','ﻚ'=>'ﻚ','ï»›'=>'ï»›','ﻜ'=>'ﻜ','ï»'=>'ï»','ﻞ'=>'ﻞ','ﻟ'=>'ﻟ','ï» '=>'ï» ','ﻡ'=>'ﻡ','ﻢ'=>'ﻢ','ﻣ'=>'ﻣ','ﻤ'=>'ﻤ','ﻥ'=>'ﻥ','ﻦ'=>'ﻦ','ï»§'=>'ï»§','ﻨ'=>'ﻨ','ﻩ'=>'ﻩ','ﻪ'=>'ﻪ','ﻫ'=>'ﻫ','ﻬ'=>'ﻬ','ï»'=>'ï»','ï»®'=>'ï»®','ﻯ'=>'ﻯ','ï»°'=>'ï»°','ï»±'=>'ï»±','ﻲ'=>'ﻲ','ﻳ'=>'ﻳ','ï»´'=>'ï»´','ﻵ'=>'ﻵ','ï»¶'=>'ï»¶','ï»·'=>'ï»·','ﻸ'=>'ﻸ','ﻹ'=>'ﻹ','ﻺ'=>'ﻺ','ï»»'=>'ï»»','ﻼ'=>'ﻼ','ï¼'=>'0','1'=>'1','ï¼’'=>'2','3'=>'3','ï¼”'=>'4','5'=>'5','ï¼–'=>'6','ï¼—'=>'7','8'=>'8','ï¼™'=>'9','A'=>'ï½','ï¼¢'=>'b','ï¼£'=>'c','D'=>'d','ï¼¥'=>'ï½…','F'=>'f','ï¼§'=>'g','H'=>'h','I'=>'i','J'=>'j','K'=>'k','L'=>'l','ï¼'=>'ï½','ï¼®'=>'n','O'=>'ï½','ï¼°'=>'ï½','ï¼±'=>'q','ï¼²'=>'ï½’','ï¼³'=>'s','ï¼´'=>'ï½”','ï¼µ'=>'u','ï¼¶'=>'ï½–','ï¼·'=>'ï½—','X'=>'x','ï¼¹'=>'ï½™','Z'=>'z','ï½'=>'ï½','b'=>'b','c'=>'c','d'=>'d','ï½…'=>'ï½…','f'=>'f','g'=>'g','h'=>'h','i'=>'i','j'=>'j','k'=>'k','l'=>'l','ï½'=>'ï½','n'=>'n','ï½'=>'ï½','ï½'=>'ï½','q'=>'q','ï½’'=>'ï½’','s'=>'s','ï½”'=>'ï½”','u'=>'u','ï½–'=>'ï½–','ï½—'=>'ï½—','x'=>'x','ï½™'=>'ï½™','z'=>'z','ヲ'=>'ヲ','ï½§'=>'ï½§','ィ'=>'ィ','ゥ'=>'ゥ','ェ'=>'ェ','ォ'=>'ォ','ャ'=>'ャ','ï½'=>'ï½','ï½®'=>'ï½®','ッ'=>'ッ','ï½°'=>'ï½°','ï½±'=>'ï½±','ï½²'=>'ï½²','ï½³'=>'ï½³','ï½´'=>'ï½´','ï½µ'=>'ï½µ','ï½¶'=>'ï½¶','ï½·'=>'ï½·','ク'=>'ク','ï½¹'=>'ï½¹','コ'=>'コ','ï½»'=>'ï½»','ï½¼'=>'ï½¼','ï½½'=>'ï½½','ï½¾'=>'ï½¾','ソ'=>'ソ','ï¾€'=>'ï¾€','ï¾'=>'ï¾','ツ'=>'ツ','テ'=>'テ','ト'=>'ト','ï¾…'=>'ï¾…','ニ'=>'ニ','ヌ'=>'ヌ','ネ'=>'ネ','ノ'=>'ノ','ハ'=>'ハ','ヒ'=>'ヒ','フ'=>'フ','ï¾'=>'ï¾','ホ'=>'ホ','ï¾'=>'ï¾','ï¾'=>'ï¾','ム'=>'ム','ï¾’'=>'ï¾’','モ'=>'モ','ï¾”'=>'ï¾”','ユ'=>'ユ','ï¾–'=>'ï¾–','ï¾—'=>'ï¾—','リ'=>'リ','ï¾™'=>'ï¾™','レ'=>'レ','ï¾›'=>'ï¾›','ワ'=>'ワ','ï¾'=>'ï¾','゙'=>'゙','゚'=>'゚','ï¾ '=>'ï¾ ','ᄀ'=>'ᄀ','ï¾¢'=>'ï¾¢','ï¾£'=>'ï¾£','ᄂ'=>'ᄂ','ï¾¥'=>'ï¾¥','ᆭ'=>'ᆭ','ï¾§'=>'ï¾§','ᄄ'=>'ᄄ','ᄅ'=>'ᄅ','ᆰ'=>'ᆰ','ᆱ'=>'ᆱ','ᆲ'=>'ᆲ','ï¾'=>'ï¾','ï¾®'=>'ï¾®','ᆵ'=>'ᆵ','ï¾°'=>'ï¾°','ï¾±'=>'ï¾±','ï¾²'=>'ï¾²','ï¾³'=>'ï¾³','ï¾´'=>'ï¾´','ï¾µ'=>'ï¾µ','ï¾¶'=>'ï¾¶','ï¾·'=>'ï¾·','ᄌ'=>'ᄌ','ï¾¹'=>'ï¾¹','ᄎ'=>'ᄎ','ï¾»'=>'ï¾»','ï¾¼'=>'ï¾¼','ï¾½'=>'ï¾½','ï¾¾'=>'ï¾¾','ï¿‚'=>'ï¿‚','ᅢ'=>'ᅢ','ï¿„'=>'ï¿„','ï¿…'=>'ï¿…','ᅥ'=>'ᅥ','ᅦ'=>'ᅦ','ᅧ'=>'ᅧ','ï¿‹'=>'ï¿‹','ᅩ'=>'ᅩ','ï¿'=>'ï¿','ᅫ'=>'ᅫ','ï¿'=>'ï¿','ï¿’'=>'ï¿’','ï¿“'=>'ï¿“','ï¿”'=>'ï¿”','ï¿•'=>'ï¿•','ï¿–'=>'ï¿–','ï¿—'=>'ï¿—','ᅳ'=>'ᅳ','ï¿›'=>'ï¿›','ᅵ'=>'ᅵ');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_32.php b/phpBB/includes/utf/data/search_indexer_32.php deleted file mode 100644 index 73ed2924ab..0000000000 --- a/phpBB/includes/utf/data/search_indexer_32.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('ð€€'=>'ð€€','ð€'=>'ð€','ð€‚'=>'ð€‚','ð€ƒ'=>'ð€ƒ','ð€„'=>'ð€„','ð€…'=>'ð€…','ð€†'=>'ð€†','ð€‡'=>'ð€‡','ð€ˆ'=>'ð€ˆ','ð€‰'=>'ð€‰','ð€Š'=>'ð€Š','ð€‹'=>'ð€‹','ð€'=>'ð€','ð€Ž'=>'ð€Ž','ð€'=>'ð€','ð€'=>'ð€','ð€‘'=>'ð€‘','ð€’'=>'ð€’','ð€“'=>'ð€“','ð€”'=>'ð€”','ð€•'=>'ð€•','ð€–'=>'ð€–','ð€—'=>'ð€—','ð€˜'=>'ð€˜','ð€™'=>'ð€™','ð€š'=>'ð€š','ð€›'=>'ð€›','ð€œ'=>'ð€œ','ð€'=>'ð€','ð€ž'=>'ð€ž','ð€Ÿ'=>'ð€Ÿ','ð€ '=>'ð€ ','ð€¡'=>'ð€¡','ð€¢'=>'ð€¢','ð€£'=>'ð€£','ð€¤'=>'ð€¤','ð€¥'=>'ð€¥','ð€¦'=>'ð€¦','ð€¨'=>'ð€¨','ð€©'=>'ð€©','ð€ª'=>'ð€ª','ð€«'=>'ð€«','ð€¬'=>'ð€¬','ð€'=>'ð€','ð€®'=>'ð€®','ð€¯'=>'ð€¯','ð€°'=>'ð€°','ð€±'=>'ð€±','ð€²'=>'ð€²','ð€³'=>'ð€³','ð€´'=>'ð€´','ð€µ'=>'ð€µ','ð€¶'=>'ð€¶','ð€·'=>'ð€·','ð€¸'=>'ð€¸','ð€¹'=>'ð€¹','ð€º'=>'ð€º','ð€¼'=>'ð€¼','ð€½'=>'ð€½','ð€¿'=>'ð€¿','ð€'=>'ð€','ð'=>'ð','ð‚'=>'ð‚','ðƒ'=>'ðƒ','ð„'=>'ð„','ð…'=>'ð…','ð†'=>'ð†','ð‡'=>'ð‡','ðˆ'=>'ðˆ','ð‰'=>'ð‰','ðŠ'=>'ðŠ','ð‹'=>'ð‹','ðŒ'=>'ðŒ','ð'=>'ð','ð'=>'ð','ð‘'=>'ð‘','ð’'=>'ð’','ð“'=>'ð“','ð”'=>'ð”','ð•'=>'ð•','ð–'=>'ð–','ð—'=>'ð—','ð˜'=>'ð˜','ð™'=>'ð™','ðš'=>'ðš','ð›'=>'ð›','ðœ'=>'ðœ','ð'=>'ð','ð‚€'=>'ð‚€','ð‚'=>'ð‚','ð‚‚'=>'ð‚‚','ð‚ƒ'=>'ð‚ƒ','ð‚„'=>'ð‚„','ð‚…'=>'ð‚…','ð‚†'=>'ð‚†','ð‚‡'=>'ð‚‡','ð‚ˆ'=>'ð‚ˆ','ð‚‰'=>'ð‚‰','ð‚Š'=>'ð‚Š','ð‚‹'=>'ð‚‹','ð‚Œ'=>'ð‚Œ','ð‚'=>'ð‚','ð‚Ž'=>'ð‚Ž','ð‚'=>'ð‚','ð‚'=>'ð‚','ð‚‘'=>'ð‚‘','ð‚’'=>'ð‚’','ð‚“'=>'ð‚“','ð‚”'=>'ð‚”','ð‚•'=>'ð‚•','ð‚–'=>'ð‚–','ð‚—'=>'ð‚—','ð‚˜'=>'ð‚˜','ð‚™'=>'ð‚™','ð‚š'=>'ð‚š','ð‚›'=>'ð‚›','ð‚œ'=>'ð‚œ','ð‚'=>'ð‚','ð‚ž'=>'ð‚ž','ð‚Ÿ'=>'ð‚Ÿ','ð‚ '=>'ð‚ ','ð‚¡'=>'ð‚¡','ð‚¢'=>'ð‚¢','ð‚£'=>'ð‚£','ð‚¤'=>'ð‚¤','ð‚¥'=>'ð‚¥','ð‚¦'=>'ð‚¦','ð‚§'=>'ð‚§','ð‚¨'=>'ð‚¨','ð‚©'=>'ð‚©','ð‚ª'=>'ð‚ª','ð‚«'=>'ð‚«','ð‚¬'=>'ð‚¬','ð‚'=>'ð‚','ð‚®'=>'ð‚®','ð‚¯'=>'ð‚¯','ð‚°'=>'ð‚°','ð‚±'=>'ð‚±','ð‚²'=>'ð‚²','ð‚³'=>'ð‚³','ð‚´'=>'ð‚´','ð‚µ'=>'ð‚µ','ð‚¶'=>'ð‚¶','ð‚·'=>'ð‚·','ð‚¸'=>'ð‚¸','ð‚¹'=>'ð‚¹','ð‚º'=>'ð‚º','ð‚»'=>'ð‚»','ð‚¼'=>'ð‚¼','ð‚½'=>'ð‚½','ð‚¾'=>'ð‚¾','ð‚¿'=>'ð‚¿','ðƒ€'=>'ðƒ€','ðƒ'=>'ðƒ','ðƒ‚'=>'ðƒ‚','ðƒƒ'=>'ðƒƒ','ðƒ„'=>'ðƒ„','ðƒ…'=>'ðƒ…','ðƒ†'=>'ðƒ†','ðƒ‡'=>'ðƒ‡','ðƒˆ'=>'ðƒˆ','ðƒ‰'=>'ðƒ‰','ðƒŠ'=>'ðƒŠ','ðƒ‹'=>'ðƒ‹','ðƒŒ'=>'ðƒŒ','ðƒ'=>'ðƒ','ðƒŽ'=>'ðƒŽ','ðƒ'=>'ðƒ','ðƒ'=>'ðƒ','ðƒ‘'=>'ðƒ‘','ðƒ’'=>'ðƒ’','ðƒ“'=>'ðƒ“','ðƒ”'=>'ðƒ”','ðƒ•'=>'ðƒ•','ðƒ–'=>'ðƒ–','ðƒ—'=>'ðƒ—','ðƒ˜'=>'ðƒ˜','ðƒ™'=>'ðƒ™','ðƒš'=>'ðƒš','ðƒ›'=>'ðƒ›','ðƒœ'=>'ðƒœ','ðƒ'=>'ðƒ','ðƒž'=>'ðƒž','ðƒŸ'=>'ðƒŸ','ðƒ '=>'ðƒ ','ðƒ¡'=>'ðƒ¡','ðƒ¢'=>'ðƒ¢','ðƒ£'=>'ðƒ£','ðƒ¤'=>'ðƒ¤','ðƒ¥'=>'ðƒ¥','ðƒ¦'=>'ðƒ¦','ðƒ§'=>'ðƒ§','ðƒ¨'=>'ðƒ¨','ðƒ©'=>'ðƒ©','ðƒª'=>'ðƒª','ðƒ«'=>'ðƒ«','ðƒ¬'=>'ðƒ¬','ðƒ'=>'ðƒ','ðƒ®'=>'ðƒ®','ðƒ¯'=>'ðƒ¯','ðƒ°'=>'ðƒ°','ðƒ±'=>'ðƒ±','ðƒ²'=>'ðƒ²','ðƒ³'=>'ðƒ³','ðƒ´'=>'ðƒ´','ðƒµ'=>'ðƒµ','ðƒ¶'=>'ðƒ¶','ðƒ·'=>'ðƒ·','ðƒ¸'=>'ðƒ¸','ðƒ¹'=>'ðƒ¹','ðƒº'=>'ðƒº','ð„‡'=>'1','ð„ˆ'=>'2','ð„‰'=>'3','ð„Š'=>'4','ð„‹'=>'5','ð„Œ'=>'6','ð„'=>'7','ð„Ž'=>'8','ð„'=>'9','ð„'=>'10','ð„‘'=>'20','ð„’'=>'30','ð„“'=>'40','ð„”'=>'50','ð„•'=>'60','ð„–'=>'70','ð„—'=>'80','ð„˜'=>'90','ð„™'=>'100','ð„š'=>'200','ð„›'=>'300','ð„œ'=>'400','ð„'=>'500','ð„ž'=>'600','ð„Ÿ'=>'700','ð„ '=>'800','ð„¡'=>'900','ð„¢'=>'1000','ð„£'=>'2000','ð„¤'=>'3000','ð„¥'=>'4000','ð„¦'=>'5000','ð„§'=>'6000','ð„¨'=>'7000','ð„©'=>'8000','ð„ª'=>'9000','ð„«'=>'10000','ð„¬'=>'20000','ð„'=>'30000','ð„®'=>'40000','ð„¯'=>'50000','ð„°'=>'60000','ð„±'=>'70000','ð„²'=>'80000','ð„³'=>'90000','ð…€'=>'1/4','ð…'=>'1/2','ð…‚'=>'1','ð…ƒ'=>'5','ð…„'=>'50','ð……'=>'500','ð…†'=>'5000','ð…‡'=>'50000','ð…ˆ'=>'5','ð…‰'=>'10','ð…Š'=>'50','ð…‹'=>'100','ð…Œ'=>'500','ð…'=>'1000','ð…Ž'=>'5000','ð…'=>'5','ð…'=>'10','ð…‘'=>'50','ð…’'=>'100','ð…“'=>'500','ð…”'=>'1000','ð…•'=>'10000','ð…–'=>'50000','ð…—'=>'10','ð…˜'=>'1','ð…™'=>'1','ð…š'=>'1','ð…›'=>'2','ð…œ'=>'2','ð…'=>'2','ð…ž'=>'2','ð…Ÿ'=>'5','ð… '=>'10','ð…¡'=>'10','ð…¢'=>'10','ð…£'=>'10','ð…¤'=>'10','ð…¥'=>'30','ð…¦'=>'50','ð…§'=>'50','ð…¨'=>'50','ð…©'=>'50','ð…ª'=>'100','ð…«'=>'300','ð…¬'=>'500','ð…'=>'500','ð…®'=>'500','ð…¯'=>'500','ð…°'=>'500','ð…±'=>'1000','ð…²'=>'5000','ð…³'=>'5','ð…´'=>'50','ð…µ'=>'1/2','ð…¶'=>'1/2','ð…·'=>'2/3','ð…¸'=>'3/4','ð†Š'=>'0','ðŒ€'=>'ðŒ€','ðŒ'=>'ðŒ','ðŒ‚'=>'ðŒ‚','ðŒƒ'=>'ðŒƒ','ðŒ„'=>'ðŒ„','ðŒ…'=>'ðŒ…','ðŒ†'=>'ðŒ†','ðŒ‡'=>'ðŒ‡','ðŒˆ'=>'ðŒˆ','ðŒ‰'=>'ðŒ‰','ðŒŠ'=>'ðŒŠ','ðŒ‹'=>'ðŒ‹','ðŒŒ'=>'ðŒŒ','ðŒ'=>'ðŒ','ðŒŽ'=>'ðŒŽ','ðŒ'=>'ðŒ','ðŒ'=>'ðŒ','ðŒ‘'=>'ðŒ‘','ðŒ’'=>'ðŒ’','ðŒ“'=>'ðŒ“','ðŒ”'=>'ðŒ”','ðŒ•'=>'ðŒ•','ðŒ–'=>'ðŒ–','ðŒ—'=>'ðŒ—','ðŒ˜'=>'ðŒ˜','ðŒ™'=>'ðŒ™','ðŒš'=>'ðŒš','ðŒ›'=>'ðŒ›','ðŒœ'=>'ðŒœ','ðŒ'=>'ðŒ','ðŒž'=>'ðŒž','ðŒ '=>'1','ðŒ¡'=>'5','ðŒ¢'=>'10','ðŒ£'=>'50','ðŒ°'=>'ðŒ°','ðŒ±'=>'ðŒ±','ðŒ²'=>'ðŒ²','ðŒ³'=>'ðŒ³','ðŒ´'=>'ðŒ´','ðŒµ'=>'ðŒµ','ðŒ¶'=>'ðŒ¶','ðŒ·'=>'ðŒ·','ðŒ¸'=>'ðŒ¸','ðŒ¹'=>'ðŒ¹','ðŒº'=>'ðŒº','ðŒ»'=>'ðŒ»','ðŒ¼'=>'ðŒ¼','ðŒ½'=>'ðŒ½','ðŒ¾'=>'ðŒ¾','ðŒ¿'=>'ðŒ¿','ð€'=>'ð€','ð'=>'90','ð‚'=>'ð‚','ðƒ'=>'ðƒ','ð„'=>'ð„','ð…'=>'ð…','ð†'=>'ð†','ð‡'=>'ð‡','ðˆ'=>'ðˆ','ð‰'=>'ð‰','ðŠ'=>'900','ðŽ€'=>'ðŽ€','ðŽ'=>'ðŽ','ðŽ‚'=>'ðŽ‚','ðŽƒ'=>'ðŽƒ','ðŽ„'=>'ðŽ„','ðŽ…'=>'ðŽ…','ðކ'=>'ðކ','ðއ'=>'ðއ','ðŽˆ'=>'ðŽˆ','ðމ'=>'ðމ','ðŽŠ'=>'ðŽŠ','ðŽ‹'=>'ðŽ‹','ðŽŒ'=>'ðŽŒ','ðŽ'=>'ðŽ','ðŽŽ'=>'ðŽŽ','ðŽ'=>'ðŽ','ðŽ'=>'ðŽ','ðŽ‘'=>'ðŽ‘','ðŽ’'=>'ðŽ’','ðŽ“'=>'ðŽ“','ðŽ”'=>'ðŽ”','ðŽ•'=>'ðŽ•','ðŽ–'=>'ðŽ–','ðŽ—'=>'ðŽ—','ðŽ˜'=>'ðŽ˜','ðŽ™'=>'ðŽ™','ðŽš'=>'ðŽš','ðŽ›'=>'ðŽ›','ðŽœ'=>'ðŽœ','ðŽ'=>'ðŽ','ðŽ '=>'ðŽ ','ðŽ¡'=>'ðŽ¡','ðŽ¢'=>'ðŽ¢','ðŽ£'=>'ðŽ£','ðޤ'=>'ðޤ','ðŽ¥'=>'ðŽ¥','ðަ'=>'ðަ','ðާ'=>'ðާ','ðލ'=>'ðލ','ðŽ©'=>'ðŽ©','ðŽª'=>'ðŽª','ðŽ«'=>'ðŽ«','ðެ'=>'ðެ','ðŽ'=>'ðŽ','ðŽ®'=>'ðŽ®','ðޝ'=>'ðޝ','ðް'=>'ðް','ðޱ'=>'ðޱ','ð޲'=>'ð޲','ð޳'=>'ð޳','ðŽ´'=>'ðŽ´','ð޵'=>'ð޵','ð޶'=>'ð޶','ðŽ·'=>'ðŽ·','ðޏ'=>'ðޏ','ð޹'=>'ð޹','ðŽº'=>'ðŽº','ðŽ»'=>'ðŽ»','ð޼'=>'ð޼','ð޽'=>'ð޽','ð޾'=>'ð޾','ðŽ¿'=>'ðŽ¿','ð€'=>'ð€','ð'=>'ð','ð‚'=>'ð‚','ðƒ'=>'ðƒ','ðˆ'=>'ðˆ','ð‰'=>'ð‰','ðŠ'=>'ðŠ','ð‹'=>'ð‹','ðŒ'=>'ðŒ','ð'=>'ð','ðŽ'=>'ðŽ','ð'=>'ð','ð‘'=>'1','ð’'=>'2','ð“'=>'10','ð”'=>'20','ð•'=>'100','ð€'=>'ð¨','ð'=>'ð©','ð‚'=>'ðª','ðƒ'=>'ð«','ð„'=>'ð¬','ð…'=>'ð','ð†'=>'ð®','ð‡'=>'ð¯','ðˆ'=>'ð°','ð‰'=>'ð±','ðŠ'=>'ð²','ð‹'=>'ð³','ðŒ'=>'ð´','ð'=>'ðµ','ðŽ'=>'ð¶','ð'=>'ð·','ð'=>'ð¸','ð‘'=>'ð¹','ð’'=>'ðº','ð“'=>'ð»','ð”'=>'ð¼','ð•'=>'ð½','ð–'=>'ð¾','ð—'=>'ð¿','ð˜'=>'ð‘€','ð™'=>'ð‘','ðš'=>'ð‘‚','ð›'=>'ð‘ƒ','ðœ'=>'ð‘„','ð'=>'ð‘…','ðž'=>'ð‘†','ðŸ'=>'ð‘‡','ð '=>'ð‘ˆ','ð¡'=>'ð‘‰','ð¢'=>'ð‘Š','ð£'=>'ð‘‹','ð¤'=>'ð‘Œ','ð¥'=>'ð‘','ð¦'=>'ð‘Ž','ð§'=>'ð‘','ð¨'=>'ð¨','ð©'=>'ð©','ðª'=>'ðª','ð«'=>'ð«','ð¬'=>'ð¬','ð'=>'ð','ð®'=>'ð®','ð¯'=>'ð¯','ð°'=>'ð°','ð±'=>'ð±','ð²'=>'ð²','ð³'=>'ð³','ð´'=>'ð´','ðµ'=>'ðµ','ð¶'=>'ð¶','ð·'=>'ð·','ð¸'=>'ð¸','ð¹'=>'ð¹','ðº'=>'ðº','ð»'=>'ð»','ð¼'=>'ð¼','ð½'=>'ð½','ð¾'=>'ð¾','ð¿'=>'ð¿','ð‘€'=>'ð‘€','ð‘'=>'ð‘','ð‘‚'=>'ð‘‚','ð‘ƒ'=>'ð‘ƒ','ð‘„'=>'ð‘„','ð‘…'=>'ð‘…','ð‘†'=>'ð‘†','ð‘‡'=>'ð‘‡','ð‘ˆ'=>'ð‘ˆ','ð‘‰'=>'ð‘‰','ð‘Š'=>'ð‘Š','ð‘‹'=>'ð‘‹','ð‘Œ'=>'ð‘Œ','ð‘'=>'ð‘','ð‘Ž'=>'ð‘Ž','ð‘'=>'ð‘','ð‘'=>'ð‘','ð‘‘'=>'ð‘‘','ð‘’'=>'ð‘’','ð‘“'=>'ð‘“','ð‘”'=>'ð‘”','ð‘•'=>'ð‘•','ð‘–'=>'ð‘–','ð‘—'=>'ð‘—','ð‘˜'=>'ð‘˜','ð‘™'=>'ð‘™','ð‘š'=>'ð‘š','ð‘›'=>'ð‘›','ð‘œ'=>'ð‘œ','ð‘'=>'ð‘','ð‘ž'=>'ð‘ž','ð‘Ÿ'=>'ð‘Ÿ','ð‘ '=>'ð‘ ','ð‘¡'=>'ð‘¡','ð‘¢'=>'ð‘¢','ð‘£'=>'ð‘£','ð‘¤'=>'ð‘¤','ð‘¥'=>'ð‘¥','ð‘¦'=>'ð‘¦','ð‘§'=>'ð‘§','ð‘¨'=>'ð‘¨','ð‘©'=>'ð‘©','ð‘ª'=>'ð‘ª','ð‘«'=>'ð‘«','ð‘¬'=>'ð‘¬','ð‘'=>'ð‘','ð‘®'=>'ð‘®','ð‘¯'=>'ð‘¯','ð‘°'=>'ð‘°','ð‘±'=>'ð‘±','ð‘²'=>'ð‘²','ð‘³'=>'ð‘³','ð‘´'=>'ð‘´','ð‘µ'=>'ð‘µ','ð‘¶'=>'ð‘¶','ð‘·'=>'ð‘·','ð‘¸'=>'ð‘¸','ð‘¹'=>'ð‘¹','ð‘º'=>'ð‘º','ð‘»'=>'ð‘»','ð‘¼'=>'ð‘¼','ð‘½'=>'ð‘½','ð‘¾'=>'ð‘¾','ð‘¿'=>'ð‘¿','ð’€'=>'ð’€','ð’'=>'ð’','ð’‚'=>'ð’‚','ð’ƒ'=>'ð’ƒ','ð’„'=>'ð’„','ð’…'=>'ð’…','ð’†'=>'ð’†','ð’‡'=>'ð’‡','ð’ˆ'=>'ð’ˆ','ð’‰'=>'ð’‰','ð’Š'=>'ð’Š','ð’‹'=>'ð’‹','ð’Œ'=>'ð’Œ','ð’'=>'ð’','ð’Ž'=>'ð’Ž','ð’'=>'ð’','ð’'=>'ð’','ð’‘'=>'ð’‘','ð’’'=>'ð’’','ð’“'=>'ð’“','ð’”'=>'ð’”','ð’•'=>'ð’•','ð’–'=>'ð’–','ð’—'=>'ð’—','ð’˜'=>'ð’˜','ð’™'=>'ð’™','ð’š'=>'ð’š','ð’›'=>'ð’›','ð’œ'=>'ð’œ','ð’'=>'ð’','ð’ '=>'0','ð’¡'=>'1','ð’¢'=>'2','ð’£'=>'3','ð’¤'=>'4','ð’¥'=>'5','ð’¦'=>'6','ð’§'=>'7','ð’¨'=>'8','ð’©'=>'9');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_33.php b/phpBB/includes/utf/data/search_indexer_33.php deleted file mode 100644 index 4e8762a646..0000000000 --- a/phpBB/includes/utf/data/search_indexer_33.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('ð €'=>'ð €','ð '=>'ð ','ð ‚'=>'ð ‚','ð ƒ'=>'ð ƒ','ð „'=>'ð „','ð …'=>'ð …','ð ˆ'=>'ð ˆ','ð Š'=>'ð Š','ð ‹'=>'ð ‹','ð Œ'=>'ð Œ','ð '=>'ð ','ð Ž'=>'ð Ž','ð '=>'ð ','ð '=>'ð ','ð ‘'=>'ð ‘','ð ’'=>'ð ’','ð “'=>'ð “','ð ”'=>'ð ”','ð •'=>'ð •','ð –'=>'ð –','ð —'=>'ð —','ð ˜'=>'ð ˜','ð ™'=>'ð ™','ð š'=>'ð š','ð ›'=>'ð ›','ð œ'=>'ð œ','ð '=>'ð ','ð ž'=>'ð ž','ð Ÿ'=>'ð Ÿ','ð '=>'ð ','ð ¡'=>'ð ¡','ð ¢'=>'ð ¢','ð £'=>'ð £','ð ¤'=>'ð ¤','ð ¥'=>'ð ¥','ð ¦'=>'ð ¦','ð §'=>'ð §','ð ¨'=>'ð ¨','ð ©'=>'ð ©','ð ª'=>'ð ª','ð «'=>'ð «','ð ¬'=>'ð ¬','ð '=>'ð ','ð ®'=>'ð ®','ð ¯'=>'ð ¯','ð °'=>'ð °','ð ±'=>'ð ±','ð ²'=>'ð ²','ð ³'=>'ð ³','ð ´'=>'ð ´','ð µ'=>'ð µ','ð ·'=>'ð ·','ð ¸'=>'ð ¸','ð ¼'=>'ð ¼','ð ¿'=>'ð ¿','ð¤€'=>'ð¤€','ð¤'=>'ð¤','ð¤‚'=>'ð¤‚','ð¤ƒ'=>'ð¤ƒ','ð¤„'=>'ð¤„','ð¤…'=>'ð¤…','ð¤†'=>'ð¤†','ð¤‡'=>'ð¤‡','ð¤ˆ'=>'ð¤ˆ','ð¤‰'=>'ð¤‰','ð¤Š'=>'ð¤Š','ð¤‹'=>'ð¤‹','ð¤Œ'=>'ð¤Œ','ð¤'=>'ð¤','ð¤Ž'=>'ð¤Ž','ð¤'=>'ð¤','ð¤'=>'ð¤','ð¤‘'=>'ð¤‘','ð¤’'=>'ð¤’','ð¤“'=>'ð¤“','ð¤”'=>'ð¤”','ð¤•'=>'ð¤•','ð¤–'=>'1','ð¤—'=>'10','ð¤˜'=>'20','ð¤™'=>'100','ð¨€'=>'ð¨€','ð¨'=>'ð¨','ð¨‚'=>'ð¨‚','ð¨ƒ'=>'ð¨ƒ','ð¨…'=>'ð¨…','ð¨†'=>'ð¨†','ð¨Œ'=>'ð¨Œ','ð¨'=>'ð¨','ð¨Ž'=>'ð¨Ž','ð¨'=>'ð¨','ð¨'=>'ð¨','ð¨‘'=>'ð¨‘','ð¨’'=>'ð¨’','ð¨“'=>'ð¨“','ð¨•'=>'ð¨•','ð¨–'=>'ð¨–','ð¨—'=>'ð¨—','ð¨™'=>'ð¨™','ð¨š'=>'ð¨š','ð¨›'=>'ð¨›','ð¨œ'=>'ð¨œ','ð¨'=>'ð¨','ð¨ž'=>'ð¨ž','ð¨Ÿ'=>'ð¨Ÿ','ð¨ '=>'ð¨ ','ð¨¡'=>'ð¨¡','ð¨¢'=>'ð¨¢','ð¨£'=>'ð¨£','ð¨¤'=>'ð¨¤','ð¨¥'=>'ð¨¥','ð¨¦'=>'ð¨¦','ð¨§'=>'ð¨§','ð¨¨'=>'ð¨¨','ð¨©'=>'ð¨©','ð¨ª'=>'ð¨ª','ð¨«'=>'ð¨«','ð¨¬'=>'ð¨¬','ð¨'=>'ð¨','ð¨®'=>'ð¨®','ð¨¯'=>'ð¨¯','ð¨°'=>'ð¨°','ð¨±'=>'ð¨±','ð¨²'=>'ð¨²','ð¨³'=>'ð¨³','ð¨¸'=>'ð¨¸','ð¨¹'=>'ð¨¹','ð¨º'=>'ð¨º','ð¨¿'=>'ð¨¿','ð©€'=>'1','ð©'=>'2','ð©‚'=>'3','ð©ƒ'=>'4','ð©„'=>'10','ð©…'=>'20','ð©†'=>'100','ð©‡'=>'1000');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_36.php b/phpBB/includes/utf/data/search_indexer_36.php deleted file mode 100644 index 8bf908e514..0000000000 --- a/phpBB/includes/utf/data/search_indexer_36.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('ð’€€'=>'ð’€€','ð’€'=>'ð’€','𒀂'=>'𒀂','𒀃'=>'𒀃','𒀄'=>'𒀄','ð’€…'=>'ð’€…','𒀆'=>'𒀆','𒀇'=>'𒀇','𒀈'=>'𒀈','𒀉'=>'𒀉','𒀊'=>'𒀊','𒀋'=>'𒀋','𒀌'=>'𒀌','ð’€'=>'ð’€','𒀎'=>'𒀎','ð’€'=>'ð’€','ð’€'=>'ð’€','𒀑'=>'𒀑','ð’€’'=>'ð’€’','𒀓'=>'𒀓','ð’€”'=>'ð’€”','𒀕'=>'𒀕','ð’€–'=>'ð’€–','ð’€—'=>'ð’€—','𒀘'=>'𒀘','ð’€™'=>'ð’€™','𒀚'=>'𒀚','ð’€›'=>'ð’€›','𒀜'=>'𒀜','ð’€'=>'ð’€','𒀞'=>'𒀞','𒀟'=>'𒀟','ð’€ '=>'ð’€ ','𒀡'=>'𒀡','ð’€¢'=>'ð’€¢','ð’€£'=>'ð’€£','𒀤'=>'𒀤','ð’€¥'=>'ð’€¥','𒀦'=>'𒀦','ð’€§'=>'ð’€§','𒀨'=>'𒀨','𒀩'=>'𒀩','𒀪'=>'𒀪','𒀫'=>'𒀫','𒀬'=>'𒀬','ð’€'=>'ð’€','ð’€®'=>'ð’€®','𒀯'=>'𒀯','ð’€°'=>'ð’€°','ð’€±'=>'ð’€±','ð’€²'=>'ð’€²','ð’€³'=>'ð’€³','ð’€´'=>'ð’€´','ð’€µ'=>'ð’€µ','ð’€¶'=>'ð’€¶','ð’€·'=>'ð’€·','𒀸'=>'𒀸','ð’€¹'=>'ð’€¹','𒀺'=>'𒀺','ð’€»'=>'ð’€»','ð’€¼'=>'ð’€¼','ð’€½'=>'ð’€½','ð’€¾'=>'ð’€¾','𒀿'=>'𒀿','ð’€'=>'ð’€','ð’'=>'ð’','ð’‚'=>'ð’‚','ð’ƒ'=>'ð’ƒ','ð’„'=>'ð’„','ð’…'=>'ð’…','ð’†'=>'ð’†','ð’‡'=>'ð’‡','ð’ˆ'=>'ð’ˆ','ð’‰'=>'ð’‰','ð’Š'=>'ð’Š','ð’‹'=>'ð’‹','ð’Œ'=>'ð’Œ','ð’'=>'ð’','ð’Ž'=>'ð’Ž','ð’'=>'ð’','ð’'=>'ð’','ð’‘'=>'ð’‘','ð’’'=>'ð’’','ð’“'=>'ð’“','ð’”'=>'ð’”','ð’•'=>'ð’•','ð’–'=>'ð’–','ð’—'=>'ð’—','ð’˜'=>'ð’˜','ð’™'=>'ð’™','ð’š'=>'ð’š','ð’›'=>'ð’›','ð’œ'=>'ð’œ','ð’'=>'ð’','ð’ž'=>'ð’ž','ð’Ÿ'=>'ð’Ÿ','ð’ '=>'ð’ ','ð’¡'=>'ð’¡','ð’¢'=>'ð’¢','ð’£'=>'ð’£','ð’¤'=>'ð’¤','ð’¥'=>'ð’¥','ð’¦'=>'ð’¦','ð’§'=>'ð’§','ð’¨'=>'ð’¨','ð’©'=>'ð’©','ð’ª'=>'ð’ª','ð’«'=>'ð’«','ð’¬'=>'ð’¬','ð’'=>'ð’','ð’®'=>'ð’®','ð’¯'=>'ð’¯','ð’°'=>'ð’°','ð’±'=>'ð’±','ð’²'=>'ð’²','ð’³'=>'ð’³','ð’´'=>'ð’´','ð’µ'=>'ð’µ','ð’¶'=>'ð’¶','ð’·'=>'ð’·','ð’¸'=>'ð’¸','ð’¹'=>'ð’¹','ð’º'=>'ð’º','ð’»'=>'ð’»','ð’¼'=>'ð’¼','ð’½'=>'ð’½','ð’¾'=>'ð’¾','ð’¿'=>'ð’¿','ð’‚€'=>'ð’‚€','ð’‚'=>'ð’‚','ð’‚‚'=>'ð’‚‚','𒂃'=>'𒂃','ð’‚„'=>'ð’‚„','ð’‚…'=>'ð’‚…','𒂆'=>'𒂆','𒂇'=>'𒂇','𒂈'=>'𒂈','𒂉'=>'𒂉','ð’‚Š'=>'ð’‚Š','ð’‚‹'=>'ð’‚‹','ð’‚Œ'=>'ð’‚Œ','ð’‚'=>'ð’‚','ð’‚Ž'=>'ð’‚Ž','ð’‚'=>'ð’‚','ð’‚'=>'ð’‚','ð’‚‘'=>'ð’‚‘','ð’‚’'=>'ð’‚’','ð’‚“'=>'ð’‚“','ð’‚”'=>'ð’‚”','ð’‚•'=>'ð’‚•','ð’‚–'=>'ð’‚–','ð’‚—'=>'ð’‚—','𒂘'=>'𒂘','ð’‚™'=>'ð’‚™','ð’‚š'=>'ð’‚š','ð’‚›'=>'ð’‚›','ð’‚œ'=>'ð’‚œ','ð’‚'=>'ð’‚','ð’‚ž'=>'ð’‚ž','ð’‚Ÿ'=>'ð’‚Ÿ','ð’‚ '=>'ð’‚ ','ð’‚¡'=>'ð’‚¡','ð’‚¢'=>'ð’‚¢','ð’‚£'=>'ð’‚£','𒂤'=>'𒂤','ð’‚¥'=>'ð’‚¥','𒂦'=>'𒂦','ð’‚§'=>'ð’‚§','𒂨'=>'𒂨','ð’‚©'=>'ð’‚©','𒂪'=>'𒂪','ð’‚«'=>'ð’‚«','𒂬'=>'𒂬','ð’‚'=>'ð’‚','ð’‚®'=>'ð’‚®','𒂯'=>'𒂯','ð’‚°'=>'ð’‚°','ð’‚±'=>'ð’‚±','ð’‚²'=>'ð’‚²','ð’‚³'=>'ð’‚³','ð’‚´'=>'ð’‚´','ð’‚µ'=>'ð’‚µ','ð’‚¶'=>'ð’‚¶','ð’‚·'=>'ð’‚·','𒂸'=>'𒂸','ð’‚¹'=>'ð’‚¹','𒂺'=>'𒂺','ð’‚»'=>'ð’‚»','ð’‚¼'=>'ð’‚¼','ð’‚½'=>'ð’‚½','ð’‚¾'=>'ð’‚¾','ð’‚¿'=>'ð’‚¿','𒃀'=>'𒃀','ð’ƒ'=>'ð’ƒ','𒃂'=>'𒃂','𒃃'=>'𒃃','𒃄'=>'𒃄','ð’ƒ…'=>'ð’ƒ…','𒃆'=>'𒃆','𒃇'=>'𒃇','𒃈'=>'𒃈','𒃉'=>'𒃉','𒃊'=>'𒃊','𒃋'=>'𒃋','𒃌'=>'𒃌','ð’ƒ'=>'ð’ƒ','𒃎'=>'𒃎','ð’ƒ'=>'ð’ƒ','ð’ƒ'=>'ð’ƒ','𒃑'=>'𒃑','ð’ƒ’'=>'ð’ƒ’','𒃓'=>'𒃓','𒃔'=>'𒃔','𒃕'=>'𒃕','ð’ƒ–'=>'ð’ƒ–','ð’ƒ—'=>'ð’ƒ—','𒃘'=>'𒃘','𒃙'=>'𒃙','𒃚'=>'𒃚','𒃛'=>'𒃛','𒃜'=>'𒃜','ð’ƒ'=>'ð’ƒ','𒃞'=>'𒃞','𒃟'=>'𒃟','ð’ƒ '=>'ð’ƒ ','𒃡'=>'𒃡','𒃢'=>'𒃢','𒃣'=>'𒃣','𒃤'=>'𒃤','𒃥'=>'𒃥','𒃦'=>'𒃦','𒃧'=>'𒃧','𒃨'=>'𒃨','𒃩'=>'𒃩','𒃪'=>'𒃪','𒃫'=>'𒃫','𒃬'=>'𒃬','ð’ƒ'=>'ð’ƒ','𒃮'=>'𒃮','𒃯'=>'𒃯','ð’ƒ°'=>'ð’ƒ°','𒃱'=>'𒃱','𒃲'=>'𒃲','𒃳'=>'𒃳','ð’ƒ´'=>'ð’ƒ´','𒃵'=>'𒃵','𒃶'=>'𒃶','ð’ƒ·'=>'ð’ƒ·','𒃸'=>'𒃸','𒃹'=>'𒃹','𒃺'=>'𒃺','𒃻'=>'𒃻','𒃼'=>'𒃼','𒃽'=>'𒃽','𒃾'=>'𒃾','𒃿'=>'𒃿','ð’„€'=>'ð’„€','ð’„'=>'ð’„','ð’„‚'=>'ð’„‚','𒄃'=>'𒄃','ð’„„'=>'ð’„„','ð’„…'=>'ð’„…','𒄆'=>'𒄆','𒄇'=>'𒄇','𒄈'=>'𒄈','𒄉'=>'𒄉','ð’„Š'=>'ð’„Š','ð’„‹'=>'ð’„‹','ð’„Œ'=>'ð’„Œ','ð’„'=>'ð’„','ð’„Ž'=>'ð’„Ž','ð’„'=>'ð’„','ð’„'=>'ð’„','ð’„‘'=>'ð’„‘','ð’„’'=>'ð’„’','ð’„“'=>'ð’„“','ð’„”'=>'ð’„”','ð’„•'=>'ð’„•','ð’„–'=>'ð’„–','ð’„—'=>'ð’„—','𒄘'=>'𒄘','ð’„™'=>'ð’„™','ð’„š'=>'ð’„š','ð’„›'=>'ð’„›','ð’„œ'=>'ð’„œ','ð’„'=>'ð’„','ð’„ž'=>'ð’„ž','ð’„Ÿ'=>'ð’„Ÿ','ð’„ '=>'ð’„ ','ð’„¡'=>'ð’„¡','ð’„¢'=>'ð’„¢','ð’„£'=>'ð’„£','𒄤'=>'𒄤','ð’„¥'=>'ð’„¥','𒄦'=>'𒄦','ð’„§'=>'ð’„§','𒄨'=>'𒄨','ð’„©'=>'ð’„©','𒄪'=>'𒄪','ð’„«'=>'ð’„«','𒄬'=>'𒄬','ð’„'=>'ð’„','ð’„®'=>'ð’„®','𒄯'=>'𒄯','ð’„°'=>'ð’„°','ð’„±'=>'ð’„±','ð’„²'=>'ð’„²','ð’„³'=>'ð’„³','ð’„´'=>'ð’„´','ð’„µ'=>'ð’„µ','ð’„¶'=>'ð’„¶','ð’„·'=>'ð’„·','𒄸'=>'𒄸','ð’„¹'=>'ð’„¹','𒄺'=>'𒄺','ð’„»'=>'ð’„»','ð’„¼'=>'ð’„¼','ð’„½'=>'ð’„½','ð’„¾'=>'ð’„¾','ð’„¿'=>'ð’„¿','ð’…€'=>'ð’…€','ð’…'=>'ð’…','ð’…‚'=>'ð’…‚','ð’…ƒ'=>'ð’…ƒ','ð’…„'=>'ð’…„','ð’……'=>'ð’……','ð’…†'=>'ð’…†','ð’…‡'=>'ð’…‡','ð’…ˆ'=>'ð’…ˆ','ð’…‰'=>'ð’…‰','ð’…Š'=>'ð’…Š','ð’…‹'=>'ð’…‹','ð’…Œ'=>'ð’…Œ','ð’…'=>'ð’…','ð’…Ž'=>'ð’…Ž','ð’…'=>'ð’…','ð’…'=>'ð’…','ð’…‘'=>'ð’…‘','ð’…’'=>'ð’…’','ð’…“'=>'ð’…“','ð’…”'=>'ð’…”','ð’…•'=>'ð’…•','ð’…–'=>'ð’…–','ð’…—'=>'ð’…—','ð’…˜'=>'ð’…˜','ð’…™'=>'ð’…™','ð’…š'=>'ð’…š','ð’…›'=>'ð’…›','ð’…œ'=>'ð’…œ','ð’…'=>'ð’…','ð’…ž'=>'ð’…ž','ð’…Ÿ'=>'ð’…Ÿ','ð’… '=>'ð’… ','ð’…¡'=>'ð’…¡','ð’…¢'=>'ð’…¢','ð’…£'=>'ð’…£','ð’…¤'=>'ð’…¤','ð’…¥'=>'ð’…¥','ð’…¦'=>'ð’…¦','ð’…§'=>'ð’…§','ð’…¨'=>'ð’…¨','ð’…©'=>'ð’…©','ð’…ª'=>'ð’…ª','ð’…«'=>'ð’…«','ð’…¬'=>'ð’…¬','ð’…'=>'ð’…','ð’…®'=>'ð’…®','ð’…¯'=>'ð’…¯','ð’…°'=>'ð’…°','ð’…±'=>'ð’…±','ð’…²'=>'ð’…²','ð’…³'=>'ð’…³','ð’…´'=>'ð’…´','ð’…µ'=>'ð’…µ','ð’…¶'=>'ð’…¶','ð’…·'=>'ð’…·','ð’…¸'=>'ð’…¸','ð’…¹'=>'ð’…¹','ð’…º'=>'ð’…º','ð’…»'=>'ð’…»','ð’…¼'=>'ð’…¼','ð’…½'=>'ð’…½','ð’…¾'=>'ð’…¾','ð’…¿'=>'ð’…¿','𒆀'=>'𒆀','ð’†'=>'ð’†','𒆂'=>'𒆂','𒆃'=>'𒆃','𒆄'=>'𒆄','ð’†…'=>'ð’†…','𒆆'=>'𒆆','𒆇'=>'𒆇','𒆈'=>'𒆈','𒆉'=>'𒆉','𒆊'=>'𒆊','𒆋'=>'𒆋','𒆌'=>'𒆌','ð’†'=>'ð’†','𒆎'=>'𒆎','ð’†'=>'ð’†','ð’†'=>'ð’†','𒆑'=>'𒆑','ð’†’'=>'ð’†’','𒆓'=>'𒆓','𒆔'=>'𒆔','𒆕'=>'𒆕','ð’†–'=>'ð’†–','ð’†—'=>'ð’†—','𒆘'=>'𒆘','𒆙'=>'𒆙','𒆚'=>'𒆚','𒆛'=>'𒆛','𒆜'=>'𒆜','ð’†'=>'ð’†','𒆞'=>'𒆞','𒆟'=>'𒆟','ð’† '=>'ð’† ','𒆡'=>'𒆡','𒆢'=>'𒆢','𒆣'=>'𒆣','𒆤'=>'𒆤','𒆥'=>'𒆥','𒆦'=>'𒆦','𒆧'=>'𒆧','𒆨'=>'𒆨','𒆩'=>'𒆩','𒆪'=>'𒆪','𒆫'=>'𒆫','𒆬'=>'𒆬','ð’†'=>'ð’†','𒆮'=>'𒆮','𒆯'=>'𒆯','ð’†°'=>'ð’†°','𒆱'=>'𒆱','𒆲'=>'𒆲','𒆳'=>'𒆳','ð’†´'=>'ð’†´','𒆵'=>'𒆵','𒆶'=>'𒆶','ð’†·'=>'ð’†·','𒆸'=>'𒆸','𒆹'=>'𒆹','𒆺'=>'𒆺','𒆻'=>'𒆻','𒆼'=>'𒆼','𒆽'=>'𒆽','𒆾'=>'𒆾','𒆿'=>'𒆿','𒇀'=>'𒇀','ð’‡'=>'ð’‡','𒇂'=>'𒇂','𒇃'=>'𒇃','𒇄'=>'𒇄','ð’‡…'=>'ð’‡…','𒇆'=>'𒇆','𒇇'=>'𒇇','𒇈'=>'𒇈','𒇉'=>'𒇉','𒇊'=>'𒇊','𒇋'=>'𒇋','𒇌'=>'𒇌','ð’‡'=>'ð’‡','𒇎'=>'𒇎','ð’‡'=>'ð’‡','ð’‡'=>'ð’‡','𒇑'=>'𒇑','ð’‡’'=>'ð’‡’','𒇓'=>'𒇓','𒇔'=>'𒇔','𒇕'=>'𒇕','ð’‡–'=>'ð’‡–','ð’‡—'=>'ð’‡—','𒇘'=>'𒇘','𒇙'=>'𒇙','𒇚'=>'𒇚','𒇛'=>'𒇛','𒇜'=>'𒇜','ð’‡'=>'ð’‡','𒇞'=>'𒇞','𒇟'=>'𒇟','ð’‡ '=>'ð’‡ ','𒇡'=>'𒇡','𒇢'=>'𒇢','𒇣'=>'𒇣','𒇤'=>'𒇤','𒇥'=>'𒇥','𒇦'=>'𒇦','𒇧'=>'𒇧','𒇨'=>'𒇨','𒇩'=>'𒇩','𒇪'=>'𒇪','𒇫'=>'𒇫','𒇬'=>'𒇬','ð’‡'=>'ð’‡','𒇮'=>'𒇮','𒇯'=>'𒇯','ð’‡°'=>'ð’‡°','𒇱'=>'𒇱','𒇲'=>'𒇲','𒇳'=>'𒇳','ð’‡´'=>'ð’‡´','𒇵'=>'𒇵','𒇶'=>'𒇶','ð’‡·'=>'ð’‡·','𒇸'=>'𒇸','𒇹'=>'𒇹','𒇺'=>'𒇺','𒇻'=>'𒇻','𒇼'=>'𒇼','𒇽'=>'𒇽','𒇾'=>'𒇾','𒇿'=>'𒇿','𒈀'=>'𒈀','ð’ˆ'=>'ð’ˆ','𒈂'=>'𒈂','𒈃'=>'𒈃','𒈄'=>'𒈄','ð’ˆ…'=>'ð’ˆ…','𒈆'=>'𒈆','𒈇'=>'𒈇','𒈈'=>'𒈈','𒈉'=>'𒈉','𒈊'=>'𒈊','𒈋'=>'𒈋','𒈌'=>'𒈌','ð’ˆ'=>'ð’ˆ','𒈎'=>'𒈎','ð’ˆ'=>'ð’ˆ','ð’ˆ'=>'ð’ˆ','𒈑'=>'𒈑','ð’ˆ’'=>'ð’ˆ’','𒈓'=>'𒈓','𒈔'=>'𒈔','𒈕'=>'𒈕','ð’ˆ–'=>'ð’ˆ–','ð’ˆ—'=>'ð’ˆ—','𒈘'=>'𒈘','𒈙'=>'𒈙','𒈚'=>'𒈚','𒈛'=>'𒈛','𒈜'=>'𒈜','ð’ˆ'=>'ð’ˆ','𒈞'=>'𒈞','𒈟'=>'𒈟','ð’ˆ '=>'ð’ˆ ','𒈡'=>'𒈡','𒈢'=>'𒈢','𒈣'=>'𒈣','𒈤'=>'𒈤','𒈥'=>'𒈥','𒈦'=>'𒈦','𒈧'=>'𒈧','𒈨'=>'𒈨','𒈩'=>'𒈩','𒈪'=>'𒈪','𒈫'=>'𒈫','𒈬'=>'𒈬','ð’ˆ'=>'ð’ˆ','𒈮'=>'𒈮','𒈯'=>'𒈯','ð’ˆ°'=>'ð’ˆ°','𒈱'=>'𒈱','𒈲'=>'𒈲','𒈳'=>'𒈳','ð’ˆ´'=>'ð’ˆ´','𒈵'=>'𒈵','𒈶'=>'𒈶','ð’ˆ·'=>'ð’ˆ·','𒈸'=>'𒈸','𒈹'=>'𒈹','𒈺'=>'𒈺','𒈻'=>'𒈻','𒈼'=>'𒈼','𒈽'=>'𒈽','𒈾'=>'𒈾','𒈿'=>'𒈿','𒉀'=>'𒉀','ð’‰'=>'ð’‰','𒉂'=>'𒉂','𒉃'=>'𒉃','𒉄'=>'𒉄','ð’‰…'=>'ð’‰…','𒉆'=>'𒉆','𒉇'=>'𒉇','𒉈'=>'𒉈','𒉉'=>'𒉉','𒉊'=>'𒉊','𒉋'=>'𒉋','𒉌'=>'𒉌','ð’‰'=>'ð’‰','𒉎'=>'𒉎','ð’‰'=>'ð’‰','ð’‰'=>'ð’‰','𒉑'=>'𒉑','ð’‰’'=>'ð’‰’','𒉓'=>'𒉓','𒉔'=>'𒉔','𒉕'=>'𒉕','ð’‰–'=>'ð’‰–','ð’‰—'=>'ð’‰—','𒉘'=>'𒉘','𒉙'=>'𒉙','𒉚'=>'𒉚','𒉛'=>'𒉛','𒉜'=>'𒉜','ð’‰'=>'ð’‰','𒉞'=>'𒉞','𒉟'=>'𒉟','ð’‰ '=>'ð’‰ ','𒉡'=>'𒉡','𒉢'=>'𒉢','𒉣'=>'𒉣','𒉤'=>'𒉤','𒉥'=>'𒉥','𒉦'=>'𒉦','𒉧'=>'𒉧','𒉨'=>'𒉨','𒉩'=>'𒉩','𒉪'=>'𒉪','𒉫'=>'𒉫','𒉬'=>'𒉬','ð’‰'=>'ð’‰','𒉮'=>'𒉮','𒉯'=>'𒉯','ð’‰°'=>'ð’‰°','𒉱'=>'𒉱','𒉲'=>'𒉲','𒉳'=>'𒉳','ð’‰´'=>'ð’‰´','𒉵'=>'𒉵','𒉶'=>'𒉶','ð’‰·'=>'ð’‰·','𒉸'=>'𒉸','𒉹'=>'𒉹','𒉺'=>'𒉺','𒉻'=>'𒉻','𒉼'=>'𒉼','𒉽'=>'𒉽','𒉾'=>'𒉾','𒉿'=>'𒉿','ð’Š€'=>'ð’Š€','ð’Š'=>'ð’Š','ð’Š‚'=>'ð’Š‚','𒊃'=>'𒊃','ð’Š„'=>'ð’Š„','ð’Š…'=>'ð’Š…','𒊆'=>'𒊆','𒊇'=>'𒊇','𒊈'=>'𒊈','𒊉'=>'𒊉','ð’ŠŠ'=>'ð’ŠŠ','ð’Š‹'=>'ð’Š‹','ð’ŠŒ'=>'ð’ŠŒ','ð’Š'=>'ð’Š','ð’ŠŽ'=>'ð’ŠŽ','ð’Š'=>'ð’Š','ð’Š'=>'ð’Š','ð’Š‘'=>'ð’Š‘','ð’Š’'=>'ð’Š’','ð’Š“'=>'ð’Š“','ð’Š”'=>'ð’Š”','ð’Š•'=>'ð’Š•','ð’Š–'=>'ð’Š–','ð’Š—'=>'ð’Š—','𒊘'=>'𒊘','ð’Š™'=>'ð’Š™','ð’Šš'=>'ð’Šš','ð’Š›'=>'ð’Š›','ð’Šœ'=>'ð’Šœ','ð’Š'=>'ð’Š','ð’Šž'=>'ð’Šž','ð’ŠŸ'=>'ð’ŠŸ','ð’Š '=>'ð’Š ','ð’Š¡'=>'ð’Š¡','ð’Š¢'=>'ð’Š¢','ð’Š£'=>'ð’Š£','𒊤'=>'𒊤','ð’Š¥'=>'ð’Š¥','𒊦'=>'𒊦','𒊧'=>'𒊧','𒊨'=>'𒊨','ð’Š©'=>'ð’Š©','𒊪'=>'𒊪','ð’Š«'=>'ð’Š«','𒊬'=>'𒊬','ð’Š'=>'ð’Š','ð’Š®'=>'ð’Š®','𒊯'=>'𒊯','𒊰'=>'𒊰','𒊱'=>'𒊱','𒊲'=>'𒊲','𒊳'=>'𒊳','ð’Š´'=>'ð’Š´','𒊵'=>'𒊵','𒊶'=>'𒊶','ð’Š·'=>'ð’Š·','𒊸'=>'𒊸','𒊹'=>'𒊹','𒊺'=>'𒊺','ð’Š»'=>'ð’Š»','𒊼'=>'𒊼','𒊽'=>'𒊽','𒊾'=>'𒊾','ð’Š¿'=>'ð’Š¿','ð’‹€'=>'ð’‹€','ð’‹'=>'ð’‹','ð’‹‚'=>'ð’‹‚','𒋃'=>'𒋃','ð’‹„'=>'ð’‹„','ð’‹…'=>'ð’‹…','𒋆'=>'𒋆','𒋇'=>'𒋇','𒋈'=>'𒋈','𒋉'=>'𒋉','ð’‹Š'=>'ð’‹Š','ð’‹‹'=>'ð’‹‹','ð’‹Œ'=>'ð’‹Œ','ð’‹'=>'ð’‹','ð’‹Ž'=>'ð’‹Ž','ð’‹'=>'ð’‹','ð’‹'=>'ð’‹','ð’‹‘'=>'ð’‹‘','ð’‹’'=>'ð’‹’','ð’‹“'=>'ð’‹“','ð’‹”'=>'ð’‹”','ð’‹•'=>'ð’‹•','ð’‹–'=>'ð’‹–','ð’‹—'=>'ð’‹—','𒋘'=>'𒋘','ð’‹™'=>'ð’‹™','ð’‹š'=>'ð’‹š','ð’‹›'=>'ð’‹›','ð’‹œ'=>'ð’‹œ','ð’‹'=>'ð’‹','ð’‹ž'=>'ð’‹ž','ð’‹Ÿ'=>'ð’‹Ÿ','ð’‹ '=>'ð’‹ ','ð’‹¡'=>'ð’‹¡','ð’‹¢'=>'ð’‹¢','ð’‹£'=>'ð’‹£','𒋤'=>'𒋤','ð’‹¥'=>'ð’‹¥','𒋦'=>'𒋦','ð’‹§'=>'ð’‹§','𒋨'=>'𒋨','ð’‹©'=>'ð’‹©','𒋪'=>'𒋪','ð’‹«'=>'ð’‹«','𒋬'=>'𒋬','ð’‹'=>'ð’‹','ð’‹®'=>'ð’‹®','𒋯'=>'𒋯','ð’‹°'=>'ð’‹°','ð’‹±'=>'ð’‹±','ð’‹²'=>'ð’‹²','ð’‹³'=>'ð’‹³','ð’‹´'=>'ð’‹´','ð’‹µ'=>'ð’‹µ','ð’‹¶'=>'ð’‹¶','ð’‹·'=>'ð’‹·','𒋸'=>'𒋸','ð’‹¹'=>'ð’‹¹','𒋺'=>'𒋺','ð’‹»'=>'ð’‹»','ð’‹¼'=>'ð’‹¼','ð’‹½'=>'ð’‹½','ð’‹¾'=>'ð’‹¾','ð’‹¿'=>'ð’‹¿','𒌀'=>'𒌀','ð’Œ'=>'ð’Œ','𒌂'=>'𒌂','𒌃'=>'𒌃','𒌄'=>'𒌄','𒌅'=>'𒌅','𒌆'=>'𒌆','𒌇'=>'𒌇','𒌈'=>'𒌈','𒌉'=>'𒌉','𒌊'=>'𒌊','𒌋'=>'𒌋','𒌌'=>'𒌌','ð’Œ'=>'ð’Œ','𒌎'=>'𒌎','ð’Œ'=>'ð’Œ','ð’Œ'=>'ð’Œ','𒌑'=>'𒌑','𒌒'=>'𒌒','𒌓'=>'𒌓','𒌔'=>'𒌔','𒌕'=>'𒌕','𒌖'=>'𒌖','𒌗'=>'𒌗','𒌘'=>'𒌘','𒌙'=>'𒌙','𒌚'=>'𒌚','𒌛'=>'𒌛','𒌜'=>'𒌜','ð’Œ'=>'ð’Œ','𒌞'=>'𒌞','𒌟'=>'𒌟','𒌠'=>'𒌠','𒌡'=>'𒌡','𒌢'=>'𒌢','𒌣'=>'𒌣','𒌤'=>'𒌤','𒌥'=>'𒌥','𒌦'=>'𒌦','𒌧'=>'𒌧','𒌨'=>'𒌨','𒌩'=>'𒌩','𒌪'=>'𒌪','𒌫'=>'𒌫','𒌬'=>'𒌬','ð’Œ'=>'ð’Œ','𒌮'=>'𒌮','𒌯'=>'𒌯','𒌰'=>'𒌰','𒌱'=>'𒌱','𒌲'=>'𒌲','𒌳'=>'𒌳','𒌴'=>'𒌴','𒌵'=>'𒌵','𒌶'=>'𒌶','𒌷'=>'𒌷','𒌸'=>'𒌸','𒌹'=>'𒌹','𒌺'=>'𒌺','𒌻'=>'𒌻','𒌼'=>'𒌼','𒌽'=>'𒌽','𒌾'=>'𒌾','𒌿'=>'𒌿','ð’€'=>'ð’€','ð’'=>'ð’','ð’‚'=>'ð’‚','ð’ƒ'=>'ð’ƒ','ð’„'=>'ð’„','ð’…'=>'ð’…','ð’†'=>'ð’†','ð’‡'=>'ð’‡','ð’ˆ'=>'ð’ˆ','ð’‰'=>'ð’‰','ð’Š'=>'ð’Š','ð’‹'=>'ð’‹','ð’Œ'=>'ð’Œ','ð’'=>'ð’','ð’Ž'=>'ð’Ž','ð’'=>'ð’','ð’'=>'ð’','ð’‘'=>'ð’‘','ð’’'=>'ð’’','ð’“'=>'ð’“','ð’”'=>'ð’”','ð’•'=>'ð’•','ð’–'=>'ð’–','ð’—'=>'ð’—','ð’˜'=>'ð’˜','ð’™'=>'ð’™','ð’š'=>'ð’š','ð’›'=>'ð’›','ð’œ'=>'ð’œ','ð’'=>'ð’','ð’ž'=>'ð’ž','ð’Ÿ'=>'ð’Ÿ','ð’ '=>'ð’ ','ð’¡'=>'ð’¡','ð’¢'=>'ð’¢','ð’£'=>'ð’£','ð’¤'=>'ð’¤','ð’¥'=>'ð’¥','ð’¦'=>'ð’¦','ð’§'=>'ð’§','ð’¨'=>'ð’¨','ð’©'=>'ð’©','ð’ª'=>'ð’ª','ð’«'=>'ð’«','ð’¬'=>'ð’¬','ð’'=>'ð’','ð’®'=>'ð’®','ð’€'=>'2','ð’'=>'3','ð’‚'=>'4','ð’ƒ'=>'5','ð’„'=>'6','ð’…'=>'7','ð’†'=>'8','ð’‡'=>'9','ð’ˆ'=>'3','ð’‰'=>'4','ð’Š'=>'5','ð’‹'=>'6','ð’Œ'=>'7','ð’'=>'8','ð’Ž'=>'9','ð’'=>'4','ð’'=>'5','ð’‘'=>'6','ð’’'=>'7','ð’“'=>'8','ð’”'=>'9','ð’•'=>'1','ð’–'=>'2','ð’—'=>'3','ð’˜'=>'4','ð’™'=>'5','ð’š'=>'6','ð’›'=>'7','ð’œ'=>'8','ð’'=>'9','ð’ž'=>'1','ð’Ÿ'=>'2','ð’ '=>'3','ð’¡'=>'4','ð’¢'=>'5','ð’£'=>'2','ð’¤'=>'3','ð’¥'=>'3','ð’¦'=>'4','ð’§'=>'5','ð’¨'=>'6','ð’©'=>'7','ð’ª'=>'8','ð’«'=>'9','ð’¬'=>'1','ð’'=>'2','ð’®'=>'3','ð’¯'=>'3','ð’°'=>'4','ð’±'=>'5','ð’²'=>'ð’²','ð’³'=>'ð’³','ð’´'=>'1','ð’µ'=>'2','ð’¶'=>'3','ð’·'=>'3','ð’¸'=>'4','ð’¹'=>'5','ð’º'=>'3','ð’»'=>'3','ð’¼'=>'4','ð’½'=>'4','ð’¾'=>'4','ð’¿'=>'4','ð’‘€'=>'6','ð’‘'=>'7','ð’‘‚'=>'7','𒑃'=>'7','ð’‘„'=>'8','ð’‘…'=>'8','𒑆'=>'9','𒑇'=>'9','𒑈'=>'9','𒑉'=>'9','ð’‘Š'=>'2','ð’‘‹'=>'3','ð’‘Œ'=>'4','ð’‘'=>'5','ð’‘Ž'=>'6','ð’‘'=>'1','ð’‘'=>'2','ð’‘‘'=>'3','ð’‘’'=>'4','ð’‘“'=>'4','ð’‘”'=>'5','ð’‘•'=>'5','ð’‘–'=>'ð’‘–','ð’‘—'=>'ð’‘—','𒑘'=>'1','ð’‘™'=>'2','ð’‘š'=>'1/3','ð’‘›'=>'2/3','ð’‘œ'=>'5/6','ð’‘'=>'1/3','ð’‘ž'=>'2/3','ð’‘Ÿ'=>'1/8','ð’‘ '=>'1/4','ð’‘¡'=>'1/6','ð’‘¢'=>'1/4');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_4.php b/phpBB/includes/utf/data/search_indexer_4.php deleted file mode 100644 index 51acbff1c2..0000000000 --- a/phpBB/includes/utf/data/search_indexer_4.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('â°'=>'0','â±'=>'â±','â´'=>'4','âµ'=>'5','â¶'=>'6','â·'=>'7','â¸'=>'8','â¹'=>'9','â¿'=>'â¿','â‚€'=>'0','â‚'=>'1','â‚‚'=>'2','₃'=>'3','â‚„'=>'4','â‚…'=>'5','₆'=>'6','₇'=>'7','₈'=>'8','₉'=>'9','â‚'=>'â‚','â‚‘'=>'â‚‘','â‚’'=>'â‚’','â‚“'=>'â‚“','â‚”'=>'â‚”','âƒ'=>'âƒ','⃑'=>'⃑','⃒'=>'⃒','⃓'=>'⃓','⃔'=>'⃔','⃕'=>'⃕','⃖'=>'⃖','⃗'=>'⃗','⃘'=>'⃘','⃙'=>'⃙','⃚'=>'⃚','⃛'=>'⃛','⃜'=>'⃜','âƒ'=>'âƒ','⃞'=>'⃞','⃟'=>'⃟','⃠'=>'⃠','⃡'=>'⃡','⃢'=>'⃢','⃣'=>'⃣','⃤'=>'⃤','⃥'=>'⃥','⃦'=>'⃦','⃧'=>'⃧','⃨'=>'⃨','⃩'=>'⃩','⃪'=>'⃪','⃫'=>'⃫','⃬'=>'⃬','âƒ'=>'âƒ','⃮'=>'⃮','⃯'=>'⃯','â„‚'=>'â„‚','ℇ'=>'ℇ','ℊ'=>'ℊ','â„‹'=>'â„‹','ℌ'=>'ℌ','â„'=>'â„','ℎ'=>'ℎ','â„'=>'â„','â„'=>'â„','â„‘'=>'â„‘','â„’'=>'â„’','â„“'=>'â„“','â„•'=>'â„•','â„™'=>'â„™','ℚ'=>'ℚ','â„›'=>'â„›','ℜ'=>'ℜ','â„'=>'â„','ℤ'=>'ℤ','Ω'=>'ω','ℨ'=>'ℨ','K'=>'k','â„«'=>'Ã¥','ℬ'=>'ℬ','â„'=>'â„','ℯ'=>'ℯ','â„°'=>'â„°','ℱ'=>'ℱ','Ⅎ'=>'â…Ž','ℳ'=>'ℳ','â„´'=>'â„´','ℵ'=>'ℵ','â„¶'=>'â„¶','â„·'=>'â„·','ℸ'=>'ℸ','ℹ'=>'ℹ','ℼ'=>'ℼ','ℽ'=>'ℽ','ℾ'=>'ℾ','â„¿'=>'â„¿','â……'=>'â……','â…†'=>'â…†','â…‡'=>'â…‡','â…ˆ'=>'â…ˆ','â…‰'=>'â…‰','â…Ž'=>'â…Ž','â…“'=>'1/3','â…”'=>'2/3','â…•'=>'1/5','â…–'=>'2/5','â…—'=>'3/5','â…˜'=>'4/5','â…™'=>'1/6','â…š'=>'5/6','â…›'=>'1/8','â…œ'=>'3/8','â…'=>'5/8','â…ž'=>'7/8','â…Ÿ'=>'1','â… '=>'1','â…¡'=>'2','â…¢'=>'3','â…£'=>'4','â…¤'=>'5','â…¥'=>'6','â…¦'=>'7','â…§'=>'8','â…¨'=>'9','â…©'=>'10','â…ª'=>'11','â…«'=>'12','â…¬'=>'50','â…'=>'100','â…®'=>'500','â…¯'=>'1000','â…°'=>'1','â…±'=>'2','â…²'=>'3','â…³'=>'4','â…´'=>'5','â…µ'=>'6','â…¶'=>'7','â…·'=>'8','â…¸'=>'9','â…¹'=>'10','â…º'=>'11','â…»'=>'12','â…¼'=>'50','â…½'=>'100','â…¾'=>'500','â…¿'=>'1000','ↀ'=>'1000','â†'=>'5000','ↂ'=>'10000','Ↄ'=>'ↄ','ↄ'=>'ↄ','â‘ '=>'1','â‘¡'=>'2','â‘¢'=>'3','â‘£'=>'4','⑤'=>'5','â‘¥'=>'6','⑦'=>'7','â‘§'=>'8','⑨'=>'9','â‘©'=>'10','⑪'=>'11','â‘«'=>'12','⑬'=>'13','â‘'=>'14','â‘®'=>'15','⑯'=>'16','â‘°'=>'17','⑱'=>'18','⑲'=>'19','⑳'=>'20','â‘´'=>'1','⑵'=>'2','â‘¶'=>'3','â‘·'=>'4','⑸'=>'5','⑹'=>'6','⑺'=>'7','â‘»'=>'8','⑼'=>'9','⑽'=>'10','⑾'=>'11','â‘¿'=>'12','â’€'=>'13','â’'=>'14','â’‚'=>'15','â’ƒ'=>'16','â’„'=>'17','â’…'=>'18','â’†'=>'19','â’‡'=>'20','â’ˆ'=>'1','â’‰'=>'2','â’Š'=>'3','â’‹'=>'4','â’Œ'=>'5','â’'=>'6','â’Ž'=>'7','â’'=>'8','â’'=>'9','â’‘'=>'10','â’’'=>'11','â’“'=>'12','â’”'=>'13','â’•'=>'14','â’–'=>'15','â’—'=>'16','â’˜'=>'17','â’™'=>'18','â’š'=>'19','â’›'=>'20','⓪'=>'0','â“«'=>'11','⓬'=>'12','â“'=>'13','â“®'=>'14','⓯'=>'15','â“°'=>'16','⓱'=>'17','⓲'=>'18','⓳'=>'19','â“´'=>'20','⓵'=>'1','â“¶'=>'2','â“·'=>'3','⓸'=>'4','⓹'=>'5','⓺'=>'6','â“»'=>'7','⓼'=>'8','⓽'=>'9','⓾'=>'10','â“¿'=>'0','â¶'=>'1','â·'=>'2','â¸'=>'3','â¹'=>'4','âº'=>'5','â»'=>'6','â¼'=>'7','â½'=>'8','â¾'=>'9','â¿'=>'10','➀'=>'1','âž'=>'2','âž‚'=>'3','➃'=>'4','âž„'=>'5','âž…'=>'6','➆'=>'7','➇'=>'8','➈'=>'9','➉'=>'10','➊'=>'1','âž‹'=>'2','➌'=>'3','âž'=>'4','➎'=>'5','âž'=>'6','âž'=>'7','âž‘'=>'8','âž’'=>'9','âž“'=>'10');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_448.php b/phpBB/includes/utf/data/search_indexer_448.php deleted file mode 100644 index 32ac28a549..0000000000 --- a/phpBB/includes/utf/data/search_indexer_448.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('ó „€'=>'ó „€','ó „'=>'ó „','ó „‚'=>'ó „‚','ó „ƒ'=>'ó „ƒ','ó „„'=>'ó „„','ó „…'=>'ó „…','ó „†'=>'ó „†','ó „‡'=>'ó „‡','ó „ˆ'=>'ó „ˆ','ó „‰'=>'ó „‰','ó „Š'=>'ó „Š','ó „‹'=>'ó „‹','ó „Œ'=>'ó „Œ','ó „'=>'ó „','ó „Ž'=>'ó „Ž','ó „'=>'ó „','ó „'=>'ó „','ó „‘'=>'ó „‘','ó „’'=>'ó „’','ó „“'=>'ó „“','ó „”'=>'ó „”','ó „•'=>'ó „•','ó „–'=>'ó „–','ó „—'=>'ó „—','ó „˜'=>'ó „˜','ó „™'=>'ó „™','ó „š'=>'ó „š','ó „›'=>'ó „›','ó „œ'=>'ó „œ','ó „'=>'ó „','ó „ž'=>'ó „ž','ó „Ÿ'=>'ó „Ÿ','ó „ '=>'ó „ ','ó „¡'=>'ó „¡','ó „¢'=>'ó „¢','ó „£'=>'ó „£','ó „¤'=>'ó „¤','ó „¥'=>'ó „¥','ó „¦'=>'ó „¦','ó „§'=>'ó „§','ó „¨'=>'ó „¨','ó „©'=>'ó „©','ó „ª'=>'ó „ª','ó „«'=>'ó „«','ó „¬'=>'ó „¬','ó „'=>'ó „','ó „®'=>'ó „®','ó „¯'=>'ó „¯','ó „°'=>'ó „°','ó „±'=>'ó „±','ó „²'=>'ó „²','ó „³'=>'ó „³','ó „´'=>'ó „´','ó „µ'=>'ó „µ','ó „¶'=>'ó „¶','ó „·'=>'ó „·','ó „¸'=>'ó „¸','ó „¹'=>'ó „¹','ó „º'=>'ó „º','ó „»'=>'ó „»','ó „¼'=>'ó „¼','ó „½'=>'ó „½','ó „¾'=>'ó „¾','ó „¿'=>'ó „¿','ó …€'=>'ó …€','ó …'=>'ó …','ó …‚'=>'ó …‚','ó …ƒ'=>'ó …ƒ','ó …„'=>'ó …„','ó ……'=>'ó ……','ó …†'=>'ó …†','ó …‡'=>'ó …‡','ó …ˆ'=>'ó …ˆ','ó …‰'=>'ó …‰','ó …Š'=>'ó …Š','ó …‹'=>'ó …‹','ó …Œ'=>'ó …Œ','ó …'=>'ó …','ó …Ž'=>'ó …Ž','ó …'=>'ó …','ó …'=>'ó …','ó …‘'=>'ó …‘','ó …’'=>'ó …’','ó …“'=>'ó …“','ó …”'=>'ó …”','ó …•'=>'ó …•','ó …–'=>'ó …–','ó …—'=>'ó …—','ó …˜'=>'ó …˜','ó …™'=>'ó …™','ó …š'=>'ó …š','ó …›'=>'ó …›','ó …œ'=>'ó …œ','ó …'=>'ó …','ó …ž'=>'ó …ž','ó …Ÿ'=>'ó …Ÿ','ó … '=>'ó … ','ó …¡'=>'ó …¡','ó …¢'=>'ó …¢','ó …£'=>'ó …£','ó …¤'=>'ó …¤','ó …¥'=>'ó …¥','ó …¦'=>'ó …¦','ó …§'=>'ó …§','ó …¨'=>'ó …¨','ó …©'=>'ó …©','ó …ª'=>'ó …ª','ó …«'=>'ó …«','ó …¬'=>'ó …¬','ó …'=>'ó …','ó …®'=>'ó …®','ó …¯'=>'ó …¯','ó …°'=>'ó …°','ó …±'=>'ó …±','ó …²'=>'ó …²','ó …³'=>'ó …³','ó …´'=>'ó …´','ó …µ'=>'ó …µ','ó …¶'=>'ó …¶','ó …·'=>'ó …·','ó …¸'=>'ó …¸','ó …¹'=>'ó …¹','ó …º'=>'ó …º','ó …»'=>'ó …»','ó …¼'=>'ó …¼','ó …½'=>'ó …½','ó …¾'=>'ó …¾','ó …¿'=>'ó …¿','ó †€'=>'ó †€','ó †'=>'ó †','ó †‚'=>'ó †‚','ó †ƒ'=>'ó †ƒ','ó †„'=>'ó †„','ó †…'=>'ó †…','ó ††'=>'ó ††','ó †‡'=>'ó †‡','ó †ˆ'=>'ó †ˆ','ó †‰'=>'ó †‰','ó †Š'=>'ó †Š','ó †‹'=>'ó †‹','ó †Œ'=>'ó †Œ','ó †'=>'ó †','ó †Ž'=>'ó †Ž','ó †'=>'ó †','ó †'=>'ó †','ó †‘'=>'ó †‘','ó †’'=>'ó †’','ó †“'=>'ó †“','ó †”'=>'ó †”','ó †•'=>'ó †•','ó †–'=>'ó †–','ó †—'=>'ó †—','ó †˜'=>'ó †˜','ó †™'=>'ó †™','ó †š'=>'ó †š','ó †›'=>'ó †›','ó †œ'=>'ó †œ','ó †'=>'ó †','ó †ž'=>'ó †ž','ó †Ÿ'=>'ó †Ÿ','ó † '=>'ó † ','ó †¡'=>'ó †¡','ó †¢'=>'ó †¢','ó †£'=>'ó †£','ó †¤'=>'ó †¤','ó †¥'=>'ó †¥','ó †¦'=>'ó †¦','ó †§'=>'ó †§','ó †¨'=>'ó †¨','ó †©'=>'ó †©','ó †ª'=>'ó †ª','ó †«'=>'ó †«','ó †¬'=>'ó †¬','ó †'=>'ó †','ó †®'=>'ó †®','ó †¯'=>'ó †¯','ó †°'=>'ó †°','ó †±'=>'ó †±','ó †²'=>'ó †²','ó †³'=>'ó †³','ó †´'=>'ó †´','ó †µ'=>'ó †µ','ó †¶'=>'ó †¶','ó †·'=>'ó †·','ó †¸'=>'ó †¸','ó †¹'=>'ó †¹','ó †º'=>'ó †º','ó †»'=>'ó †»','ó †¼'=>'ó †¼','ó †½'=>'ó †½','ó †¾'=>'ó †¾','ó †¿'=>'ó †¿','ó ‡€'=>'ó ‡€','ó ‡'=>'ó ‡','ó ‡‚'=>'ó ‡‚','ó ‡ƒ'=>'ó ‡ƒ','ó ‡„'=>'ó ‡„','ó ‡…'=>'ó ‡…','ó ‡†'=>'ó ‡†','ó ‡‡'=>'ó ‡‡','ó ‡ˆ'=>'ó ‡ˆ','ó ‡‰'=>'ó ‡‰','ó ‡Š'=>'ó ‡Š','ó ‡‹'=>'ó ‡‹','ó ‡Œ'=>'ó ‡Œ','ó ‡'=>'ó ‡','ó ‡Ž'=>'ó ‡Ž','ó ‡'=>'ó ‡','ó ‡'=>'ó ‡','ó ‡‘'=>'ó ‡‘','ó ‡’'=>'ó ‡’','ó ‡“'=>'ó ‡“','ó ‡”'=>'ó ‡”','ó ‡•'=>'ó ‡•','ó ‡–'=>'ó ‡–','ó ‡—'=>'ó ‡—','ó ‡˜'=>'ó ‡˜','ó ‡™'=>'ó ‡™','ó ‡š'=>'ó ‡š','ó ‡›'=>'ó ‡›','ó ‡œ'=>'ó ‡œ','ó ‡'=>'ó ‡','ó ‡ž'=>'ó ‡ž','ó ‡Ÿ'=>'ó ‡Ÿ','ó ‡ '=>'ó ‡ ','ó ‡¡'=>'ó ‡¡','ó ‡¢'=>'ó ‡¢','ó ‡£'=>'ó ‡£','ó ‡¤'=>'ó ‡¤','ó ‡¥'=>'ó ‡¥','ó ‡¦'=>'ó ‡¦','ó ‡§'=>'ó ‡§','ó ‡¨'=>'ó ‡¨','ó ‡©'=>'ó ‡©','ó ‡ª'=>'ó ‡ª','ó ‡«'=>'ó ‡«','ó ‡¬'=>'ó ‡¬','ó ‡'=>'ó ‡','ó ‡®'=>'ó ‡®','ó ‡¯'=>'ó ‡¯');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_5.php b/phpBB/includes/utf/data/search_indexer_5.php deleted file mode 100644 index 0f1228a394..0000000000 --- a/phpBB/includes/utf/data/search_indexer_5.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('â°€'=>'â°°','â°'=>'â°±','â°‚'=>'â°²','â°ƒ'=>'â°³','â°„'=>'â°´','â°…'=>'â°µ','â°†'=>'â°¶','â°‡'=>'â°·','â°ˆ'=>'â°¸','â°‰'=>'â°¹','â°Š'=>'â°º','â°‹'=>'â°»','â°Œ'=>'â°¼','â°'=>'â°½','â°Ž'=>'â°¾','â°'=>'â°¿','â°'=>'â±€','â°‘'=>'â±','â°’'=>'ⱂ','â°“'=>'ⱃ','â°”'=>'ⱄ','â°•'=>'â±…','â°–'=>'ⱆ','â°—'=>'ⱇ','â°˜'=>'ⱈ','â°™'=>'ⱉ','â°š'=>'ⱊ','â°›'=>'ⱋ','â°œ'=>'ⱌ','â°'=>'â±','â°ž'=>'ⱎ','â°Ÿ'=>'â±','â° '=>'â±','â°¡'=>'ⱑ','â°¢'=>'â±’','â°£'=>'ⱓ','â°¤'=>'â±”','â°¥'=>'ⱕ','â°¦'=>'â±–','â°§'=>'â±—','â°¨'=>'ⱘ','â°©'=>'â±™','â°ª'=>'ⱚ','â°«'=>'â±›','â°¬'=>'ⱜ','â°'=>'â±','â°®'=>'ⱞ','â°°'=>'â°°','â°±'=>'â°±','â°²'=>'â°²','â°³'=>'â°³','â°´'=>'â°´','â°µ'=>'â°µ','â°¶'=>'â°¶','â°·'=>'â°·','â°¸'=>'â°¸','â°¹'=>'â°¹','â°º'=>'â°º','â°»'=>'â°»','â°¼'=>'â°¼','â°½'=>'â°½','â°¾'=>'â°¾','â°¿'=>'â°¿','â±€'=>'â±€','â±'=>'â±','ⱂ'=>'ⱂ','ⱃ'=>'ⱃ','ⱄ'=>'ⱄ','â±…'=>'â±…','ⱆ'=>'ⱆ','ⱇ'=>'ⱇ','ⱈ'=>'ⱈ','ⱉ'=>'ⱉ','ⱊ'=>'ⱊ','ⱋ'=>'ⱋ','ⱌ'=>'ⱌ','â±'=>'â±','ⱎ'=>'ⱎ','â±'=>'â±','â±'=>'â±','ⱑ'=>'ⱑ','â±’'=>'â±’','ⱓ'=>'ⱓ','â±”'=>'â±”','ⱕ'=>'ⱕ','â±–'=>'â±–','â±—'=>'â±—','ⱘ'=>'ⱘ','â±™'=>'â±™','ⱚ'=>'ⱚ','â±›'=>'â±›','ⱜ'=>'ⱜ','â±'=>'â±','ⱞ'=>'ⱞ','â± '=>'ⱡ','ⱡ'=>'ⱡ','â±¢'=>'É«','â±£'=>'áµ½','Ɽ'=>'ɽ','â±¥'=>'â±¥','ⱦ'=>'ⱦ','â±§'=>'ⱨ','ⱨ'=>'ⱨ','Ⱪ'=>'ⱪ','ⱪ'=>'ⱪ','Ⱬ'=>'ⱬ','ⱬ'=>'ⱬ','â±´'=>'â±´','â±µ'=>'â±¶','â±¶'=>'â±¶','â±·'=>'â±·','â²€'=>'â²','â²'=>'â²','Ⲃ'=>'ⲃ','ⲃ'=>'ⲃ','Ⲅ'=>'â²…','â²…'=>'â²…','Ⲇ'=>'ⲇ','ⲇ'=>'ⲇ','Ⲉ'=>'ⲉ','ⲉ'=>'ⲉ','Ⲋ'=>'ⲋ','ⲋ'=>'ⲋ','Ⲍ'=>'â²','â²'=>'â²','Ⲏ'=>'â²','â²'=>'â²','â²'=>'ⲑ','ⲑ'=>'ⲑ','â²’'=>'ⲓ','ⲓ'=>'ⲓ','â²”'=>'ⲕ','ⲕ'=>'ⲕ','â²–'=>'â²—','â²—'=>'â²—','Ⲙ'=>'â²™','â²™'=>'â²™','Ⲛ'=>'â²›','â²›'=>'â²›','Ⲝ'=>'â²','â²'=>'â²','Ⲟ'=>'ⲟ','ⲟ'=>'ⲟ','â² '=>'ⲡ','ⲡ'=>'ⲡ','â²¢'=>'â²£','â²£'=>'â²£','Ⲥ'=>'â²¥','â²¥'=>'â²¥','Ⲧ'=>'â²§','â²§'=>'â²§','Ⲩ'=>'ⲩ','ⲩ'=>'ⲩ','Ⲫ'=>'ⲫ','ⲫ'=>'ⲫ','Ⲭ'=>'â²','â²'=>'â²','â²®'=>'ⲯ','ⲯ'=>'ⲯ','â²°'=>'â²±','â²±'=>'â²±','â²²'=>'â²³','â²³'=>'â²³','â²´'=>'â²µ','â²µ'=>'â²µ','â²¶'=>'â²·','â²·'=>'â²·','Ⲹ'=>'â²¹','â²¹'=>'â²¹','Ⲻ'=>'â²»','â²»'=>'â²»','â²¼'=>'â²½','â²½'=>'â²½','â²¾'=>'ⲿ','ⲿ'=>'ⲿ','â³€'=>'â³','â³'=>'â³','Ⳃ'=>'ⳃ','ⳃ'=>'ⳃ','Ⳅ'=>'â³…','â³…'=>'â³…','Ⳇ'=>'ⳇ','ⳇ'=>'ⳇ','Ⳉ'=>'ⳉ','ⳉ'=>'ⳉ','Ⳋ'=>'ⳋ','ⳋ'=>'ⳋ','Ⳍ'=>'â³','â³'=>'â³','Ⳏ'=>'â³','â³'=>'â³','â³'=>'ⳑ','ⳑ'=>'ⳑ','â³’'=>'ⳓ','ⳓ'=>'ⳓ','â³”'=>'ⳕ','ⳕ'=>'ⳕ','â³–'=>'â³—','â³—'=>'â³—','Ⳙ'=>'â³™','â³™'=>'â³™','Ⳛ'=>'â³›','â³›'=>'â³›','Ⳝ'=>'â³','â³'=>'â³','Ⳟ'=>'ⳟ','ⳟ'=>'ⳟ','â³ '=>'ⳡ','ⳡ'=>'ⳡ','â³¢'=>'â³£','â³£'=>'â³£','ⳤ'=>'ⳤ','â³½'=>'1/2','â´€'=>'â´€','â´'=>'â´','â´‚'=>'â´‚','â´ƒ'=>'â´ƒ','â´„'=>'â´„','â´…'=>'â´…','â´†'=>'â´†','â´‡'=>'â´‡','â´ˆ'=>'â´ˆ','â´‰'=>'â´‰','â´Š'=>'â´Š','â´‹'=>'â´‹','â´Œ'=>'â´Œ','â´'=>'â´','â´Ž'=>'â´Ž','â´'=>'â´','â´'=>'â´','â´‘'=>'â´‘','â´’'=>'â´’','â´“'=>'â´“','â´”'=>'â´”','â´•'=>'â´•','â´–'=>'â´–','â´—'=>'â´—','â´˜'=>'â´˜','â´™'=>'â´™','â´š'=>'â´š','â´›'=>'â´›','â´œ'=>'â´œ','â´'=>'â´','â´ž'=>'â´ž','â´Ÿ'=>'â´Ÿ','â´ '=>'â´ ','â´¡'=>'â´¡','â´¢'=>'â´¢','â´£'=>'â´£','â´¤'=>'â´¤','â´¥'=>'â´¥','â´°'=>'â´°','â´±'=>'â´±','â´²'=>'â´²','â´³'=>'â´³','â´´'=>'â´´','â´µ'=>'â´µ','â´¶'=>'â´¶','â´·'=>'â´·','â´¸'=>'â´¸','â´¹'=>'â´¹','â´º'=>'â´º','â´»'=>'â´»','â´¼'=>'â´¼','â´½'=>'â´½','â´¾'=>'â´¾','â´¿'=>'â´¿','âµ€'=>'âµ€','âµ'=>'âµ','ⵂ'=>'ⵂ','ⵃ'=>'ⵃ','ⵄ'=>'ⵄ','âµ…'=>'âµ…','ⵆ'=>'ⵆ','ⵇ'=>'ⵇ','ⵈ'=>'ⵈ','ⵉ'=>'ⵉ','ⵊ'=>'ⵊ','ⵋ'=>'ⵋ','ⵌ'=>'ⵌ','âµ'=>'âµ','ⵎ'=>'ⵎ','âµ'=>'âµ','âµ'=>'âµ','ⵑ'=>'ⵑ','âµ’'=>'âµ’','ⵓ'=>'ⵓ','âµ”'=>'âµ”','ⵕ'=>'ⵕ','âµ–'=>'âµ–','âµ—'=>'âµ—','ⵘ'=>'ⵘ','âµ™'=>'âµ™','ⵚ'=>'ⵚ','âµ›'=>'âµ›','ⵜ'=>'ⵜ','âµ'=>'âµ','ⵞ'=>'ⵞ','ⵟ'=>'ⵟ','âµ '=>'âµ ','ⵡ'=>'ⵡ','âµ¢'=>'âµ¢','âµ£'=>'âµ£','ⵤ'=>'ⵤ','âµ¥'=>'âµ¥','ⵯ'=>'ⵯ','â¶€'=>'â¶€','â¶'=>'â¶','â¶‚'=>'â¶‚','ⶃ'=>'ⶃ','â¶„'=>'â¶„','â¶…'=>'â¶…','ⶆ'=>'ⶆ','ⶇ'=>'ⶇ','ⶈ'=>'ⶈ','ⶉ'=>'ⶉ','â¶Š'=>'â¶Š','â¶‹'=>'â¶‹','â¶Œ'=>'â¶Œ','â¶'=>'â¶','â¶Ž'=>'â¶Ž','â¶'=>'â¶','â¶'=>'â¶','â¶‘'=>'â¶‘','â¶’'=>'â¶’','â¶“'=>'â¶“','â¶”'=>'â¶”','â¶•'=>'â¶•','â¶–'=>'â¶–','â¶ '=>'â¶ ','â¶¡'=>'â¶¡','â¶¢'=>'â¶¢','â¶£'=>'â¶£','ⶤ'=>'ⶤ','â¶¥'=>'â¶¥','ⶦ'=>'ⶦ','ⶨ'=>'ⶨ','â¶©'=>'â¶©','ⶪ'=>'ⶪ','â¶«'=>'â¶«','ⶬ'=>'ⶬ','â¶'=>'â¶','â¶®'=>'â¶®','â¶°'=>'â¶°','â¶±'=>'â¶±','â¶²'=>'â¶²','â¶³'=>'â¶³','â¶´'=>'â¶´','â¶µ'=>'â¶µ','â¶¶'=>'â¶¶','ⶸ'=>'ⶸ','â¶¹'=>'â¶¹','ⶺ'=>'ⶺ','â¶»'=>'â¶»','â¶¼'=>'â¶¼','â¶½'=>'â¶½','â¶¾'=>'â¶¾','â·€'=>'â·€','â·'=>'â·','â·‚'=>'â·‚','â·ƒ'=>'â·ƒ','â·„'=>'â·„','â·…'=>'â·…','â·†'=>'â·†','â·ˆ'=>'â·ˆ','â·‰'=>'â·‰','â·Š'=>'â·Š','â·‹'=>'â·‹','â·Œ'=>'â·Œ','â·'=>'â·','â·Ž'=>'â·Ž','â·'=>'â·','â·‘'=>'â·‘','â·’'=>'â·’','â·“'=>'â·“','â·”'=>'â·”','â·•'=>'â·•','â·–'=>'â·–','â·˜'=>'â·˜','â·™'=>'â·™','â·š'=>'â·š','â·›'=>'â·›','â·œ'=>'â·œ','â·'=>'â·','â·ž'=>'â·ž');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_58.php b/phpBB/includes/utf/data/search_indexer_58.php deleted file mode 100644 index 8902bc7995..0000000000 --- a/phpBB/includes/utf/data/search_indexer_58.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('ð…¥'=>'ð…¥','ð…¦'=>'ð…¦','ð…§'=>'ð…§','ð…¨'=>'ð…¨','ð…©'=>'ð…©','ð…'=>'ð…','ð…®'=>'ð…®','ð…¯'=>'ð…¯','ð…°'=>'ð…°','ð…±'=>'ð…±','ð…²'=>'ð…²','ð…»'=>'ð…»','ð…¼'=>'ð…¼','ð…½'=>'ð…½','ð…¾'=>'ð…¾','ð…¿'=>'ð…¿','ð†€'=>'ð†€','ð†'=>'ð†','ð†‚'=>'ð†‚','ð†…'=>'ð†…','ð††'=>'ð††','ð†‡'=>'ð†‡','ð†ˆ'=>'ð†ˆ','ð†‰'=>'ð†‰','ð†Š'=>'ð†Š','ð†‹'=>'ð†‹','ð†ª'=>'ð†ª','ð†«'=>'ð†«','ð†¬'=>'ð†¬','ð†'=>'ð†','ð‰‚'=>'ð‰‚','ð‰ƒ'=>'ð‰ƒ','ð‰„'=>'ð‰„','ð '=>'1','ð¡'=>'2','ð¢'=>'3','ð£'=>'4','ð¤'=>'5','ð¥'=>'6','ð¦'=>'7','ð§'=>'8','ð¨'=>'9','ð©'=>'10','ðª'=>'20','ð«'=>'30','ð¬'=>'40','ð'=>'50','ð®'=>'60','ð¯'=>'70','ð°'=>'80','ð±'=>'90','ð€'=>'ð€','ð'=>'ð','ð‚'=>'ð‚','ðƒ'=>'ðƒ','ð„'=>'ð„','ð…'=>'ð…','ð†'=>'ð†','ð‡'=>'ð‡','ðˆ'=>'ðˆ','ð‰'=>'ð‰','ðŠ'=>'ðŠ','ð‹'=>'ð‹','ðŒ'=>'ðŒ','ð'=>'ð','ðŽ'=>'ðŽ','ð'=>'ð','ð'=>'ð','ð‘'=>'ð‘','ð’'=>'ð’','ð“'=>'ð“','ð”'=>'ð”','ð•'=>'ð•','ð–'=>'ð–','ð—'=>'ð—','ð˜'=>'ð˜','ð™'=>'ð™','ðš'=>'ðš','ð›'=>'ð›','ðœ'=>'ðœ','ð'=>'ð','ðž'=>'ðž','ðŸ'=>'ðŸ','ð '=>'ð ','ð¡'=>'ð¡','ð¢'=>'ð¢','ð£'=>'ð£','ð¤'=>'ð¤','ð¥'=>'ð¥','ð¦'=>'ð¦','ð§'=>'ð§','ð¨'=>'ð¨','ð©'=>'ð©','ðª'=>'ðª','ð«'=>'ð«','ð¬'=>'ð¬','ð'=>'ð','ð®'=>'ð®','ð¯'=>'ð¯','ð°'=>'ð°','ð±'=>'ð±','ð²'=>'ð²','ð³'=>'ð³','ð´'=>'ð´','ðµ'=>'ðµ','ð¶'=>'ð¶','ð·'=>'ð·','ð¸'=>'ð¸','ð¹'=>'ð¹','ðº'=>'ðº','ð»'=>'ð»','ð¼'=>'ð¼','ð½'=>'ð½','ð¾'=>'ð¾','ð¿'=>'ð¿','ð‘€'=>'ð‘€','ð‘'=>'ð‘','ð‘‚'=>'ð‘‚','ð‘ƒ'=>'ð‘ƒ','ð‘„'=>'ð‘„','ð‘…'=>'ð‘…','ð‘†'=>'ð‘†','ð‘‡'=>'ð‘‡','ð‘ˆ'=>'ð‘ˆ','ð‘‰'=>'ð‘‰','ð‘Š'=>'ð‘Š','ð‘‹'=>'ð‘‹','ð‘Œ'=>'ð‘Œ','ð‘'=>'ð‘','ð‘Ž'=>'ð‘Ž','ð‘'=>'ð‘','ð‘'=>'ð‘','ð‘‘'=>'ð‘‘','ð‘’'=>'ð‘’','ð‘“'=>'ð‘“','ð‘”'=>'ð‘”','ð‘–'=>'ð‘–','ð‘—'=>'ð‘—','ð‘˜'=>'ð‘˜','ð‘™'=>'ð‘™','ð‘š'=>'ð‘š','ð‘›'=>'ð‘›','ð‘œ'=>'ð‘œ','ð‘'=>'ð‘','ð‘ž'=>'ð‘ž','ð‘Ÿ'=>'ð‘Ÿ','ð‘ '=>'ð‘ ','ð‘¡'=>'ð‘¡','ð‘¢'=>'ð‘¢','ð‘£'=>'ð‘£','ð‘¤'=>'ð‘¤','ð‘¥'=>'ð‘¥','ð‘¦'=>'ð‘¦','ð‘§'=>'ð‘§','ð‘¨'=>'ð‘¨','ð‘©'=>'ð‘©','ð‘ª'=>'ð‘ª','ð‘«'=>'ð‘«','ð‘¬'=>'ð‘¬','ð‘'=>'ð‘','ð‘®'=>'ð‘®','ð‘¯'=>'ð‘¯','ð‘°'=>'ð‘°','ð‘±'=>'ð‘±','ð‘²'=>'ð‘²','ð‘³'=>'ð‘³','ð‘´'=>'ð‘´','ð‘µ'=>'ð‘µ','ð‘¶'=>'ð‘¶','ð‘·'=>'ð‘·','ð‘¸'=>'ð‘¸','ð‘¹'=>'ð‘¹','ð‘º'=>'ð‘º','ð‘»'=>'ð‘»','ð‘¼'=>'ð‘¼','ð‘½'=>'ð‘½','ð‘¾'=>'ð‘¾','ð‘¿'=>'ð‘¿','ð’€'=>'ð’€','ð’'=>'ð’','ð’‚'=>'ð’‚','ð’ƒ'=>'ð’ƒ','ð’„'=>'ð’„','ð’…'=>'ð’…','ð’†'=>'ð’†','ð’‡'=>'ð’‡','ð’ˆ'=>'ð’ˆ','ð’‰'=>'ð’‰','ð’Š'=>'ð’Š','ð’‹'=>'ð’‹','ð’Œ'=>'ð’Œ','ð’'=>'ð’','ð’Ž'=>'ð’Ž','ð’'=>'ð’','ð’'=>'ð’','ð’‘'=>'ð’‘','ð’’'=>'ð’’','ð’“'=>'ð’“','ð’”'=>'ð’”','ð’•'=>'ð’•','ð’–'=>'ð’–','ð’—'=>'ð’—','ð’˜'=>'ð’˜','ð’™'=>'ð’™','ð’š'=>'ð’š','ð’›'=>'ð’›','ð’œ'=>'ð’œ','ð’ž'=>'ð’ž','ð’Ÿ'=>'ð’Ÿ','ð’¢'=>'ð’¢','ð’¥'=>'ð’¥','ð’¦'=>'ð’¦','ð’©'=>'ð’©','ð’ª'=>'ð’ª','ð’«'=>'ð’«','ð’¬'=>'ð’¬','ð’®'=>'ð’®','ð’¯'=>'ð’¯','ð’°'=>'ð’°','ð’±'=>'ð’±','ð’²'=>'ð’²','ð’³'=>'ð’³','ð’´'=>'ð’´','ð’µ'=>'ð’µ','ð’¶'=>'ð’¶','ð’·'=>'ð’·','ð’¸'=>'ð’¸','ð’¹'=>'ð’¹','ð’»'=>'ð’»','ð’½'=>'ð’½','ð’¾'=>'ð’¾','ð’¿'=>'ð’¿','ð“€'=>'ð“€','ð“'=>'ð“','ð“‚'=>'ð“‚','ð“ƒ'=>'ð“ƒ','ð“…'=>'ð“…','ð“†'=>'ð“†','ð“‡'=>'ð“‡','ð“ˆ'=>'ð“ˆ','ð“‰'=>'ð“‰','ð“Š'=>'ð“Š','ð“‹'=>'ð“‹','ð“Œ'=>'ð“Œ','ð“'=>'ð“','ð“Ž'=>'ð“Ž','ð“'=>'ð“','ð“'=>'ð“','ð“‘'=>'ð“‘','ð“’'=>'ð“’','ð““'=>'ð““','ð“”'=>'ð“”','ð“•'=>'ð“•','ð“–'=>'ð“–','ð“—'=>'ð“—','ð“˜'=>'ð“˜','ð“™'=>'ð“™','ð“š'=>'ð“š','ð“›'=>'ð“›','ð“œ'=>'ð“œ','ð“'=>'ð“','ð“ž'=>'ð“ž','ð“Ÿ'=>'ð“Ÿ','ð“ '=>'ð“ ','ð“¡'=>'ð“¡','ð“¢'=>'ð“¢','ð“£'=>'ð“£','ð“¤'=>'ð“¤','ð“¥'=>'ð“¥','ð“¦'=>'ð“¦','ð“§'=>'ð“§','ð“¨'=>'ð“¨','ð“©'=>'ð“©','ð“ª'=>'ð“ª','ð“«'=>'ð“«','ð“¬'=>'ð“¬','ð“'=>'ð“','ð“®'=>'ð“®','ð“¯'=>'ð“¯','ð“°'=>'ð“°','ð“±'=>'ð“±','ð“²'=>'ð“²','ð“³'=>'ð“³','ð“´'=>'ð“´','ð“µ'=>'ð“µ','ð“¶'=>'ð“¶','ð“·'=>'ð“·','ð“¸'=>'ð“¸','ð“¹'=>'ð“¹','ð“º'=>'ð“º','ð“»'=>'ð“»','ð“¼'=>'ð“¼','ð“½'=>'ð“½','ð“¾'=>'ð“¾','ð“¿'=>'ð“¿','ð”€'=>'ð”€','ð”'=>'ð”','ð”‚'=>'ð”‚','ð”ƒ'=>'ð”ƒ','ð”„'=>'ð”„','ð”…'=>'ð”…','ð”‡'=>'ð”‡','ð”ˆ'=>'ð”ˆ','ð”‰'=>'ð”‰','ð”Š'=>'ð”Š','ð”'=>'ð”','ð”Ž'=>'ð”Ž','ð”'=>'ð”','ð”'=>'ð”','ð”‘'=>'ð”‘','ð”’'=>'ð”’','ð”“'=>'ð”“','ð””'=>'ð””','ð”–'=>'ð”–','ð”—'=>'ð”—','ð”˜'=>'ð”˜','ð”™'=>'ð”™','ð”š'=>'ð”š','ð”›'=>'ð”›','ð”œ'=>'ð”œ','ð”ž'=>'ð”ž','ð”Ÿ'=>'ð”Ÿ','ð” '=>'ð” ','ð”¡'=>'ð”¡','ð”¢'=>'ð”¢','ð”£'=>'ð”£','ð”¤'=>'ð”¤','ð”¥'=>'ð”¥','ð”¦'=>'ð”¦','ð”§'=>'ð”§','ð”¨'=>'ð”¨','ð”©'=>'ð”©','ð”ª'=>'ð”ª','ð”«'=>'ð”«','ð”¬'=>'ð”¬','ð”'=>'ð”','ð”®'=>'ð”®','ð”¯'=>'ð”¯','ð”°'=>'ð”°','ð”±'=>'ð”±','ð”²'=>'ð”²','ð”³'=>'ð”³','ð”´'=>'ð”´','ð”µ'=>'ð”µ','ð”¶'=>'ð”¶','ð”·'=>'ð”·','ð”¸'=>'ð”¸','ð”¹'=>'ð”¹','ð”»'=>'ð”»','ð”¼'=>'ð”¼','ð”½'=>'ð”½','ð”¾'=>'ð”¾','ð•€'=>'ð•€','ð•'=>'ð•','ð•‚'=>'ð•‚','ð•ƒ'=>'ð•ƒ','ð•„'=>'ð•„','ð•†'=>'ð•†','ð•Š'=>'ð•Š','ð•‹'=>'ð•‹','ð•Œ'=>'ð•Œ','ð•'=>'ð•','ð•Ž'=>'ð•Ž','ð•'=>'ð•','ð•'=>'ð•','ð•’'=>'ð•’','ð•“'=>'ð•“','ð•”'=>'ð•”','ð••'=>'ð••','ð•–'=>'ð•–','ð•—'=>'ð•—','ð•˜'=>'ð•˜','ð•™'=>'ð•™','ð•š'=>'ð•š','ð•›'=>'ð•›','ð•œ'=>'ð•œ','ð•'=>'ð•','ð•ž'=>'ð•ž','ð•Ÿ'=>'ð•Ÿ','ð• '=>'ð• ','ð•¡'=>'ð•¡','ð•¢'=>'ð•¢','ð•£'=>'ð•£','ð•¤'=>'ð•¤','ð•¥'=>'ð•¥','ð•¦'=>'ð•¦','ð•§'=>'ð•§','ð•¨'=>'ð•¨','ð•©'=>'ð•©','ð•ª'=>'ð•ª','ð•«'=>'ð•«','ð•¬'=>'ð•¬','ð•'=>'ð•','ð•®'=>'ð•®','ð•¯'=>'ð•¯','ð•°'=>'ð•°','ð•±'=>'ð•±','ð•²'=>'ð•²','ð•³'=>'ð•³','ð•´'=>'ð•´','ð•µ'=>'ð•µ','ð•¶'=>'ð•¶','ð•·'=>'ð•·','ð•¸'=>'ð•¸','ð•¹'=>'ð•¹','ð•º'=>'ð•º','ð•»'=>'ð•»','ð•¼'=>'ð•¼','ð•½'=>'ð•½','ð•¾'=>'ð•¾','ð•¿'=>'ð•¿','ð–€'=>'ð–€','ð–'=>'ð–','ð–‚'=>'ð–‚','ð–ƒ'=>'ð–ƒ','ð–„'=>'ð–„','ð–…'=>'ð–…','ð–†'=>'ð–†','ð–‡'=>'ð–‡','ð–ˆ'=>'ð–ˆ','ð–‰'=>'ð–‰','ð–Š'=>'ð–Š','ð–‹'=>'ð–‹','ð–Œ'=>'ð–Œ','ð–'=>'ð–','ð–Ž'=>'ð–Ž','ð–'=>'ð–','ð–'=>'ð–','ð–‘'=>'ð–‘','ð–’'=>'ð–’','ð–“'=>'ð–“','ð–”'=>'ð–”','ð–•'=>'ð–•','ð––'=>'ð––','ð–—'=>'ð–—','ð–˜'=>'ð–˜','ð–™'=>'ð–™','ð–š'=>'ð–š','ð–›'=>'ð–›','ð–œ'=>'ð–œ','ð–'=>'ð–','ð–ž'=>'ð–ž','ð–Ÿ'=>'ð–Ÿ','ð– '=>'ð– ','ð–¡'=>'ð–¡','ð–¢'=>'ð–¢','ð–£'=>'ð–£','ð–¤'=>'ð–¤','ð–¥'=>'ð–¥','ð–¦'=>'ð–¦','ð–§'=>'ð–§','ð–¨'=>'ð–¨','ð–©'=>'ð–©','ð–ª'=>'ð–ª','ð–«'=>'ð–«','ð–¬'=>'ð–¬','ð–'=>'ð–','ð–®'=>'ð–®','ð–¯'=>'ð–¯','ð–°'=>'ð–°','ð–±'=>'ð–±','ð–²'=>'ð–²','ð–³'=>'ð–³','ð–´'=>'ð–´','ð–µ'=>'ð–µ','ð–¶'=>'ð–¶','ð–·'=>'ð–·','ð–¸'=>'ð–¸','ð–¹'=>'ð–¹','ð–º'=>'ð–º','ð–»'=>'ð–»','ð–¼'=>'ð–¼','ð–½'=>'ð–½','ð–¾'=>'ð–¾','ð–¿'=>'ð–¿','ð—€'=>'ð—€','ð—'=>'ð—','ð—‚'=>'ð—‚','ð—ƒ'=>'ð—ƒ','ð—„'=>'ð—„','ð—…'=>'ð—…','ð—†'=>'ð—†','ð—‡'=>'ð—‡','ð—ˆ'=>'ð—ˆ','ð—‰'=>'ð—‰','ð—Š'=>'ð—Š','ð—‹'=>'ð—‹','ð—Œ'=>'ð—Œ','ð—'=>'ð—','ð—Ž'=>'ð—Ž','ð—'=>'ð—','ð—'=>'ð—','ð—‘'=>'ð—‘','ð—’'=>'ð—’','ð—“'=>'ð—“','ð—”'=>'ð—”','ð—•'=>'ð—•','ð—–'=>'ð—–','ð——'=>'ð——','ð—˜'=>'ð—˜','ð—™'=>'ð—™','ð—š'=>'ð—š','ð—›'=>'ð—›','ð—œ'=>'ð—œ','ð—'=>'ð—','ð—ž'=>'ð—ž','ð—Ÿ'=>'ð—Ÿ','ð— '=>'ð— ','ð—¡'=>'ð—¡','ð—¢'=>'ð—¢','ð—£'=>'ð—£','ð—¤'=>'ð—¤','ð—¥'=>'ð—¥','ð—¦'=>'ð—¦','ð—§'=>'ð—§','ð—¨'=>'ð—¨','ð—©'=>'ð—©','ð—ª'=>'ð—ª','ð—«'=>'ð—«','ð—¬'=>'ð—¬','ð—'=>'ð—','ð—®'=>'ð—®','ð—¯'=>'ð—¯','ð—°'=>'ð—°','ð—±'=>'ð—±','ð—²'=>'ð—²','ð—³'=>'ð—³','ð—´'=>'ð—´','ð—µ'=>'ð—µ','ð—¶'=>'ð—¶','ð—·'=>'ð—·','ð—¸'=>'ð—¸','ð—¹'=>'ð—¹','ð—º'=>'ð—º','ð—»'=>'ð—»','ð—¼'=>'ð—¼','ð—½'=>'ð—½','ð—¾'=>'ð—¾','ð—¿'=>'ð—¿','ð˜€'=>'ð˜€','ð˜'=>'ð˜','ð˜‚'=>'ð˜‚','ð˜ƒ'=>'ð˜ƒ','ð˜„'=>'ð˜„','ð˜…'=>'ð˜…','ð˜†'=>'ð˜†','ð˜‡'=>'ð˜‡','ð˜ˆ'=>'ð˜ˆ','ð˜‰'=>'ð˜‰','ð˜Š'=>'ð˜Š','ð˜‹'=>'ð˜‹','ð˜Œ'=>'ð˜Œ','ð˜'=>'ð˜','ð˜Ž'=>'ð˜Ž','ð˜'=>'ð˜','ð˜'=>'ð˜','ð˜‘'=>'ð˜‘','ð˜’'=>'ð˜’','ð˜“'=>'ð˜“','ð˜”'=>'ð˜”','ð˜•'=>'ð˜•','ð˜–'=>'ð˜–','ð˜—'=>'ð˜—','ð˜˜'=>'ð˜˜','ð˜™'=>'ð˜™','ð˜š'=>'ð˜š','ð˜›'=>'ð˜›','ð˜œ'=>'ð˜œ','ð˜'=>'ð˜','ð˜ž'=>'ð˜ž','ð˜Ÿ'=>'ð˜Ÿ','ð˜ '=>'ð˜ ','ð˜¡'=>'ð˜¡','ð˜¢'=>'ð˜¢','ð˜£'=>'ð˜£','ð˜¤'=>'ð˜¤','ð˜¥'=>'ð˜¥','ð˜¦'=>'ð˜¦','ð˜§'=>'ð˜§','ð˜¨'=>'ð˜¨','ð˜©'=>'ð˜©','ð˜ª'=>'ð˜ª','ð˜«'=>'ð˜«','ð˜¬'=>'ð˜¬','ð˜'=>'ð˜','ð˜®'=>'ð˜®','ð˜¯'=>'ð˜¯','ð˜°'=>'ð˜°','ð˜±'=>'ð˜±','ð˜²'=>'ð˜²','ð˜³'=>'ð˜³','ð˜´'=>'ð˜´','ð˜µ'=>'ð˜µ','ð˜¶'=>'ð˜¶','ð˜·'=>'ð˜·','ð˜¸'=>'ð˜¸','ð˜¹'=>'ð˜¹','ð˜º'=>'ð˜º','ð˜»'=>'ð˜»','ð˜¼'=>'ð˜¼','ð˜½'=>'ð˜½','ð˜¾'=>'ð˜¾','ð˜¿'=>'ð˜¿','ð™€'=>'ð™€','ð™'=>'ð™','ð™‚'=>'ð™‚','ð™ƒ'=>'ð™ƒ','ð™„'=>'ð™„','ð™…'=>'ð™…','ð™†'=>'ð™†','ð™‡'=>'ð™‡','ð™ˆ'=>'ð™ˆ','ð™‰'=>'ð™‰','ð™Š'=>'ð™Š','ð™‹'=>'ð™‹','ð™Œ'=>'ð™Œ','ð™'=>'ð™','ð™Ž'=>'ð™Ž','ð™'=>'ð™','ð™'=>'ð™','ð™‘'=>'ð™‘','ð™’'=>'ð™’','ð™“'=>'ð™“','ð™”'=>'ð™”','ð™•'=>'ð™•','ð™–'=>'ð™–','ð™—'=>'ð™—','ð™˜'=>'ð™˜','ð™™'=>'ð™™','ð™š'=>'ð™š','ð™›'=>'ð™›','ð™œ'=>'ð™œ','ð™'=>'ð™','ð™ž'=>'ð™ž','ð™Ÿ'=>'ð™Ÿ','ð™ '=>'ð™ ','ð™¡'=>'ð™¡','ð™¢'=>'ð™¢','ð™£'=>'ð™£','ð™¤'=>'ð™¤','ð™¥'=>'ð™¥','ð™¦'=>'ð™¦','ð™§'=>'ð™§','ð™¨'=>'ð™¨','ð™©'=>'ð™©','ð™ª'=>'ð™ª','ð™«'=>'ð™«','ð™¬'=>'ð™¬','ð™'=>'ð™','ð™®'=>'ð™®','ð™¯'=>'ð™¯','ð™°'=>'ð™°','ð™±'=>'ð™±','ð™²'=>'ð™²','ð™³'=>'ð™³','ð™´'=>'ð™´','ð™µ'=>'ð™µ','ð™¶'=>'ð™¶','ð™·'=>'ð™·','ð™¸'=>'ð™¸','ð™¹'=>'ð™¹','ð™º'=>'ð™º','ð™»'=>'ð™»','ð™¼'=>'ð™¼','ð™½'=>'ð™½','ð™¾'=>'ð™¾','ð™¿'=>'ð™¿','ðš€'=>'ðš€','ðš'=>'ðš','ðš‚'=>'ðš‚','ðšƒ'=>'ðšƒ','ðš„'=>'ðš„','ðš…'=>'ðš…','ðš†'=>'ðš†','ðš‡'=>'ðš‡','ðšˆ'=>'ðšˆ','ðš‰'=>'ðš‰','ðšŠ'=>'ðšŠ','ðš‹'=>'ðš‹','ðšŒ'=>'ðšŒ','ðš'=>'ðš','ðšŽ'=>'ðšŽ','ðš'=>'ðš','ðš'=>'ðš','ðš‘'=>'ðš‘','ðš’'=>'ðš’','ðš“'=>'ðš“','ðš”'=>'ðš”','ðš•'=>'ðš•','ðš–'=>'ðš–','ðš—'=>'ðš—','ðš˜'=>'ðš˜','ðš™'=>'ðš™','ðšš'=>'ðšš','ðš›'=>'ðš›','ðšœ'=>'ðšœ','ðš'=>'ðš','ðšž'=>'ðšž','ðšŸ'=>'ðšŸ','ðš '=>'ðš ','ðš¡'=>'ðš¡','ðš¢'=>'ðš¢','ðš£'=>'ðš£','ðš¤'=>'ðš¤','ðš¥'=>'ðš¥','ðš¨'=>'ðš¨','ðš©'=>'ðš©','ðšª'=>'ðšª','ðš«'=>'ðš«','ðš¬'=>'ðš¬','ðš'=>'ðš','ðš®'=>'ðš®','ðš¯'=>'ðš¯','ðš°'=>'ðš°','ðš±'=>'ðš±','ðš²'=>'ðš²','ðš³'=>'ðš³','ðš´'=>'ðš´','ðšµ'=>'ðšµ','ðš¶'=>'ðš¶','ðš·'=>'ðš·','ðš¸'=>'ðš¸','ðš¹'=>'ðš¹','ðšº'=>'ðšº','ðš»'=>'ðš»','ðš¼'=>'ðš¼','ðš½'=>'ðš½','ðš¾'=>'ðš¾','ðš¿'=>'ðš¿','ð›€'=>'ð›€','ð›‚'=>'ð›‚','ð›ƒ'=>'ð›ƒ','ð›„'=>'ð›„','ð›…'=>'ð›…','ð›†'=>'ð›†','ð›‡'=>'ð›‡','ð›ˆ'=>'ð›ˆ','ð›‰'=>'ð›‰','ð›Š'=>'ð›Š','ð›‹'=>'ð›‹','ð›Œ'=>'ð›Œ','ð›'=>'ð›','ð›Ž'=>'ð›Ž','ð›'=>'ð›','ð›'=>'ð›','ð›‘'=>'ð›‘','ð›’'=>'ð›’','ð›“'=>'ð›“','ð›”'=>'ð›”','ð›•'=>'ð›•','ð›–'=>'ð›–','ð›—'=>'ð›—','ð›˜'=>'ð›˜','ð›™'=>'ð›™','ð›š'=>'ð›š','ð›œ'=>'ð›œ','ð›'=>'ð›','ð›ž'=>'ð›ž','ð›Ÿ'=>'ð›Ÿ','ð› '=>'ð› ','ð›¡'=>'ð›¡','ð›¢'=>'ð›¢','ð›£'=>'ð›£','ð›¤'=>'ð›¤','ð›¥'=>'ð›¥','ð›¦'=>'ð›¦','ð›§'=>'ð›§','ð›¨'=>'ð›¨','ð›©'=>'ð›©','ð›ª'=>'ð›ª','ð›«'=>'ð›«','ð›¬'=>'ð›¬','ð›'=>'ð›','ð›®'=>'ð›®','ð›¯'=>'ð›¯','ð›°'=>'ð›°','ð›±'=>'ð›±','ð›²'=>'ð›²','ð›³'=>'ð›³','ð›´'=>'ð›´','ð›µ'=>'ð›µ','ð›¶'=>'ð›¶','ð›·'=>'ð›·','ð›¸'=>'ð›¸','ð›¹'=>'ð›¹','ð›º'=>'ð›º','ð›¼'=>'ð›¼','ð›½'=>'ð›½','ð›¾'=>'ð›¾','ð›¿'=>'ð›¿','ðœ€'=>'ðœ€','ðœ'=>'ðœ','ðœ‚'=>'ðœ‚','ðœƒ'=>'ðœƒ','ðœ„'=>'ðœ„','ðœ…'=>'ðœ…','ðœ†'=>'ðœ†','ðœ‡'=>'ðœ‡','ðœˆ'=>'ðœˆ','ðœ‰'=>'ðœ‰','ðœŠ'=>'ðœŠ','ðœ‹'=>'ðœ‹','ðœŒ'=>'ðœŒ','ðœ'=>'ðœ','ðœŽ'=>'ðœŽ','ðœ'=>'ðœ','ðœ'=>'ðœ','ðœ‘'=>'ðœ‘','ðœ’'=>'ðœ’','ðœ“'=>'ðœ“','ðœ”'=>'ðœ”','ðœ–'=>'ðœ–','ðœ—'=>'ðœ—','ðœ˜'=>'ðœ˜','ðœ™'=>'ðœ™','ðœš'=>'ðœš','ðœ›'=>'ðœ›','ðœœ'=>'ðœœ','ðœ'=>'ðœ','ðœž'=>'ðœž','ðœŸ'=>'ðœŸ','ðœ '=>'ðœ ','ðœ¡'=>'ðœ¡','ðœ¢'=>'ðœ¢','ðœ£'=>'ðœ£','ðœ¤'=>'ðœ¤','ðœ¥'=>'ðœ¥','ðœ¦'=>'ðœ¦','ðœ§'=>'ðœ§','ðœ¨'=>'ðœ¨','ðœ©'=>'ðœ©','ðœª'=>'ðœª','ðœ«'=>'ðœ«','ðœ¬'=>'ðœ¬','ðœ'=>'ðœ','ðœ®'=>'ðœ®','ðœ¯'=>'ðœ¯','ðœ°'=>'ðœ°','ðœ±'=>'ðœ±','ðœ²'=>'ðœ²','ðœ³'=>'ðœ³','ðœ´'=>'ðœ´','ðœ¶'=>'ðœ¶','ðœ·'=>'ðœ·','ðœ¸'=>'ðœ¸','ðœ¹'=>'ðœ¹','ðœº'=>'ðœº','ðœ»'=>'ðœ»','ðœ¼'=>'ðœ¼','ðœ½'=>'ðœ½','ðœ¾'=>'ðœ¾','ðœ¿'=>'ðœ¿','ð€'=>'ð€','ð'=>'ð','ð‚'=>'ð‚','ðƒ'=>'ðƒ','ð„'=>'ð„','ð…'=>'ð…','ð†'=>'ð†','ð‡'=>'ð‡','ðˆ'=>'ðˆ','ð‰'=>'ð‰','ðŠ'=>'ðŠ','ð‹'=>'ð‹','ðŒ'=>'ðŒ','ð'=>'ð','ðŽ'=>'ðŽ','ð'=>'ð','ð‘'=>'ð‘','ð’'=>'ð’','ð“'=>'ð“','ð”'=>'ð”','ð•'=>'ð•','ð–'=>'ð–','ð—'=>'ð—','ð˜'=>'ð˜','ð™'=>'ð™','ðš'=>'ðš','ð›'=>'ð›','ðœ'=>'ðœ','ð'=>'ð','ðž'=>'ðž','ðŸ'=>'ðŸ','ð '=>'ð ','ð¡'=>'ð¡','ð¢'=>'ð¢','ð£'=>'ð£','ð¤'=>'ð¤','ð¥'=>'ð¥','ð¦'=>'ð¦','ð§'=>'ð§','ð¨'=>'ð¨','ð©'=>'ð©','ðª'=>'ðª','ð«'=>'ð«','ð¬'=>'ð¬','ð'=>'ð','ð®'=>'ð®','ð°'=>'ð°','ð±'=>'ð±','ð²'=>'ð²','ð³'=>'ð³','ð´'=>'ð´','ðµ'=>'ðµ','ð¶'=>'ð¶','ð·'=>'ð·','ð¸'=>'ð¸','ð¹'=>'ð¹','ðº'=>'ðº','ð»'=>'ð»','ð¼'=>'ð¼','ð½'=>'ð½','ð¾'=>'ð¾','ð¿'=>'ð¿','ðž€'=>'ðž€','ðž'=>'ðž','ðž‚'=>'ðž‚','ðžƒ'=>'ðžƒ','ðž„'=>'ðž„','ðž…'=>'ðž…','ðž†'=>'ðž†','ðž‡'=>'ðž‡','ðžˆ'=>'ðžˆ','ðžŠ'=>'ðžŠ','ðž‹'=>'ðž‹','ðžŒ'=>'ðžŒ','ðž'=>'ðž','ðžŽ'=>'ðžŽ','ðž'=>'ðž','ðž'=>'ðž','ðž‘'=>'ðž‘','ðž’'=>'ðž’','ðž“'=>'ðž“','ðž”'=>'ðž”','ðž•'=>'ðž•','ðž–'=>'ðž–','ðž—'=>'ðž—','ðž˜'=>'ðž˜','ðž™'=>'ðž™','ðžš'=>'ðžš','ðž›'=>'ðž›','ðžœ'=>'ðžœ','ðž'=>'ðž','ðžž'=>'ðžž','ðžŸ'=>'ðžŸ','ðž '=>'ðž ','ðž¡'=>'ðž¡','ðž¢'=>'ðž¢','ðž£'=>'ðž£','ðž¤'=>'ðž¤','ðž¥'=>'ðž¥','ðž¦'=>'ðž¦','ðž§'=>'ðž§','ðž¨'=>'ðž¨','ðžª'=>'ðžª','ðž«'=>'ðž«','ðž¬'=>'ðž¬','ðž'=>'ðž','ðž®'=>'ðž®','ðž¯'=>'ðž¯','ðž°'=>'ðž°','ðž±'=>'ðž±','ðž²'=>'ðž²','ðž³'=>'ðž³','ðž´'=>'ðž´','ðžµ'=>'ðžµ','ðž¶'=>'ðž¶','ðž·'=>'ðž·','ðž¸'=>'ðž¸','ðž¹'=>'ðž¹','ðžº'=>'ðžº','ðž»'=>'ðž»','ðž¼'=>'ðž¼','ðž½'=>'ðž½','ðž¾'=>'ðž¾','ðž¿'=>'ðž¿','ðŸ€'=>'ðŸ€','ðŸ'=>'ðŸ','ðŸ‚'=>'ðŸ‚','ðŸ„'=>'ðŸ„','ðŸ…'=>'ðŸ…','ðŸ†'=>'ðŸ†','ðŸ‡'=>'ðŸ‡','ðŸˆ'=>'ðŸˆ','ðŸ‰'=>'ðŸ‰','ðŸŠ'=>'ðŸŠ','ðŸ‹'=>'ðŸ‹','ðŸŽ'=>'0','ðŸ'=>'1','ðŸ'=>'2','ðŸ‘'=>'3','ðŸ’'=>'4','ðŸ“'=>'5','ðŸ”'=>'6','ðŸ•'=>'7','ðŸ–'=>'8','ðŸ—'=>'9','ðŸ˜'=>'0','ðŸ™'=>'1','ðŸš'=>'2','ðŸ›'=>'3','ðŸœ'=>'4','ðŸ'=>'5','ðŸž'=>'6','ðŸŸ'=>'7','ðŸ '=>'8','ðŸ¡'=>'9','ðŸ¢'=>'0','ðŸ£'=>'1','ðŸ¤'=>'2','ðŸ¥'=>'3','ðŸ¦'=>'4','ðŸ§'=>'5','ðŸ¨'=>'6','ðŸ©'=>'7','ðŸª'=>'8','ðŸ«'=>'9','ðŸ¬'=>'0','ðŸ'=>'1','ðŸ®'=>'2','ðŸ¯'=>'3','ðŸ°'=>'4','ðŸ±'=>'5','ðŸ²'=>'6','ðŸ³'=>'7','ðŸ´'=>'8','ðŸµ'=>'9','ðŸ¶'=>'0','ðŸ·'=>'1','ðŸ¸'=>'2','ðŸ¹'=>'3','ðŸº'=>'4','ðŸ»'=>'5','ðŸ¼'=>'6','ðŸ½'=>'7','ðŸ¾'=>'8','ðŸ¿'=>'9');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_6.php b/phpBB/includes/utf/data/search_indexer_6.php deleted file mode 100644 index f6d2ac0665..0000000000 --- a/phpBB/includes/utf/data/search_indexer_6.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('々'=>'々','〆'=>'〆','〇'=>'0','〡'=>'1','〢'=>'2','〣'=>'3','〤'=>'4','〥'=>'5','〦'=>'6','〧'=>'7','〨'=>'8','〩'=>'9','〪'=>'〪','〫'=>'〫','〬'=>'〬','ã€'=>'ã€','〮'=>'〮','〯'=>'〯','〱'=>'〱','〲'=>'〲','〳'=>'〳','〴'=>'〴','〵'=>'〵','〸'=>'10','〹'=>'20','〺'=>'30','〻'=>'〻','〼'=>'〼','ã'=>'ã','ã‚'=>'ã‚','ãƒ'=>'ãƒ','ã„'=>'ã„','ã…'=>'ã…','ã†'=>'ã†','ã‡'=>'ã‡','ãˆ'=>'ãˆ','ã‰'=>'ã‰','ãŠ'=>'ãŠ','ã‹'=>'ã‹','ãŒ'=>'ãŒ','ã'=>'ã','ãŽ'=>'ãŽ','ã'=>'ã','ã'=>'ã','ã‘'=>'ã‘','ã’'=>'ã’','ã“'=>'ã“','ã”'=>'ã”','ã•'=>'ã•','ã–'=>'ã–','ã—'=>'ã—','ã˜'=>'ã˜','ã™'=>'ã™','ãš'=>'ãš','ã›'=>'ã›','ãœ'=>'ãœ','ã'=>'ã','ãž'=>'ãž','ãŸ'=>'ãŸ','ã '=>'ã ','ã¡'=>'ã¡','ã¢'=>'ã¢','ã£'=>'ã£','ã¤'=>'ã¤','ã¥'=>'ã¥','ã¦'=>'ã¦','ã§'=>'ã§','ã¨'=>'ã¨','ã©'=>'ã©','ãª'=>'ãª','ã«'=>'ã«','ã¬'=>'ã¬','ã'=>'ã','ã®'=>'ã®','ã¯'=>'ã¯','ã°'=>'ã°','ã±'=>'ã±','ã²'=>'ã²','ã³'=>'ã³','ã´'=>'ã´','ãµ'=>'ãµ','ã¶'=>'ã¶','ã·'=>'ã·','ã¸'=>'ã¸','ã¹'=>'ã¹','ãº'=>'ãº','ã»'=>'ã»','ã¼'=>'ã¼','ã½'=>'ã½','ã¾'=>'ã¾','ã¿'=>'ã¿','ã‚€'=>'ã‚€','ã‚'=>'ã‚','ã‚‚'=>'ã‚‚','ゃ'=>'ゃ','ã‚„'=>'ã‚„','ã‚…'=>'ã‚…','ゆ'=>'ゆ','ょ'=>'ょ','よ'=>'よ','ら'=>'ら','り'=>'り','ã‚‹'=>'ã‚‹','れ'=>'れ','ã‚'=>'ã‚','ゎ'=>'ゎ','ã‚'=>'ã‚','ã‚'=>'ã‚','ã‚‘'=>'ã‚‘','ã‚’'=>'ã‚’','ã‚“'=>'ã‚“','ã‚”'=>'ã‚”','ã‚•'=>'ã‚•','ã‚–'=>'ã‚–','ã‚™'=>'ã‚™','゚'=>'゚','ã‚'=>'ã‚','ゞ'=>'ゞ','ゟ'=>'ゟ','ã‚¡'=>'ã‚¡','ã‚¢'=>'ã‚¢','ã‚£'=>'ã‚£','イ'=>'イ','ã‚¥'=>'ã‚¥','ウ'=>'ウ','ã‚§'=>'ã‚§','エ'=>'エ','ã‚©'=>'ã‚©','オ'=>'オ','ã‚«'=>'ã‚«','ガ'=>'ガ','ã‚'=>'ã‚','ã‚®'=>'ã‚®','ク'=>'ク','ã‚°'=>'ã‚°','ケ'=>'ケ','ゲ'=>'ゲ','コ'=>'コ','ã‚´'=>'ã‚´','サ'=>'サ','ã‚¶'=>'ã‚¶','ã‚·'=>'ã‚·','ジ'=>'ジ','ス'=>'ス','ズ'=>'ズ','ã‚»'=>'ã‚»','ゼ'=>'ゼ','ソ'=>'ソ','ゾ'=>'ゾ','ã‚¿'=>'ã‚¿','ダ'=>'ダ','ãƒ'=>'ãƒ','ヂ'=>'ヂ','ッ'=>'ッ','ツ'=>'ツ','ヅ'=>'ヅ','テ'=>'テ','デ'=>'デ','ト'=>'ト','ド'=>'ド','ナ'=>'ナ','ニ'=>'ニ','ヌ'=>'ヌ','ãƒ'=>'ãƒ','ノ'=>'ノ','ãƒ'=>'ãƒ','ãƒ'=>'ãƒ','パ'=>'パ','ヒ'=>'ヒ','ビ'=>'ビ','ピ'=>'ピ','フ'=>'フ','ブ'=>'ブ','プ'=>'プ','ヘ'=>'ヘ','ベ'=>'ベ','ペ'=>'ペ','ホ'=>'ホ','ボ'=>'ボ','ãƒ'=>'ãƒ','マ'=>'マ','ミ'=>'ミ','ム'=>'ム','メ'=>'メ','モ'=>'モ','ャ'=>'ャ','ヤ'=>'ヤ','ュ'=>'ュ','ユ'=>'ユ','ョ'=>'ョ','ヨ'=>'ヨ','ラ'=>'ラ','リ'=>'リ','ル'=>'ル','レ'=>'レ','ãƒ'=>'ãƒ','ヮ'=>'ヮ','ワ'=>'ワ','ヰ'=>'ヰ','ヱ'=>'ヱ','ヲ'=>'ヲ','ン'=>'ン','ヴ'=>'ヴ','ヵ'=>'ヵ','ヶ'=>'ヶ','ヷ'=>'ヷ','ヸ'=>'ヸ','ヹ'=>'ヹ','ヺ'=>'ヺ','ー'=>'ー','ヽ'=>'ヽ','ヾ'=>'ヾ','ヿ'=>'ヿ','ã„…'=>'ã„…','ㄆ'=>'ㄆ','ㄇ'=>'ㄇ','ㄈ'=>'ㄈ','ㄉ'=>'ㄉ','ㄊ'=>'ㄊ','ã„‹'=>'ã„‹','ㄌ'=>'ㄌ','ã„'=>'ã„','ㄎ'=>'ㄎ','ã„'=>'ã„','ã„'=>'ã„','ã„‘'=>'ã„‘','ã„’'=>'ã„’','ã„“'=>'ã„“','ã„”'=>'ã„”','ã„•'=>'ã„•','ã„–'=>'ã„–','ã„—'=>'ã„—','ㄘ'=>'ㄘ','ã„™'=>'ã„™','ㄚ'=>'ㄚ','ã„›'=>'ã„›','ㄜ'=>'ㄜ','ã„'=>'ã„','ㄞ'=>'ㄞ','ㄟ'=>'ㄟ','ã„ '=>'ã„ ','ã„¡'=>'ã„¡','ã„¢'=>'ã„¢','ã„£'=>'ã„£','ㄤ'=>'ㄤ','ã„¥'=>'ã„¥','ㄦ'=>'ㄦ','ã„§'=>'ã„§','ㄨ'=>'ㄨ','ã„©'=>'ã„©','ㄪ'=>'ㄪ','ã„«'=>'ã„«','ㄬ'=>'ㄬ','ㄱ'=>'ㄱ','ㄲ'=>'ㄲ','ㄳ'=>'ㄳ','ã„´'=>'ã„´','ㄵ'=>'ㄵ','ã„¶'=>'ã„¶','ã„·'=>'ã„·','ㄸ'=>'ㄸ','ㄹ'=>'ㄹ','ㄺ'=>'ㄺ','ã„»'=>'ã„»','ㄼ'=>'ㄼ','ㄽ'=>'ㄽ','ㄾ'=>'ㄾ','ã„¿'=>'ã„¿','ã…€'=>'ã…€','ã…'=>'ã…','ã…‚'=>'ã…‚','ã…ƒ'=>'ã…ƒ','ã…„'=>'ã…„','ã……'=>'ã……','ã…†'=>'ã…†','ã…‡'=>'ã…‡','ã…ˆ'=>'ã…ˆ','ã…‰'=>'ã…‰','ã…Š'=>'ã…Š','ã…‹'=>'ã…‹','ã…Œ'=>'ã…Œ','ã…'=>'ã…','ã…Ž'=>'ã…Ž','ã…'=>'ã…','ã…'=>'ã…','ã…‘'=>'ã…‘','ã…’'=>'ã…’','ã…“'=>'ã…“','ã…”'=>'ã…”','ã…•'=>'ã…•','ã…–'=>'ã…–','ã…—'=>'ã…—','ã…˜'=>'ã…˜','ã…™'=>'ã…™','ã…š'=>'ã…š','ã…›'=>'ã…›','ã…œ'=>'ã…œ','ã…'=>'ã…','ã…ž'=>'ã…ž','ã…Ÿ'=>'ã…Ÿ','ã… '=>'ã… ','ã…¡'=>'ã…¡','ã…¢'=>'ã…¢','ã…£'=>'ã…£','ã…¤'=>'ã…¤','ã…¥'=>'ã…¥','ã…¦'=>'ã…¦','ã…§'=>'ã…§','ã…¨'=>'ã…¨','ã…©'=>'ã…©','ã…ª'=>'ã…ª','ã…«'=>'ã…«','ã…¬'=>'ã…¬','ã…'=>'ã…','ã…®'=>'ã…®','ã…¯'=>'ã…¯','ã…°'=>'ã…°','ã…±'=>'ã…±','ã…²'=>'ã…²','ã…³'=>'ã…³','ã…´'=>'ã…´','ã…µ'=>'ã…µ','ã…¶'=>'ã…¶','ã…·'=>'ã…·','ã…¸'=>'ã…¸','ã…¹'=>'ã…¹','ã…º'=>'ã…º','ã…»'=>'ã…»','ã…¼'=>'ã…¼','ã…½'=>'ã…½','ã…¾'=>'ã…¾','ã…¿'=>'ã…¿','ㆀ'=>'ㆀ','ã†'=>'ã†','ㆂ'=>'ㆂ','ㆃ'=>'ㆃ','ㆄ'=>'ㆄ','ㆅ'=>'ㆅ','ㆆ'=>'ㆆ','ㆇ'=>'ㆇ','ㆈ'=>'ㆈ','ㆉ'=>'ㆉ','ㆊ'=>'ㆊ','ㆋ'=>'ㆋ','ㆌ'=>'ㆌ','ã†'=>'ã†','ㆎ'=>'ㆎ','㆒'=>'1','㆓'=>'2','㆔'=>'3','㆕'=>'4','ㆠ'=>'ㆠ','ㆡ'=>'ㆡ','ㆢ'=>'ㆢ','ㆣ'=>'ㆣ','ㆤ'=>'ㆤ','ㆥ'=>'ㆥ','ㆦ'=>'ㆦ','ㆧ'=>'ㆧ','ㆨ'=>'ㆨ','ㆩ'=>'ㆩ','ㆪ'=>'ㆪ','ㆫ'=>'ㆫ','ㆬ'=>'ㆬ','ã†'=>'ã†','ㆮ'=>'ㆮ','ㆯ'=>'ㆯ','ㆰ'=>'ㆰ','ㆱ'=>'ㆱ','ㆲ'=>'ㆲ','ㆳ'=>'ㆳ','ㆴ'=>'ㆴ','ㆵ'=>'ㆵ','ㆶ'=>'ㆶ','ㆷ'=>'ㆷ','ㇰ'=>'ㇰ','ㇱ'=>'ㇱ','ㇲ'=>'ㇲ','ㇳ'=>'ㇳ','ㇴ'=>'ㇴ','ㇵ'=>'ㇵ','ㇶ'=>'ㇶ','ㇷ'=>'ㇷ','ㇸ'=>'ㇸ','ㇹ'=>'ㇹ','ㇺ'=>'ㇺ','ㇻ'=>'ㇻ','ㇼ'=>'ㇼ','ㇽ'=>'ㇽ','ㇾ'=>'ㇾ','ㇿ'=>'ㇿ','㈠'=>'1','㈡'=>'2','㈢'=>'3','㈣'=>'4','㈤'=>'5','㈥'=>'6','㈦'=>'7','㈧'=>'8','㈨'=>'9','㈩'=>'10','㉑'=>'21','㉒'=>'22','㉓'=>'23','㉔'=>'24','㉕'=>'25','㉖'=>'26','㉗'=>'27','㉘'=>'28','㉙'=>'29','㉚'=>'30','㉛'=>'31','㉜'=>'32','ã‰'=>'33','㉞'=>'34','㉟'=>'35','㊀'=>'1','ãŠ'=>'2','㊂'=>'3','㊃'=>'4','㊄'=>'5','㊅'=>'6','㊆'=>'7','㊇'=>'8','㊈'=>'9','㊉'=>'10','㊱'=>'36','㊲'=>'37','㊳'=>'38','㊴'=>'39','㊵'=>'40','㊶'=>'41','㊷'=>'42','㊸'=>'43','㊹'=>'44','㊺'=>'45','㊻'=>'46','㊼'=>'47','㊽'=>'48','㊾'=>'49','㊿'=>'50','ã€'=>'ã€');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_64.php b/phpBB/includes/utf/data/search_indexer_64.php deleted file mode 100644 index 44d0beb624..0000000000 --- a/phpBB/includes/utf/data/search_indexer_64.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('ð €€'=>'ð €€');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_84.php b/phpBB/includes/utf/data/search_indexer_84.php deleted file mode 100644 index 5c3f1d54b8..0000000000 --- a/phpBB/includes/utf/data/search_indexer_84.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('𪛖'=>'𪛖');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_9.php b/phpBB/includes/utf/data/search_indexer_9.php deleted file mode 100644 index bdf188291f..0000000000 --- a/phpBB/includes/utf/data/search_indexer_9.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('䶵'=>'䶵','一'=>'一');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/search_indexer_95.php b/phpBB/includes/utf/data/search_indexer_95.php deleted file mode 100644 index b0f8eed3aa..0000000000 --- a/phpBB/includes/utf/data/search_indexer_95.php +++ /dev/null @@ -1 +0,0 @@ -<?php return array('丽'=>'丽','ð¯ '=>'ð¯ ','乁'=>'乁','𠄢'=>'𠄢','你'=>'你','侮'=>'侮','侻'=>'侻','倂'=>'倂','偺'=>'偺','備'=>'備','僧'=>'僧','像'=>'像','㒞'=>'㒞','ð¯ '=>'ð¯ ','免'=>'免','ð¯ '=>'ð¯ ','ð¯ '=>'ð¯ ','具'=>'具','𠔜'=>'𠔜','㒹'=>'㒹','內'=>'內','再'=>'再','𠕋'=>'𠕋','冗'=>'冗','冤'=>'冤','仌'=>'仌','冬'=>'冬','况'=>'况','𩇟'=>'𩇟','ð¯ '=>'ð¯ ','刃'=>'刃','㓟'=>'㓟','ð¯ '=>'ð¯ ','剆'=>'剆','割'=>'割','剷'=>'剷','㔕'=>'㔕','勇'=>'勇','勉'=>'勉','勤'=>'勤','勺'=>'勺','包'=>'包','匆'=>'匆','北'=>'北','卉'=>'卉','ð¯ '=>'ð¯ ','博'=>'博','即'=>'即','卽'=>'卽','卿'=>'卿','卿'=>'卿','卿'=>'卿','𠨬'=>'𠨬','灰'=>'灰','及'=>'及','叟'=>'叟','𠭣'=>'𠭣','叫'=>'叫','叱'=>'叱','吆'=>'吆','咞'=>'咞','吸'=>'吸','呈'=>'呈','周'=>'周','咢'=>'咢','ð¯¡'=>'ð¯¡','唐'=>'唐','啓'=>'啓','啣'=>'啣','善'=>'善','善'=>'善','喙'=>'喙','喫'=>'喫','喳'=>'喳','嗂'=>'嗂','圖'=>'圖','嘆'=>'嘆','ð¯¡'=>'ð¯¡','噑'=>'噑','ð¯¡'=>'ð¯¡','ð¯¡'=>'ð¯¡','壮'=>'壮','城'=>'城','埴'=>'埴','堍'=>'堍','型'=>'型','堲'=>'堲','報'=>'報','墬'=>'墬','𡓤'=>'𡓤','売'=>'売','壷'=>'壷','夆'=>'夆','ð¯¡'=>'ð¯¡','夢'=>'夢','奢'=>'奢','𡚨'=>'𡚨','𡛪'=>'𡛪','姬'=>'姬','娛'=>'娛','娧'=>'娧','姘'=>'姘','婦'=>'婦','㛮'=>'㛮','㛼'=>'㛼','嬈'=>'嬈','嬾'=>'嬾','嬾'=>'嬾','𡧈'=>'𡧈','ð¯¡'=>'ð¯¡','寘'=>'寘','寧'=>'寧','寳'=>'寳','𡬘'=>'𡬘','寿'=>'寿','将'=>'将','当'=>'当','尢'=>'尢','㞁'=>'㞁','屠'=>'屠','屮'=>'屮','峀'=>'峀','岍'=>'岍','𡷤'=>'𡷤','嵃'=>'嵃','𡷦'=>'𡷦','嵮'=>'嵮','嵫'=>'嵫','嵼'=>'嵼','ð¯¢'=>'ð¯¢','巢'=>'巢','㠯'=>'㠯','巽'=>'巽','帨'=>'帨','帽'=>'帽','幩'=>'幩','㡢'=>'㡢','𢆃'=>'𢆃','㡼'=>'㡼','庰'=>'庰','庳'=>'庳','ð¯¢'=>'ð¯¢','廊'=>'廊','ð¯¢'=>'ð¯¢','ð¯¢'=>'ð¯¢','𢌱'=>'𢌱','𢌱'=>'𢌱','舁'=>'舁','弢'=>'弢','弢'=>'弢','㣇'=>'㣇','𣊸'=>'𣊸','𦇚'=>'𦇚','形'=>'形','彫'=>'彫','㣣'=>'㣣','徚'=>'徚','ð¯¢'=>'ð¯¢','志'=>'志','忹'=>'忹','悁'=>'悁','㤺'=>'㤺','㤜'=>'㤜','悔'=>'悔','𢛔'=>'𢛔','惇'=>'惇','慈'=>'慈','慌'=>'慌','慎'=>'慎','慌'=>'慌','慺'=>'慺','憎'=>'憎','憲'=>'憲','ð¯¢'=>'ð¯¢','憯'=>'憯','懞'=>'懞','懲'=>'懲','懶'=>'懶','成'=>'成','戛'=>'戛','扝'=>'扝','抱'=>'抱','拔'=>'拔','捐'=>'捐','𢬌'=>'𢬌','挽'=>'挽','拼'=>'拼','捨'=>'捨','掃'=>'掃','揤'=>'揤','𢯱'=>'𢯱','搢'=>'搢','揅'=>'揅','ð¯£'=>'ð¯£','㨮'=>'㨮','摩'=>'摩','摾'=>'摾','撝'=>'撝','摷'=>'摷','㩬'=>'㩬','敏'=>'敏','敬'=>'敬','𣀊'=>'𣀊','旣'=>'旣','書'=>'書','ð¯£'=>'ð¯£','㬙'=>'㬙','ð¯£'=>'ð¯£','ð¯£'=>'ð¯£','㫤'=>'㫤','冒'=>'冒','冕'=>'冕','最'=>'最','暜'=>'暜','肭'=>'肭','䏙'=>'䏙','朗'=>'朗','望'=>'望','朡'=>'朡','杞'=>'杞','杓'=>'杓','ð¯£'=>'ð¯£','㭉'=>'㭉','柺'=>'柺','枅'=>'枅','桒'=>'桒','梅'=>'梅','𣑭'=>'𣑭','梎'=>'梎','栟'=>'栟','椔'=>'椔','㮝'=>'㮝','楂'=>'楂','榣'=>'榣','槪'=>'槪','檨'=>'檨','𣚣'=>'𣚣','ð¯£'=>'ð¯£','㰘'=>'㰘','次'=>'次','𣢧'=>'𣢧','歔'=>'歔','㱎'=>'㱎','歲'=>'歲','殟'=>'殟','殺'=>'殺','殻'=>'殻','𣪍'=>'𣪍','𡴋'=>'𡴋','𣫺'=>'𣫺','汎'=>'汎','𣲼'=>'𣲼','沿'=>'沿','泍'=>'泍','汧'=>'汧','洖'=>'洖','派'=>'派','ð¯¤'=>'ð¯¤','流'=>'流','浩'=>'浩','浸'=>'浸','涅'=>'涅','𣴞'=>'𣴞','洴'=>'洴','港'=>'港','湮'=>'湮','㴳'=>'㴳','滋'=>'滋','滇'=>'滇','ð¯¤'=>'ð¯¤','淹'=>'淹','ð¯¤'=>'ð¯¤','ð¯¤'=>'ð¯¤','𣾎'=>'𣾎','濆'=>'濆','瀹'=>'瀹','瀞'=>'瀞','瀛'=>'瀛','㶖'=>'㶖','灊'=>'灊','災'=>'災','灷'=>'灷','炭'=>'炭','𠔥'=>'𠔥','煅'=>'煅','ð¯¤'=>'ð¯¤','熜'=>'熜','𤎫'=>'𤎫','爨'=>'爨','爵'=>'爵','牐'=>'牐','𤘈'=>'𤘈','犀'=>'犀','犕'=>'犕','𤜵'=>'𤜵','𤠔'=>'𤠔','獺'=>'獺','王'=>'王','㺬'=>'㺬','玥'=>'玥','㺸'=>'㺸','ð¯¤'=>'ð¯¤','瑇'=>'瑇','瑜'=>'瑜','瑱'=>'瑱','璅'=>'璅','瓊'=>'瓊','㼛'=>'㼛','甤'=>'甤','𤰶'=>'𤰶','甾'=>'甾','𤲒'=>'𤲒','異'=>'異','𢆟'=>'𢆟','瘐'=>'瘐','𤾡'=>'𤾡','𤾸'=>'𤾸','𥁄'=>'𥁄','㿼'=>'㿼','䀈'=>'䀈','直'=>'直','ð¯¥'=>'ð¯¥','𥃲'=>'𥃲','𥄙'=>'𥄙','𥄳'=>'𥄳','眞'=>'眞','真'=>'真','真'=>'真','睊'=>'睊','䀹'=>'䀹','瞋'=>'瞋','䁆'=>'䁆','䂖'=>'䂖','ð¯¥'=>'ð¯¥','硎'=>'硎','ð¯¥'=>'ð¯¥','ð¯¥'=>'ð¯¥','䃣'=>'䃣','𥘦'=>'𥘦','祖'=>'祖','𥚚'=>'𥚚','𥛅'=>'𥛅','福'=>'福','秫'=>'秫','䄯'=>'䄯','穀'=>'穀','穊'=>'穊','穏'=>'穏','𥥼'=>'𥥼','ð¯¥'=>'ð¯¥','𥪧'=>'𥪧','竮'=>'竮','䈂'=>'䈂','𥮫'=>'𥮫','篆'=>'篆','築'=>'築','䈧'=>'䈧','𥲀'=>'𥲀','糒'=>'糒','䊠'=>'䊠','糨'=>'糨','糣'=>'糣','紀'=>'紀','𥾆'=>'𥾆','絣'=>'絣','ð¯¥'=>'ð¯¥','緇'=>'緇','縂'=>'縂','繅'=>'繅','䌴'=>'䌴','𦈨'=>'𦈨','𦉇'=>'𦉇','䍙'=>'䍙','𦋙'=>'𦋙','罺'=>'罺','𦌾'=>'𦌾','羕'=>'羕','翺'=>'翺','者'=>'者','𦓚'=>'𦓚','𦔣'=>'𦔣','聠'=>'聠','𦖨'=>'𦖨','聰'=>'聰','𣍟'=>'𣍟','ð¯¦'=>'ð¯¦','育'=>'育','脃'=>'脃','䐋'=>'䐋','脾'=>'脾','媵'=>'媵','𦞧'=>'𦞧','𦞵'=>'𦞵','𣎓'=>'𣎓','𣎜'=>'𣎜','舁'=>'舁','舄'=>'舄','ð¯¦'=>'ð¯¦','䑫'=>'䑫','ð¯¦'=>'ð¯¦','ð¯¦'=>'ð¯¦','芝'=>'芝','劳'=>'劳','花'=>'花','芳'=>'芳','芽'=>'芽','苦'=>'苦','𦬼'=>'𦬼','若'=>'若','茝'=>'茝','荣'=>'荣','莭'=>'莭','茣'=>'茣','ð¯¦'=>'ð¯¦','菧'=>'菧','著'=>'著','荓'=>'荓','菊'=>'菊','菌'=>'菌','菜'=>'菜','𦰶'=>'𦰶','𦵫'=>'𦵫','𦳕'=>'𦳕','䔫'=>'䔫','蓱'=>'蓱','蓳'=>'蓳','蔖'=>'蔖','𧏊'=>'𧏊','蕤'=>'蕤','ð¯¦'=>'ð¯¦','䕝'=>'䕝','䕡'=>'䕡','𦾱'=>'𦾱','𧃒'=>'𧃒','䕫'=>'䕫','虐'=>'虐','虜'=>'虜','虧'=>'虧','虩'=>'虩','蚩'=>'蚩','蚈'=>'蚈','蜎'=>'蜎','蛢'=>'蛢','蝹'=>'蝹','蜨'=>'蜨','蝫'=>'蝫','螆'=>'螆','䗗'=>'䗗','蟡'=>'蟡','ð¯§'=>'ð¯§','䗹'=>'䗹','衠'=>'衠','衣'=>'衣','𧙧'=>'𧙧','裗'=>'裗','裞'=>'裞','䘵'=>'䘵','裺'=>'裺','㒻'=>'㒻','𧢮'=>'𧢮','𧥦'=>'𧥦','ð¯§'=>'ð¯§','䛇'=>'䛇','ð¯§'=>'ð¯§','ð¯§'=>'ð¯§','變'=>'變','豕'=>'豕','𧲨'=>'𧲨','貫'=>'貫','賁'=>'賁','贛'=>'贛','起'=>'起','𧼯'=>'𧼯','𠠄'=>'𠠄','跋'=>'跋','趼'=>'趼','跰'=>'跰','ð¯§'=>'ð¯§','軔'=>'軔','輸'=>'輸','𨗒'=>'𨗒','𨗭'=>'𨗭','邔'=>'邔','郱'=>'郱','鄑'=>'鄑','𨜮'=>'𨜮','鄛'=>'鄛','鈸'=>'鈸','鋗'=>'鋗','鋘'=>'鋘','鉼'=>'鉼','鏹'=>'鏹','鐕'=>'鐕','ð¯§'=>'ð¯§','開'=>'開','䦕'=>'䦕','閷'=>'閷','𨵷'=>'𨵷','䧦'=>'䧦','雃'=>'雃','嶲'=>'嶲','霣'=>'霣','𩅅'=>'𩅅','𩈚'=>'𩈚','䩮'=>'䩮','䩶'=>'䩶','韠'=>'韠','𩐊'=>'𩐊','䪲'=>'䪲','𩒖'=>'𩒖','頋'=>'頋','頋'=>'頋','頩'=>'頩','ð¯¨'=>'ð¯¨','飢'=>'飢','䬳'=>'䬳','餩'=>'餩','馧'=>'馧','駂'=>'駂','駾'=>'駾','䯎'=>'䯎','𩬰'=>'𩬰','鬒'=>'鬒','鱀'=>'鱀','鳽'=>'鳽','ð¯¨'=>'ð¯¨','䳭'=>'䳭','ð¯¨'=>'ð¯¨','ð¯¨'=>'ð¯¨','䳸'=>'䳸','𪄅'=>'𪄅','𪈎'=>'𪈎','𪊑'=>'𪊑','麻'=>'麻','䵖'=>'䵖','黹'=>'黹','黾'=>'黾','鼅'=>'鼅','鼏'=>'鼏','鼖'=>'鼖','鼻'=>'鼻','ð¯¨'=>'ð¯¨');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/utf_canonical_comp.php b/phpBB/includes/utf/data/utf_canonical_comp.php deleted file mode 100644 index a3ed3ee602..0000000000 --- a/phpBB/includes/utf/data/utf_canonical_comp.php +++ /dev/null @@ -1,2 +0,0 @@ -<?php -$GLOBALS['utf_canonical_comp']=array('AÌ€'=>'À','AÌ'=>'Ã','AÌ‚'=>'Â','Ã'=>'Ã','Ä'=>'Ä','AÌŠ'=>'Ã…','Ç'=>'Ç','EÌ€'=>'È','EÌ'=>'É','EÌ‚'=>'Ê','Ë'=>'Ë','IÌ€'=>'ÃŒ','IÌ'=>'Ã','IÌ‚'=>'ÃŽ','Ï'=>'Ã','Ñ'=>'Ñ','OÌ€'=>'Ã’','OÌ'=>'Ó','OÌ‚'=>'Ô','Õ'=>'Õ','Ö'=>'Ö','UÌ€'=>'Ù','UÌ'=>'Ú','UÌ‚'=>'Û','Ü'=>'Ü','YÌ'=>'Ã','aÌ€'=>'à ','aÌ'=>'á','aÌ‚'=>'â','ã'=>'ã','ä'=>'ä','aÌŠ'=>'Ã¥','ç'=>'ç','eÌ€'=>'è','eÌ'=>'é','eÌ‚'=>'ê','ë'=>'ë','iÌ€'=>'ì','iÌ'=>'Ã','iÌ‚'=>'î','ï'=>'ï','ñ'=>'ñ','oÌ€'=>'ò','oÌ'=>'ó','oÌ‚'=>'ô','õ'=>'õ','ö'=>'ö','uÌ€'=>'ù','uÌ'=>'ú','uÌ‚'=>'û','ü'=>'ü','yÌ'=>'ý','ÿ'=>'ÿ','AÌ„'=>'Ä€','aÌ„'=>'Ä','Ă'=>'Ä‚','ă'=>'ă','Ą'=>'Ä„','ą'=>'Ä…','CÌ'=>'Ć','cÌ'=>'ć','CÌ‚'=>'Ĉ','cÌ‚'=>'ĉ','Ċ'=>'ÄŠ','ċ'=>'Ä‹','CÌŒ'=>'ÄŒ','cÌŒ'=>'Ä','DÌŒ'=>'ÄŽ','dÌŒ'=>'Ä','EÌ„'=>'Ä’','eÌ„'=>'Ä“','Ĕ'=>'Ä”','ĕ'=>'Ä•','Ė'=>'Ä–','ė'=>'Ä—','Ę'=>'Ę','ę'=>'Ä™','EÌŒ'=>'Äš','eÌŒ'=>'Ä›','GÌ‚'=>'Äœ','gÌ‚'=>'Ä','Ğ'=>'Äž','ğ'=>'ÄŸ','Ġ'=>'Ä ','ġ'=>'Ä¡','Ģ'=>'Ä¢','ģ'=>'Ä£','HÌ‚'=>'Ĥ','hÌ‚'=>'Ä¥','Ĩ'=>'Ĩ','ĩ'=>'Ä©','IÌ„'=>'Ī','iÌ„'=>'Ä«','Ĭ'=>'Ĭ','ĭ'=>'Ä','Į'=>'Ä®','į'=>'į','İ'=>'İ','JÌ‚'=>'Ä´','jÌ‚'=>'ĵ','Ķ'=>'Ķ','ķ'=>'Ä·','LÌ'=>'Ĺ','lÌ'=>'ĺ','Ļ'=>'Ä»','ļ'=>'ļ','LÌŒ'=>'Ľ','lÌŒ'=>'ľ','NÌ'=>'Ń','nÌ'=>'Å„','Ņ'=>'Å…','ņ'=>'ņ','NÌŒ'=>'Ň','nÌŒ'=>'ň','OÌ„'=>'ÅŒ','oÌ„'=>'Å','Ŏ'=>'ÅŽ','ŏ'=>'Å','OÌ‹'=>'Å','oÌ‹'=>'Å‘','RÌ'=>'Å”','rÌ'=>'Å•','Ŗ'=>'Å–','ŗ'=>'Å—','RÌŒ'=>'Ř','rÌŒ'=>'Å™','SÌ'=>'Åš','sÌ'=>'Å›','SÌ‚'=>'Åœ','sÌ‚'=>'Å','Ş'=>'Åž','ş'=>'ÅŸ','SÌŒ'=>'Å ','sÌŒ'=>'Å¡','Ţ'=>'Å¢','ţ'=>'Å£','TÌŒ'=>'Ť','tÌŒ'=>'Å¥','Ũ'=>'Ũ','ũ'=>'Å©','UÌ„'=>'Ū','uÌ„'=>'Å«','Ŭ'=>'Ŭ','ŭ'=>'Å','UÌŠ'=>'Å®','uÌŠ'=>'ů','UÌ‹'=>'Ű','uÌ‹'=>'ű','Ų'=>'Ų','ų'=>'ų','WÌ‚'=>'Å´','wÌ‚'=>'ŵ','YÌ‚'=>'Ŷ','yÌ‚'=>'Å·','Ÿ'=>'Ÿ','ZÌ'=>'Ź','zÌ'=>'ź','Ż'=>'Å»','ż'=>'ż','ZÌŒ'=>'Ž','zÌŒ'=>'ž','OÌ›'=>'Æ ','oÌ›'=>'Æ¡','UÌ›'=>'Ư','uÌ›'=>'ư','AÌŒ'=>'Ç','aÌŒ'=>'ÇŽ','IÌŒ'=>'Ç','iÌŒ'=>'Ç','OÌŒ'=>'Ç‘','oÌŒ'=>'Ç’','UÌŒ'=>'Ç“','uÌŒ'=>'Ç”','Ǖ'=>'Ç•','ǖ'=>'Ç–','ÜÌ'=>'Ç—','üÌ'=>'ǘ','Ǚ'=>'Ç™','ǚ'=>'Çš','Ǜ'=>'Ç›','ǜ'=>'Çœ','Ǟ'=>'Çž','ǟ'=>'ÇŸ','Ǡ'=>'Ç ','ǡ'=>'Ç¡','Ǣ'=>'Ç¢','ǣ'=>'Ç£','GÌŒ'=>'Ǧ','gÌŒ'=>'ǧ','KÌŒ'=>'Ǩ','kÌŒ'=>'Ç©','Ǫ'=>'Ǫ','ǫ'=>'Ç«','Ǭ'=>'Ǭ','ǭ'=>'Ç','Æ·ÌŒ'=>'Ç®','Ê’ÌŒ'=>'ǯ','jÌŒ'=>'ǰ','GÌ'=>'Ç´','gÌ'=>'ǵ','NÌ€'=>'Ǹ','nÌ€'=>'ǹ','Ã…Ì'=>'Ǻ','Ã¥Ì'=>'Ç»','ÆÌ'=>'Ǽ','æÌ'=>'ǽ','ØÌ'=>'Ǿ','øÌ'=>'Ç¿','AÌ'=>'È€','aÌ'=>'È','AÌ‘'=>'È‚','aÌ‘'=>'ȃ','EÌ'=>'È„','eÌ'=>'È…','EÌ‘'=>'Ȇ','eÌ‘'=>'ȇ','IÌ'=>'Ȉ','iÌ'=>'ȉ','IÌ‘'=>'ÈŠ','iÌ‘'=>'È‹','OÌ'=>'ÈŒ','oÌ'=>'È','OÌ‘'=>'ÈŽ','oÌ‘'=>'È','RÌ'=>'È','rÌ'=>'È‘','RÌ‘'=>'È’','rÌ‘'=>'È“','UÌ'=>'È”','uÌ'=>'È•','UÌ‘'=>'È–','uÌ‘'=>'È—','Ș'=>'Ș','ș'=>'È™','Ț'=>'Èš','ț'=>'È›','HÌŒ'=>'Èž','hÌŒ'=>'ÈŸ','Ȧ'=>'Ȧ','ȧ'=>'ȧ','Ȩ'=>'Ȩ','ȩ'=>'È©','Ȫ'=>'Ȫ','ȫ'=>'È«','Ȭ'=>'Ȭ','ȭ'=>'È','Ȯ'=>'È®','ȯ'=>'ȯ','Ȱ'=>'Ȱ','ȱ'=>'ȱ','YÌ„'=>'Ȳ','yÌ„'=>'ȳ','̈Ì'=>'Í„','¨Ì'=>'Î…','ΑÌ'=>'Ά','ΕÌ'=>'Έ','ΗÌ'=>'Ή','ΙÌ'=>'Ί','ΟÌ'=>'ÎŒ','Î¥Ì'=>'ÎŽ','ΩÌ'=>'Î','ÏŠÌ'=>'Î','Ϊ'=>'Ϊ','Ϋ'=>'Ϋ','αÌ'=>'ά','εÌ'=>'Î','ηÌ'=>'ή','ιÌ'=>'ί','Ï‹Ì'=>'ΰ','ϊ'=>'ÏŠ','ϋ'=>'Ï‹','οÌ'=>'ÏŒ','Ï…Ì'=>'Ï','ωÌ'=>'ÏŽ','Ï’Ì'=>'Ï“','ϔ'=>'Ï”','Ѐ'=>'Ѐ','Ё'=>'Ð','ГÌ'=>'Ѓ','Ї'=>'Ї','КÌ'=>'ÐŒ','Ѝ'=>'Ð','Ў'=>'ÐŽ','Й'=>'Й','й'=>'й','ѐ'=>'Ñ','ё'=>'Ñ‘','гÌ'=>'Ñ“','ї'=>'Ñ—','кÌ'=>'Ñœ','ѝ'=>'Ñ','ў'=>'Ñž','Ñ´Ì'=>'Ѷ','ѵÌ'=>'Ñ·','Ӂ'=>'Ó','ӂ'=>'Ó‚','Ð̆'=>'Ó','ӑ'=>'Ó‘','Ð̈'=>'Ó’','ӓ'=>'Ó“','Ӗ'=>'Ó–','ӗ'=>'Ó—','Ӛ'=>'Óš','ӛ'=>'Ó›','Ӝ'=>'Óœ','ӝ'=>'Ó','Ӟ'=>'Óž','ӟ'=>'ÓŸ','Ӣ'=>'Ó¢','ӣ'=>'Ó£','Ӥ'=>'Ó¤','ӥ'=>'Ó¥','Ӧ'=>'Ó¦','ӧ'=>'Ó§','Ӫ'=>'Óª','ӫ'=>'Ó«','Ð̈'=>'Ó¬','Ñ̈'=>'Ó','Ӯ'=>'Ó®','ӯ'=>'Ó¯','Ӱ'=>'Ó°','ӱ'=>'Ó±','Ӳ'=>'Ó²','ӳ'=>'Ó³','Ӵ'=>'Ó´','ӵ'=>'Óµ','Ӹ'=>'Ó¸','ӹ'=>'Ó¹','آ'=>'Ø¢','أ'=>'Ø£','ÙˆÙ”'=>'ؤ','إ'=>'Ø¥','ÙŠÙ”'=>'ئ','Û•Ù”'=>'Û€','ÛÙ”'=>'Û‚','Û’Ù”'=>'Û“','ऩ'=>'ऩ','ऱ'=>'ऱ','ऴ'=>'ऴ','ো'=>'à§‹','ৌ'=>'à§Œ','à‡à–'=>'àˆ','à‡à¬¾'=>'à‹','à‡à—'=>'àŒ','ஔ'=>'à®”','ொ'=>'ொ','ோ'=>'ோ','ௌ'=>'ௌ','ై'=>'ై','ೀ'=>'à³€','ೇ'=>'ೇ','ೈ'=>'ೈ','ೊ'=>'ೊ','ೋ'=>'ೋ','ൊ'=>'ൊ','ോ'=>'ോ','ൌ'=>'ൌ','ේ'=>'à·š','à·™à·'=>'à·œ','ෝ'=>'à·','ෞ'=>'à·ž','ཱི'=>'ཱི','ཱུ'=>'ཱུ','ཱྀ'=>'à¾','ဦ'=>'ဦ','ᬆ'=>'ᬆ','ᬈ'=>'ᬈ','ᬊ'=>'ᬊ','ᬌ'=>'ᬌ','á¬á¬µ'=>'ᬎ','ᬒ'=>'ᬒ','ᬻ'=>'ᬻ','ᬽ'=>'ᬽ','ᭀ'=>'á€','ᭁ'=>'á','á‚ᬵ'=>'áƒ','AÌ¥'=>'Ḁ','aÌ¥'=>'á¸','Ḃ'=>'Ḃ','ḃ'=>'ḃ','BÌ£'=>'Ḅ','bÌ£'=>'ḅ','Ḇ'=>'Ḇ','ḇ'=>'ḇ','ÇÌ'=>'Ḉ','çÌ'=>'ḉ','Ḋ'=>'Ḋ','ḋ'=>'ḋ','DÌ£'=>'Ḍ','dÌ£'=>'á¸','Ḏ'=>'Ḏ','ḏ'=>'á¸','Ḑ'=>'á¸','ḑ'=>'ḑ','DÌ'=>'Ḓ','dÌ'=>'ḓ','Ä’Ì€'=>'Ḕ','ḕ'=>'ḕ','Ä’Ì'=>'Ḗ','Ä“Ì'=>'ḗ','EÌ'=>'Ḙ','eÌ'=>'ḙ','Ḛ'=>'Ḛ','ḛ'=>'ḛ','Ḝ'=>'Ḝ','ḝ'=>'á¸','Ḟ'=>'Ḟ','ḟ'=>'ḟ','GÌ„'=>'Ḡ','gÌ„'=>'ḡ','Ḣ'=>'Ḣ','ḣ'=>'ḣ','HÌ£'=>'Ḥ','hÌ£'=>'ḥ','Ḧ'=>'Ḧ','ḧ'=>'ḧ','Ḩ'=>'Ḩ','ḩ'=>'ḩ','HÌ®'=>'Ḫ','hÌ®'=>'ḫ','Ḭ'=>'Ḭ','ḭ'=>'á¸','ÃÌ'=>'Ḯ','ïÌ'=>'ḯ','KÌ'=>'Ḱ','kÌ'=>'ḱ','KÌ£'=>'Ḳ','kÌ£'=>'ḳ','Ḵ'=>'Ḵ','ḵ'=>'ḵ','LÌ£'=>'Ḷ','lÌ£'=>'ḷ','Ḹ'=>'Ḹ','ḹ'=>'ḹ','Ḻ'=>'Ḻ','ḻ'=>'ḻ','LÌ'=>'Ḽ','lÌ'=>'ḽ','MÌ'=>'Ḿ','mÌ'=>'ḿ','Ṁ'=>'á¹€','ṁ'=>'á¹','MÌ£'=>'Ṃ','mÌ£'=>'ṃ','Ṅ'=>'Ṅ','ṅ'=>'á¹…','NÌ£'=>'Ṇ','nÌ£'=>'ṇ','Ṉ'=>'Ṉ','ṉ'=>'ṉ','NÌ'=>'Ṋ','nÌ'=>'ṋ','ÕÌ'=>'Ṍ','õÌ'=>'á¹','Ṏ'=>'Ṏ','ṏ'=>'á¹','Ṑ'=>'á¹','ÅÌ€'=>'ṑ','ÅŒÌ'=>'á¹’','ÅÌ'=>'ṓ','PÌ'=>'á¹”','pÌ'=>'ṕ','Ṗ'=>'á¹–','ṗ'=>'á¹—','Ṙ'=>'Ṙ','ṙ'=>'á¹™','RÌ£'=>'Ṛ','rÌ£'=>'á¹›','Ṝ'=>'Ṝ','ṝ'=>'á¹','Ṟ'=>'Ṟ','ṟ'=>'ṟ','Ṡ'=>'á¹ ','ṡ'=>'ṡ','SÌ£'=>'á¹¢','sÌ£'=>'á¹£','Ṥ'=>'Ṥ','ṥ'=>'á¹¥','Ṧ'=>'Ṧ','ṧ'=>'á¹§','Ṩ'=>'Ṩ','ṩ'=>'ṩ','Ṫ'=>'Ṫ','ṫ'=>'ṫ','TÌ£'=>'Ṭ','tÌ£'=>'á¹','Ṯ'=>'á¹®','ṯ'=>'ṯ','TÌ'=>'á¹°','tÌ'=>'á¹±','Ṳ'=>'á¹²','ṳ'=>'á¹³','Ṵ'=>'á¹´','ṵ'=>'á¹µ','UÌ'=>'á¹¶','uÌ'=>'á¹·','ŨÌ'=>'Ṹ','Å©Ì'=>'á¹¹','Ṻ'=>'Ṻ','ṻ'=>'á¹»','Ṽ'=>'á¹¼','ṽ'=>'á¹½','VÌ£'=>'á¹¾','vÌ£'=>'ṿ','WÌ€'=>'Ẁ','wÌ€'=>'áº','WÌ'=>'Ẃ','wÌ'=>'ẃ','Ẅ'=>'Ẅ','ẅ'=>'ẅ','Ẇ'=>'Ẇ','ẇ'=>'ẇ','WÌ£'=>'Ẉ','wÌ£'=>'ẉ','Ẋ'=>'Ẋ','ẋ'=>'ẋ','Ẍ'=>'Ẍ','ẍ'=>'áº','Ẏ'=>'Ẏ','ẏ'=>'áº','ZÌ‚'=>'áº','zÌ‚'=>'ẑ','ZÌ£'=>'Ẓ','zÌ£'=>'ẓ','Ẕ'=>'Ẕ','ẕ'=>'ẕ','ẖ'=>'ẖ','ẗ'=>'ẗ','wÌŠ'=>'ẘ','yÌŠ'=>'ẙ','ẛ'=>'ẛ','AÌ£'=>'Ạ','aÌ£'=>'ạ','Ả'=>'Ả','ả'=>'ả','ÂÌ'=>'Ấ','âÌ'=>'ấ','Ầ'=>'Ầ','ầ'=>'ầ','Ẩ'=>'Ẩ','ẩ'=>'ẩ','Ẫ'=>'Ẫ','ẫ'=>'ẫ','Ậ'=>'Ậ','ậ'=>'áº','Ä‚Ì'=>'Ắ','ăÌ'=>'ắ','Ằ'=>'Ằ','ằ'=>'ằ','Ẳ'=>'Ẳ','ẳ'=>'ẳ','Ẵ'=>'Ẵ','ẵ'=>'ẵ','Ặ'=>'Ặ','ặ'=>'ặ','EÌ£'=>'Ẹ','eÌ£'=>'ẹ','Ẻ'=>'Ẻ','ẻ'=>'ẻ','Ẽ'=>'Ẽ','ẽ'=>'ẽ','ÊÌ'=>'Ế','êÌ'=>'ế','Ề'=>'Ề','ề'=>'á»','Ể'=>'Ể','ể'=>'ể','Ễ'=>'Ễ','ễ'=>'á»…','Ệ'=>'Ệ','ệ'=>'ệ','Ỉ'=>'Ỉ','ỉ'=>'ỉ','IÌ£'=>'Ị','iÌ£'=>'ị','OÌ£'=>'Ọ','oÌ£'=>'á»','Ỏ'=>'Ỏ','ỏ'=>'á»','ÔÌ'=>'á»','ôÌ'=>'ố','Ồ'=>'á»’','ồ'=>'ồ','Ổ'=>'á»”','ổ'=>'ổ','Ỗ'=>'á»–','ỗ'=>'á»—','Ộ'=>'Ộ','á»Ì‚'=>'á»™','Æ Ì'=>'Ớ','Æ¡Ì'=>'á»›','Æ Ì€'=>'Ờ','ờ'=>'á»','Æ Ì‰'=>'Ở','ở'=>'ở','Æ Ìƒ'=>'á» ','ỡ'=>'ỡ','Æ Ì£'=>'Ợ','ợ'=>'ợ','UÌ£'=>'Ụ','uÌ£'=>'ụ','Ủ'=>'Ủ','ủ'=>'á»§','ƯÌ'=>'Ứ','ưÌ'=>'ứ','Ừ'=>'Ừ','ừ'=>'ừ','Ử'=>'Ử','ử'=>'á»','Ữ'=>'á»®','ữ'=>'ữ','Ự'=>'á»°','ự'=>'á»±','YÌ€'=>'Ỳ','yÌ€'=>'ỳ','YÌ£'=>'á»´','yÌ£'=>'ỵ','Ỷ'=>'á»¶','ỷ'=>'á»·','Ỹ'=>'Ỹ','ỹ'=>'ỹ','ἀ'=>'á¼€','ἁ'=>'á¼','ἂ'=>'ἂ','á¼Ì€'=>'ἃ','á¼€Ì'=>'ἄ','á¼Ì'=>'á¼…','ἆ'=>'ἆ','á¼Í‚'=>'ἇ','Ἀ'=>'Ἀ','Ἁ'=>'Ἁ','Ἂ'=>'Ἂ','Ἃ'=>'Ἃ','ἈÌ'=>'Ἄ','ἉÌ'=>'á¼','Ἆ'=>'Ἆ','Ἇ'=>'á¼','ἐ'=>'á¼','ἑ'=>'ἑ','á¼Ì€'=>'á¼’','ἓ'=>'ἓ','á¼Ì'=>'á¼”','ἑÌ'=>'ἕ','Ἐ'=>'Ἐ','Ἑ'=>'á¼™','Ἒ'=>'Ἒ','Ἓ'=>'á¼›','ἘÌ'=>'Ἔ','á¼™Ì'=>'á¼','ἠ'=>'á¼ ','ἡ'=>'ἡ','ἢ'=>'á¼¢','ἣ'=>'á¼£','á¼ Ì'=>'ἤ','ἡÌ'=>'á¼¥','á¼ Í‚'=>'ἦ','ἧ'=>'á¼§','Ἠ'=>'Ἠ','Ἡ'=>'Ἡ','Ἢ'=>'Ἢ','Ἣ'=>'Ἣ','ἨÌ'=>'Ἤ','ἩÌ'=>'á¼','Ἦ'=>'á¼®','Ἧ'=>'Ἧ','ἰ'=>'á¼°','ἱ'=>'á¼±','á¼°Ì€'=>'á¼²','ἳ'=>'á¼³','á¼°Ì'=>'á¼´','á¼±Ì'=>'á¼µ','á¼°Í‚'=>'á¼¶','ἷ'=>'á¼·','Ἰ'=>'Ἰ','Ἱ'=>'á¼¹','Ἲ'=>'Ἲ','Ἳ'=>'á¼»','ἸÌ'=>'á¼¼','á¼¹Ì'=>'á¼½','Ἶ'=>'á¼¾','Ἷ'=>'Ἷ','ὀ'=>'á½€','ὁ'=>'á½','ὂ'=>'ὂ','á½Ì€'=>'ὃ','á½€Ì'=>'ὄ','á½Ì'=>'á½…','Ὀ'=>'Ὀ','Ὁ'=>'Ὁ','Ὂ'=>'Ὂ','Ὃ'=>'Ὃ','ὈÌ'=>'Ὄ','ὉÌ'=>'á½','Ï…Ì“'=>'á½','Ï…Ì”'=>'ὑ','á½Ì€'=>'á½’','ὓ'=>'ὓ','á½Ì'=>'á½”','ὑÌ'=>'ὕ','á½Í‚'=>'á½–','ὗ'=>'á½—','Ὑ'=>'á½™','Ὓ'=>'á½›','á½™Ì'=>'á½','Ὗ'=>'Ὗ','ὠ'=>'á½ ','ὡ'=>'ὡ','ὢ'=>'á½¢','ὣ'=>'á½£','á½ Ì'=>'ὤ','ὡÌ'=>'á½¥','á½ Í‚'=>'ὦ','ὧ'=>'á½§','Ὠ'=>'Ὠ','Ὡ'=>'Ὡ','Ὢ'=>'Ὢ','Ὣ'=>'Ὣ','ὨÌ'=>'Ὤ','ὩÌ'=>'á½','Ὦ'=>'á½®','Ὧ'=>'Ὧ','ὰ'=>'á½°','ὲ'=>'á½²','ὴ'=>'á½´','ὶ'=>'á½¶','ὸ'=>'ὸ','Ï…Ì€'=>'ὺ','ὼ'=>'á½¼','ᾀ'=>'á¾€','á¼Í…'=>'á¾','ᾂ'=>'ᾂ','ᾃ'=>'ᾃ','ᾄ'=>'ᾄ','á¼…Í…'=>'á¾…','ᾆ'=>'ᾆ','ᾇ'=>'ᾇ','ᾈ'=>'ᾈ','ᾉ'=>'ᾉ','ᾊ'=>'ᾊ','ᾋ'=>'ᾋ','ᾌ'=>'ᾌ','á¼Í…'=>'á¾','ᾎ'=>'ᾎ','á¼Í…'=>'á¾','á¼ Í…'=>'á¾','ᾑ'=>'ᾑ','ᾒ'=>'á¾’','ᾓ'=>'ᾓ','ᾔ'=>'á¾”','ᾕ'=>'ᾕ','ᾖ'=>'á¾–','á¼§Í…'=>'á¾—','ᾘ'=>'ᾘ','ᾙ'=>'á¾™','ᾚ'=>'ᾚ','ᾛ'=>'á¾›','ᾜ'=>'ᾜ','á¼Í…'=>'á¾','ᾞ'=>'ᾞ','ᾟ'=>'ᾟ','á½ Í…'=>'á¾ ','ᾡ'=>'ᾡ','ᾢ'=>'á¾¢','ᾣ'=>'á¾£','ᾤ'=>'ᾤ','ᾥ'=>'á¾¥','ᾦ'=>'ᾦ','á½§Í…'=>'á¾§','ᾨ'=>'ᾨ','ᾩ'=>'ᾩ','ᾪ'=>'ᾪ','ᾫ'=>'ᾫ','ᾬ'=>'ᾬ','á½Í…'=>'á¾','ᾮ'=>'á¾®','ᾯ'=>'ᾯ','ᾰ'=>'á¾°','ᾱ'=>'á¾±','á½°Í…'=>'á¾²','ᾳ'=>'á¾³','ᾴ'=>'á¾´','ᾶ'=>'á¾¶','á¾¶Í…'=>'á¾·','Ᾰ'=>'Ᾰ','Ᾱ'=>'á¾¹','Ὰ'=>'Ὰ','ᾼ'=>'á¾¼','῁'=>'á¿','á½´Í…'=>'á¿‚','ῃ'=>'ῃ','ῄ'=>'á¿„','ῆ'=>'ῆ','ῇ'=>'ῇ','Ὲ'=>'Ὲ','Ὴ'=>'Ὴ','ῌ'=>'ῌ','῍'=>'á¿','᾿Ì'=>'῎','῏'=>'á¿','ῐ'=>'á¿','ῑ'=>'á¿‘','ÏŠÌ€'=>'á¿’','ῖ'=>'á¿–','ÏŠÍ‚'=>'á¿—','Ῐ'=>'Ῐ','Ῑ'=>'á¿™','Ὶ'=>'Ὶ','῝'=>'á¿','῾Ì'=>'῞','῟'=>'῟','ῠ'=>'á¿ ','Ï…Ì„'=>'á¿¡','ῢ'=>'á¿¢','ÏÌ“'=>'ῤ','ÏÌ”'=>'á¿¥','Ï…Í‚'=>'ῦ','ῧ'=>'á¿§','Ῠ'=>'Ῠ','Ῡ'=>'á¿©','Ὺ'=>'Ὺ','Ῥ'=>'Ῥ','῭'=>'á¿','ῲ'=>'ῲ','ῳ'=>'ῳ','ÏŽÍ…'=>'á¿´','ῶ'=>'á¿¶','á¿¶Í…'=>'á¿·','Ὸ'=>'Ὸ','Ὼ'=>'Ὼ','ῼ'=>'ῼ','â†Ì¸'=>'↚','↛'=>'↛','↮'=>'↮','â‡Ì¸'=>'â‡','⇎'=>'⇎','⇏'=>'â‡','∄'=>'∄','∉'=>'∉','∌'=>'∌','∤'=>'∤','∦'=>'∦','≁'=>'â‰','≄'=>'≄','≇'=>'≇','≉'=>'≉','≠'=>'≠','≢'=>'≢','â‰Ì¸'=>'â‰','≮'=>'≮','≯'=>'≯','≰'=>'≰','≱'=>'≱','≴'=>'≴','≵'=>'≵','≸'=>'≸','≹'=>'≹','⊀'=>'⊀','⊁'=>'âŠ','⊄'=>'⊄','⊅'=>'⊅','⊈'=>'⊈','⊉'=>'⊉','⊬'=>'⊬','⊭'=>'âŠ','⊮'=>'⊮','⊯'=>'⊯','⋠'=>'â‹ ','⋡'=>'â‹¡','⋢'=>'â‹¢','⋣'=>'â‹£','⋪'=>'⋪','⋫'=>'â‹«','⋬'=>'⋬','⋭'=>'â‹','ã‹ã‚™'=>'ãŒ','ãã‚™'=>'ãŽ','ãã‚™'=>'ã','ã‘ã‚™'=>'ã’','ã“ã‚™'=>'ã”','ã•ã‚™'=>'ã–','ã—ã‚™'=>'ã˜','ã™ã‚™'=>'ãš','ã›ã‚™'=>'ãœ','ãã‚™'=>'ãž','ãŸã‚™'=>'ã ','ã¡ã‚™'=>'ã¢','ã¤ã‚™'=>'ã¥','ã¦ã‚™'=>'ã§','ã¨ã‚™'=>'ã©','ã¯ã‚™'=>'ã°','ã¯ã‚š'=>'ã±','ã²ã‚™'=>'ã³','ã²ã‚š'=>'ã´','ãµã‚™'=>'ã¶','ãµã‚š'=>'ã·','ã¸ã‚™'=>'ã¹','ã¸ã‚š'=>'ãº','ã»ã‚™'=>'ã¼','ã»ã‚š'=>'ã½','ã†ã‚™'=>'ã‚”','ã‚ã‚™'=>'ゞ','ã‚«ã‚™'=>'ガ','ã‚ã‚™'=>'ã‚®','グ'=>'ã‚°','ゲ'=>'ゲ','ゴ'=>'ã‚´','ザ'=>'ã‚¶','ã‚·ã‚™'=>'ジ','ズ'=>'ズ','ゼ'=>'ゼ','ゾ'=>'ゾ','ã‚¿ã‚™'=>'ダ','ãƒã‚™'=>'ヂ','ヅ'=>'ヅ','デ'=>'デ','ド'=>'ド','ãƒã‚™'=>'ãƒ','ãƒã‚š'=>'パ','ビ'=>'ビ','ピ'=>'ピ','ブ'=>'ブ','プ'=>'プ','ベ'=>'ベ','ペ'=>'ペ','ボ'=>'ボ','ポ'=>'ãƒ','ヴ'=>'ヴ','ヷ'=>'ヷ','ヸ'=>'ヸ','ヹ'=>'ヹ','ヺ'=>'ヺ','ヾ'=>'ヾ');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/utf_canonical_decomp.php b/phpBB/includes/utf/data/utf_canonical_decomp.php deleted file mode 100644 index 460a0cf323..0000000000 --- a/phpBB/includes/utf/data/utf_canonical_decomp.php +++ /dev/null @@ -1,2 +0,0 @@ -<?php -$GLOBALS['utf_canonical_decomp']=array('À'=>'AÌ€','Ã'=>'AÌ','Â'=>'AÌ‚','Ã'=>'Ã','Ä'=>'Ä','Ã…'=>'AÌŠ','Ç'=>'Ç','È'=>'EÌ€','É'=>'EÌ','Ê'=>'EÌ‚','Ë'=>'Ë','ÃŒ'=>'IÌ€','Ã'=>'IÌ','ÃŽ'=>'IÌ‚','Ã'=>'Ï','Ñ'=>'Ñ','Ã’'=>'OÌ€','Ó'=>'OÌ','Ô'=>'OÌ‚','Õ'=>'Õ','Ö'=>'Ö','Ù'=>'UÌ€','Ú'=>'UÌ','Û'=>'UÌ‚','Ü'=>'Ü','Ã'=>'YÌ','à '=>'aÌ€','á'=>'aÌ','â'=>'aÌ‚','ã'=>'ã','ä'=>'ä','Ã¥'=>'aÌŠ','ç'=>'ç','è'=>'eÌ€','é'=>'eÌ','ê'=>'eÌ‚','ë'=>'ë','ì'=>'iÌ€','Ã'=>'iÌ','î'=>'iÌ‚','ï'=>'ï','ñ'=>'ñ','ò'=>'oÌ€','ó'=>'oÌ','ô'=>'oÌ‚','õ'=>'õ','ö'=>'ö','ù'=>'uÌ€','ú'=>'uÌ','û'=>'uÌ‚','ü'=>'ü','ý'=>'yÌ','ÿ'=>'ÿ','Ä€'=>'AÌ„','Ä'=>'aÌ„','Ä‚'=>'Ă','ă'=>'ă','Ä„'=>'Ą','Ä…'=>'ą','Ć'=>'CÌ','ć'=>'cÌ','Ĉ'=>'CÌ‚','ĉ'=>'cÌ‚','ÄŠ'=>'Ċ','Ä‹'=>'ċ','ÄŒ'=>'CÌŒ','Ä'=>'cÌŒ','ÄŽ'=>'DÌŒ','Ä'=>'dÌŒ','Ä’'=>'EÌ„','Ä“'=>'eÌ„','Ä”'=>'Ĕ','Ä•'=>'ĕ','Ä–'=>'Ė','Ä—'=>'ė','Ę'=>'Ę','Ä™'=>'ę','Äš'=>'EÌŒ','Ä›'=>'eÌŒ','Äœ'=>'GÌ‚','Ä'=>'gÌ‚','Äž'=>'Ğ','ÄŸ'=>'ğ','Ä '=>'Ġ','Ä¡'=>'ġ','Ä¢'=>'Ģ','Ä£'=>'ģ','Ĥ'=>'HÌ‚','Ä¥'=>'hÌ‚','Ĩ'=>'Ĩ','Ä©'=>'ĩ','Ī'=>'IÌ„','Ä«'=>'iÌ„','Ĭ'=>'Ĭ','Ä'=>'ĭ','Ä®'=>'Į','į'=>'į','İ'=>'İ','Ä´'=>'JÌ‚','ĵ'=>'jÌ‚','Ķ'=>'Ķ','Ä·'=>'ķ','Ĺ'=>'LÌ','ĺ'=>'lÌ','Ä»'=>'Ļ','ļ'=>'ļ','Ľ'=>'LÌŒ','ľ'=>'lÌŒ','Ń'=>'NÌ','Å„'=>'nÌ','Å…'=>'Ņ','ņ'=>'ņ','Ň'=>'NÌŒ','ň'=>'nÌŒ','ÅŒ'=>'OÌ„','Å'=>'oÌ„','ÅŽ'=>'Ŏ','Å'=>'ŏ','Å'=>'OÌ‹','Å‘'=>'oÌ‹','Å”'=>'RÌ','Å•'=>'rÌ','Å–'=>'Ŗ','Å—'=>'ŗ','Ř'=>'RÌŒ','Å™'=>'rÌŒ','Åš'=>'SÌ','Å›'=>'sÌ','Åœ'=>'SÌ‚','Å'=>'sÌ‚','Åž'=>'Ş','ÅŸ'=>'ş','Å '=>'SÌŒ','Å¡'=>'sÌŒ','Å¢'=>'Ţ','Å£'=>'ţ','Ť'=>'TÌŒ','Å¥'=>'tÌŒ','Ũ'=>'Ũ','Å©'=>'ũ','Ū'=>'UÌ„','Å«'=>'uÌ„','Ŭ'=>'Ŭ','Å'=>'ŭ','Å®'=>'UÌŠ','ů'=>'uÌŠ','Ű'=>'UÌ‹','ű'=>'uÌ‹','Ų'=>'Ų','ų'=>'ų','Å´'=>'WÌ‚','ŵ'=>'wÌ‚','Ŷ'=>'YÌ‚','Å·'=>'yÌ‚','Ÿ'=>'Ÿ','Ź'=>'ZÌ','ź'=>'zÌ','Å»'=>'Ż','ż'=>'ż','Ž'=>'ZÌŒ','ž'=>'zÌŒ','Æ '=>'OÌ›','Æ¡'=>'oÌ›','Ư'=>'UÌ›','ư'=>'uÌ›','Ç'=>'AÌŒ','ÇŽ'=>'aÌŒ','Ç'=>'IÌŒ','Ç'=>'iÌŒ','Ç‘'=>'OÌŒ','Ç’'=>'oÌŒ','Ç“'=>'UÌŒ','Ç”'=>'uÌŒ','Ç•'=>'Ǖ','Ç–'=>'ǖ','Ç—'=>'ÜÌ','ǘ'=>'üÌ','Ç™'=>'Ǚ','Çš'=>'ǚ','Ç›'=>'Ǜ','Çœ'=>'ǜ','Çž'=>'Ǟ','ÇŸ'=>'ǟ','Ç '=>'Ǡ','Ç¡'=>'ǡ','Ç¢'=>'Ǣ','Ç£'=>'ǣ','Ǧ'=>'GÌŒ','ǧ'=>'gÌŒ','Ǩ'=>'KÌŒ','Ç©'=>'kÌŒ','Ǫ'=>'Ǫ','Ç«'=>'ǫ','Ǭ'=>'Ǭ','Ç'=>'ǭ','Ç®'=>'Æ·ÌŒ','ǯ'=>'Ê’ÌŒ','ǰ'=>'jÌŒ','Ç´'=>'GÌ','ǵ'=>'gÌ','Ǹ'=>'NÌ€','ǹ'=>'nÌ€','Ǻ'=>'AÌŠÌ','Ç»'=>'aÌŠÌ','Ǽ'=>'ÆÌ','ǽ'=>'æÌ','Ǿ'=>'ØÌ','Ç¿'=>'øÌ','È€'=>'AÌ','È'=>'aÌ','È‚'=>'AÌ‘','ȃ'=>'aÌ‘','È„'=>'EÌ','È…'=>'eÌ','Ȇ'=>'EÌ‘','ȇ'=>'eÌ‘','Ȉ'=>'IÌ','ȉ'=>'iÌ','ÈŠ'=>'IÌ‘','È‹'=>'iÌ‘','ÈŒ'=>'OÌ','È'=>'oÌ','ÈŽ'=>'OÌ‘','È'=>'oÌ‘','È'=>'RÌ','È‘'=>'rÌ','È’'=>'RÌ‘','È“'=>'rÌ‘','È”'=>'UÌ','È•'=>'uÌ','È–'=>'UÌ‘','È—'=>'uÌ‘','Ș'=>'Ș','È™'=>'ș','Èš'=>'Ț','È›'=>'ț','Èž'=>'HÌŒ','ÈŸ'=>'hÌŒ','Ȧ'=>'Ȧ','ȧ'=>'ȧ','Ȩ'=>'Ȩ','È©'=>'ȩ','Ȫ'=>'Ȫ','È«'=>'ȫ','Ȭ'=>'Ȭ','È'=>'ȭ','È®'=>'Ȯ','ȯ'=>'ȯ','Ȱ'=>'Ȱ','ȱ'=>'ȱ','Ȳ'=>'YÌ„','ȳ'=>'yÌ„','Í€'=>'Ì€','Í'=>'Ì','̓'=>'Ì“','Í„'=>'̈Ì','Í´'=>'ʹ',';'=>';','Î…'=>'¨Ì','Ά'=>'ΑÌ','·'=>'·','Έ'=>'ΕÌ','Ή'=>'ΗÌ','Ί'=>'ΙÌ','ÎŒ'=>'ΟÌ','ÎŽ'=>'Î¥Ì','Î'=>'ΩÌ','Î'=>'ϊÌ','Ϊ'=>'Ϊ','Ϋ'=>'Ϋ','ά'=>'αÌ','Î'=>'εÌ','ή'=>'ηÌ','ί'=>'ιÌ','ΰ'=>'ϋÌ','ÏŠ'=>'ϊ','Ï‹'=>'ϋ','ÏŒ'=>'οÌ','Ï'=>'Ï…Ì','ÏŽ'=>'ωÌ','Ï“'=>'Ï’Ì','Ï”'=>'ϔ','Ѐ'=>'Ѐ','Ð'=>'Ё','Ѓ'=>'ГÌ','Ї'=>'Ї','ÐŒ'=>'КÌ','Ð'=>'Ѝ','ÐŽ'=>'Ў','Й'=>'Й','й'=>'й','Ñ'=>'ѐ','Ñ‘'=>'ё','Ñ“'=>'гÌ','Ñ—'=>'ї','Ñœ'=>'кÌ','Ñ'=>'ѝ','Ñž'=>'ў','Ѷ'=>'Ñ´Ì','Ñ·'=>'ѵÌ','Ó'=>'Ӂ','Ó‚'=>'ӂ','Ó'=>'Ð̆','Ó‘'=>'ӑ','Ó’'=>'Ð̈','Ó“'=>'ӓ','Ó–'=>'Ӗ','Ó—'=>'ӗ','Óš'=>'Ӛ','Ó›'=>'ӛ','Óœ'=>'Ӝ','Ó'=>'ӝ','Óž'=>'Ӟ','ÓŸ'=>'ӟ','Ó¢'=>'Ӣ','Ó£'=>'ӣ','Ó¤'=>'Ӥ','Ó¥'=>'ӥ','Ó¦'=>'Ӧ','Ó§'=>'ӧ','Óª'=>'Ӫ','Ó«'=>'ӫ','Ó¬'=>'Ð̈','Ó'=>'Ñ̈','Ó®'=>'Ӯ','Ó¯'=>'ӯ','Ó°'=>'Ӱ','Ó±'=>'ӱ','Ó²'=>'Ӳ','Ó³'=>'ӳ','Ó´'=>'Ӵ','Óµ'=>'ӵ','Ó¸'=>'Ӹ','Ó¹'=>'ӹ','Ø¢'=>'آ','Ø£'=>'أ','ؤ'=>'ÙˆÙ”','Ø¥'=>'إ','ئ'=>'ÙŠÙ”','Û€'=>'Û•Ù”','Û‚'=>'ÛÙ”','Û“'=>'Û’Ù”','ऩ'=>'ऩ','ऱ'=>'ऱ','ऴ'=>'ऴ','क़'=>'क़','ख़'=>'ख़','ग़'=>'ग़','ज़'=>'ज़','ड़'=>'ड़','à¥'=>'ढ़','फ़'=>'फ़','य़'=>'य़','à§‹'=>'ো','à§Œ'=>'ৌ','à§œ'=>'ড়','à§'=>'ঢ়','à§Ÿ'=>'য়','ਲ਼'=>'ਲ਼','ਸ਼'=>'ਸ਼','à©™'=>'ਖ਼','ਗ਼'=>'ਗ਼','à©›'=>'ਜ਼','ਫ਼'=>'ਫ਼','àˆ'=>'à‡à–','à‹'=>'à‡à¬¾','àŒ'=>'à‡à—','àœ'=>'ଡ଼','à'=>'ଢ଼','à®”'=>'ஔ','ொ'=>'ொ','ோ'=>'ோ','ௌ'=>'ௌ','ై'=>'ై','à³€'=>'ೀ','ೇ'=>'ೇ','ೈ'=>'ೈ','ೊ'=>'ೊ','ೋ'=>'ೋ','ൊ'=>'ൊ','ോ'=>'ോ','ൌ'=>'ൌ','à·š'=>'ේ','à·œ'=>'à·™à·','à·'=>'à·™à·à·Š','à·ž'=>'ෞ','གྷ'=>'གྷ','à½'=>'ཌྷ','དྷ'=>'དྷ','བྷ'=>'བྷ','ཛྷ'=>'ཛྷ','ཀྵ'=>'ཀྵ','ཱི'=>'ཱི','ཱུ'=>'ཱུ','ྲྀ'=>'ྲྀ','ླྀ'=>'ླྀ','à¾'=>'ཱྀ','ྒྷ'=>'ྒྷ','à¾'=>'ྜྷ','ྡྷ'=>'ྡྷ','ྦྷ'=>'ྦྷ','ྫྷ'=>'ྫྷ','ྐྵ'=>'à¾à¾µ','ဦ'=>'ဦ','ᬆ'=>'ᬆ','ᬈ'=>'ᬈ','ᬊ'=>'ᬊ','ᬌ'=>'ᬌ','ᬎ'=>'á¬á¬µ','ᬒ'=>'ᬒ','ᬻ'=>'ᬻ','ᬽ'=>'ᬽ','á€'=>'ᭀ','á'=>'ᭁ','áƒ'=>'á‚ᬵ','Ḁ'=>'AÌ¥','á¸'=>'aÌ¥','Ḃ'=>'Ḃ','ḃ'=>'ḃ','Ḅ'=>'BÌ£','ḅ'=>'bÌ£','Ḇ'=>'Ḇ','ḇ'=>'ḇ','Ḉ'=>'ÇÌ','ḉ'=>'çÌ','Ḋ'=>'Ḋ','ḋ'=>'ḋ','Ḍ'=>'DÌ£','á¸'=>'dÌ£','Ḏ'=>'Ḏ','á¸'=>'ḏ','á¸'=>'Ḑ','ḑ'=>'ḑ','Ḓ'=>'DÌ','ḓ'=>'dÌ','Ḕ'=>'Ḕ','ḕ'=>'ḕ','Ḗ'=>'EÌ„Ì','ḗ'=>'eÌ„Ì','Ḙ'=>'EÌ','ḙ'=>'eÌ','Ḛ'=>'Ḛ','ḛ'=>'ḛ','Ḝ'=>'Ḝ','á¸'=>'ḝ','Ḟ'=>'Ḟ','ḟ'=>'ḟ','Ḡ'=>'GÌ„','ḡ'=>'gÌ„','Ḣ'=>'Ḣ','ḣ'=>'ḣ','Ḥ'=>'HÌ£','ḥ'=>'hÌ£','Ḧ'=>'Ḧ','ḧ'=>'ḧ','Ḩ'=>'Ḩ','ḩ'=>'ḩ','Ḫ'=>'HÌ®','ḫ'=>'hÌ®','Ḭ'=>'Ḭ','á¸'=>'ḭ','Ḯ'=>'ÏÌ','ḯ'=>'ïÌ','Ḱ'=>'KÌ','ḱ'=>'kÌ','Ḳ'=>'KÌ£','ḳ'=>'kÌ£','Ḵ'=>'Ḵ','ḵ'=>'ḵ','Ḷ'=>'LÌ£','ḷ'=>'lÌ£','Ḹ'=>'Ḹ','ḹ'=>'ḹ','Ḻ'=>'Ḻ','ḻ'=>'ḻ','Ḽ'=>'LÌ','ḽ'=>'lÌ','Ḿ'=>'MÌ','ḿ'=>'mÌ','á¹€'=>'Ṁ','á¹'=>'ṁ','Ṃ'=>'MÌ£','ṃ'=>'mÌ£','Ṅ'=>'Ṅ','á¹…'=>'ṅ','Ṇ'=>'NÌ£','ṇ'=>'nÌ£','Ṉ'=>'Ṉ','ṉ'=>'ṉ','Ṋ'=>'NÌ','ṋ'=>'nÌ','Ṍ'=>'ÕÌ','á¹'=>'õÌ','Ṏ'=>'Ṏ','á¹'=>'ṏ','á¹'=>'Ṑ','ṑ'=>'ṑ','á¹’'=>'OÌ„Ì','ṓ'=>'oÌ„Ì','á¹”'=>'PÌ','ṕ'=>'pÌ','á¹–'=>'Ṗ','á¹—'=>'ṗ','Ṙ'=>'Ṙ','á¹™'=>'ṙ','Ṛ'=>'RÌ£','á¹›'=>'rÌ£','Ṝ'=>'Ṝ','á¹'=>'ṝ','Ṟ'=>'Ṟ','ṟ'=>'ṟ','á¹ '=>'Ṡ','ṡ'=>'ṡ','á¹¢'=>'SÌ£','á¹£'=>'sÌ£','Ṥ'=>'SÌ̇','á¹¥'=>'sÌ̇','Ṧ'=>'Ṧ','á¹§'=>'ṧ','Ṩ'=>'Ṩ','ṩ'=>'ṩ','Ṫ'=>'Ṫ','ṫ'=>'ṫ','Ṭ'=>'TÌ£','á¹'=>'tÌ£','á¹®'=>'Ṯ','ṯ'=>'ṯ','á¹°'=>'TÌ','á¹±'=>'tÌ','á¹²'=>'Ṳ','á¹³'=>'ṳ','á¹´'=>'Ṵ','á¹µ'=>'ṵ','á¹¶'=>'UÌ','á¹·'=>'uÌ','Ṹ'=>'ŨÌ','á¹¹'=>'ũÌ','Ṻ'=>'Ṻ','á¹»'=>'ṻ','á¹¼'=>'Ṽ','á¹½'=>'ṽ','á¹¾'=>'VÌ£','ṿ'=>'vÌ£','Ẁ'=>'WÌ€','áº'=>'wÌ€','Ẃ'=>'WÌ','ẃ'=>'wÌ','Ẅ'=>'Ẅ','ẅ'=>'ẅ','Ẇ'=>'Ẇ','ẇ'=>'ẇ','Ẉ'=>'WÌ£','ẉ'=>'wÌ£','Ẋ'=>'Ẋ','ẋ'=>'ẋ','Ẍ'=>'Ẍ','áº'=>'ẍ','Ẏ'=>'Ẏ','áº'=>'ẏ','áº'=>'ZÌ‚','ẑ'=>'zÌ‚','Ẓ'=>'ZÌ£','ẓ'=>'zÌ£','Ẕ'=>'Ẕ','ẕ'=>'ẕ','ẖ'=>'ẖ','ẗ'=>'ẗ','ẘ'=>'wÌŠ','ẙ'=>'yÌŠ','ẛ'=>'ẛ','Ạ'=>'AÌ£','ạ'=>'aÌ£','Ả'=>'Ả','ả'=>'ả','Ấ'=>'AÌ‚Ì','ấ'=>'aÌ‚Ì','Ầ'=>'Ầ','ầ'=>'ầ','Ẩ'=>'Ẩ','ẩ'=>'ẩ','Ẫ'=>'Ẫ','ẫ'=>'ẫ','Ậ'=>'Ậ','áº'=>'ậ','Ắ'=>'ĂÌ','ắ'=>'ăÌ','Ằ'=>'Ằ','ằ'=>'ằ','Ẳ'=>'Ẳ','ẳ'=>'ẳ','Ẵ'=>'Ẵ','ẵ'=>'ẵ','Ặ'=>'Ặ','ặ'=>'ặ','Ẹ'=>'EÌ£','ẹ'=>'eÌ£','Ẻ'=>'Ẻ','ẻ'=>'ẻ','Ẽ'=>'Ẽ','ẽ'=>'ẽ','Ế'=>'EÌ‚Ì','ế'=>'eÌ‚Ì','Ề'=>'Ề','á»'=>'ề','Ể'=>'Ể','ể'=>'ể','Ễ'=>'Ễ','á»…'=>'ễ','Ệ'=>'Ệ','ệ'=>'ệ','Ỉ'=>'Ỉ','ỉ'=>'ỉ','Ị'=>'IÌ£','ị'=>'iÌ£','Ọ'=>'OÌ£','á»'=>'oÌ£','Ỏ'=>'Ỏ','á»'=>'ỏ','á»'=>'OÌ‚Ì','ố'=>'oÌ‚Ì','á»’'=>'Ồ','ồ'=>'ồ','á»”'=>'Ổ','ổ'=>'ổ','á»–'=>'Ỗ','á»—'=>'ỗ','Ộ'=>'Ộ','á»™'=>'ộ','Ớ'=>'OÌ›Ì','á»›'=>'oÌ›Ì','Ờ'=>'Ờ','á»'=>'ờ','Ở'=>'Ở','ở'=>'ở','á» '=>'Ỡ','ỡ'=>'ỡ','Ợ'=>'Ợ','ợ'=>'ợ','Ụ'=>'UÌ£','ụ'=>'uÌ£','Ủ'=>'Ủ','á»§'=>'ủ','Ứ'=>'UÌ›Ì','ứ'=>'uÌ›Ì','Ừ'=>'Ừ','ừ'=>'ừ','Ử'=>'Ử','á»'=>'ử','á»®'=>'Ữ','ữ'=>'ữ','á»°'=>'Ự','á»±'=>'ự','Ỳ'=>'YÌ€','ỳ'=>'yÌ€','á»´'=>'YÌ£','ỵ'=>'yÌ£','á»¶'=>'Ỷ','á»·'=>'ỷ','Ỹ'=>'Ỹ','ỹ'=>'ỹ','á¼€'=>'ἀ','á¼'=>'ἁ','ἂ'=>'ἂ','ἃ'=>'ἃ','ἄ'=>'ἀÌ','á¼…'=>'ἁÌ','ἆ'=>'ἆ','ἇ'=>'ἇ','Ἀ'=>'Ἀ','Ἁ'=>'Ἁ','Ἂ'=>'Ἂ','Ἃ'=>'Ἃ','Ἄ'=>'ἈÌ','á¼'=>'ἉÌ','Ἆ'=>'Ἆ','á¼'=>'Ἇ','á¼'=>'ἐ','ἑ'=>'ἑ','á¼’'=>'ἒ','ἓ'=>'ἓ','á¼”'=>'ἐÌ','ἕ'=>'ἑÌ','Ἐ'=>'Ἐ','á¼™'=>'Ἑ','Ἒ'=>'Ἒ','á¼›'=>'Ἓ','Ἔ'=>'ἘÌ','á¼'=>'ἙÌ','á¼ '=>'ἠ','ἡ'=>'ἡ','á¼¢'=>'ἢ','á¼£'=>'ἣ','ἤ'=>'ἠÌ','á¼¥'=>'ἡÌ','ἦ'=>'ἦ','á¼§'=>'ἧ','Ἠ'=>'Ἠ','Ἡ'=>'Ἡ','Ἢ'=>'Ἢ','Ἣ'=>'Ἣ','Ἤ'=>'ἨÌ','á¼'=>'ἩÌ','á¼®'=>'Ἦ','Ἧ'=>'Ἧ','á¼°'=>'ἰ','á¼±'=>'ἱ','á¼²'=>'ἲ','á¼³'=>'ἳ','á¼´'=>'ἰÌ','á¼µ'=>'ἱÌ','á¼¶'=>'ἶ','á¼·'=>'ἷ','Ἰ'=>'Ἰ','á¼¹'=>'Ἱ','Ἲ'=>'Ἲ','á¼»'=>'Ἳ','á¼¼'=>'ἸÌ','á¼½'=>'ἹÌ','á¼¾'=>'Ἶ','Ἷ'=>'Ἷ','á½€'=>'ὀ','á½'=>'ὁ','ὂ'=>'ὂ','ὃ'=>'ὃ','ὄ'=>'ὀÌ','á½…'=>'ὁÌ','Ὀ'=>'Ὀ','Ὁ'=>'Ὁ','Ὂ'=>'Ὂ','Ὃ'=>'Ὃ','Ὄ'=>'ὈÌ','á½'=>'ὉÌ','á½'=>'Ï…Ì“','ὑ'=>'Ï…Ì”','á½’'=>'ὒ','ὓ'=>'ὓ','á½”'=>'Ï…Ì“Ì','ὕ'=>'Ï…Ì”Ì','á½–'=>'ὖ','á½—'=>'ὗ','á½™'=>'Ὑ','á½›'=>'Ὓ','á½'=>'ὙÌ','Ὗ'=>'Ὗ','á½ '=>'ὠ','ὡ'=>'ὡ','á½¢'=>'ὢ','á½£'=>'ὣ','ὤ'=>'ὠÌ','á½¥'=>'ὡÌ','ὦ'=>'ὦ','á½§'=>'ὧ','Ὠ'=>'Ὠ','Ὡ'=>'Ὡ','Ὢ'=>'Ὢ','Ὣ'=>'Ὣ','Ὤ'=>'ὨÌ','á½'=>'ὩÌ','á½®'=>'Ὦ','Ὧ'=>'Ὧ','á½°'=>'ὰ','á½±'=>'αÌ','á½²'=>'ὲ','á½³'=>'εÌ','á½´'=>'ὴ','á½µ'=>'ηÌ','á½¶'=>'ὶ','á½·'=>'ιÌ','ὸ'=>'ὸ','á½¹'=>'οÌ','ὺ'=>'Ï…Ì€','á½»'=>'Ï…Ì','á½¼'=>'ὼ','á½½'=>'ωÌ','á¾€'=>'ᾀ','á¾'=>'ᾁ','ᾂ'=>'ᾂ','ᾃ'=>'ᾃ','ᾄ'=>'ἀÌÍ…','á¾…'=>'ἁÌÍ…','ᾆ'=>'ᾆ','ᾇ'=>'ᾇ','ᾈ'=>'ᾈ','ᾉ'=>'ᾉ','ᾊ'=>'ᾊ','ᾋ'=>'ᾋ','ᾌ'=>'ἈÌÍ…','á¾'=>'ἉÌÍ…','ᾎ'=>'ᾎ','á¾'=>'ᾏ','á¾'=>'ᾐ','ᾑ'=>'ᾑ','á¾’'=>'ᾒ','ᾓ'=>'ᾓ','á¾”'=>'ἠÌÍ…','ᾕ'=>'ἡÌÍ…','á¾–'=>'ᾖ','á¾—'=>'ᾗ','ᾘ'=>'ᾘ','á¾™'=>'ᾙ','ᾚ'=>'ᾚ','á¾›'=>'ᾛ','ᾜ'=>'ἨÌÍ…','á¾'=>'ἩÌÍ…','ᾞ'=>'ᾞ','ᾟ'=>'ᾟ','á¾ '=>'ᾠ','ᾡ'=>'ᾡ','á¾¢'=>'ᾢ','á¾£'=>'ᾣ','ᾤ'=>'ὠÌÍ…','á¾¥'=>'ὡÌÍ…','ᾦ'=>'ᾦ','á¾§'=>'ᾧ','ᾨ'=>'ᾨ','ᾩ'=>'ᾩ','ᾪ'=>'ᾪ','ᾫ'=>'ᾫ','ᾬ'=>'ὨÌÍ…','á¾'=>'ὩÌÍ…','á¾®'=>'ᾮ','ᾯ'=>'ᾯ','á¾°'=>'ᾰ','á¾±'=>'ᾱ','á¾²'=>'ᾲ','á¾³'=>'ᾳ','á¾´'=>'αÌÍ…','á¾¶'=>'ᾶ','á¾·'=>'ᾷ','Ᾰ'=>'Ᾰ','á¾¹'=>'Ᾱ','Ὰ'=>'Ὰ','á¾»'=>'ΑÌ','á¾¼'=>'ᾼ','á¾¾'=>'ι','á¿'=>'῁','á¿‚'=>'ῂ','ῃ'=>'ῃ','á¿„'=>'ηÌÍ…','ῆ'=>'ῆ','ῇ'=>'ῇ','Ὲ'=>'Ὲ','Έ'=>'ΕÌ','Ὴ'=>'Ὴ','á¿‹'=>'ΗÌ','ῌ'=>'ῌ','á¿'=>'῍','῎'=>'᾿Ì','á¿'=>'῏','á¿'=>'ῐ','á¿‘'=>'ῑ','á¿’'=>'ῒ','á¿“'=>'ϊÌ','á¿–'=>'ῖ','á¿—'=>'ῗ','Ῐ'=>'Ῐ','á¿™'=>'Ῑ','Ὶ'=>'Ὶ','á¿›'=>'ΙÌ','á¿'=>'῝','῞'=>'῾Ì','῟'=>'῟','á¿ '=>'ῠ','á¿¡'=>'Ï…Ì„','á¿¢'=>'ῢ','á¿£'=>'ϋÌ','ῤ'=>'ÏÌ“','á¿¥'=>'ÏÌ”','ῦ'=>'Ï…Í‚','á¿§'=>'ῧ','Ῠ'=>'Ῠ','á¿©'=>'Ῡ','Ὺ'=>'Ὺ','á¿«'=>'Î¥Ì','Ῥ'=>'Ῥ','á¿'=>'῭','á¿®'=>'¨Ì','`'=>'`','ῲ'=>'ῲ','ῳ'=>'ῳ','á¿´'=>'ωÌÍ…','á¿¶'=>'ῶ','á¿·'=>'ῷ','Ὸ'=>'Ὸ','Ό'=>'ΟÌ','Ὼ'=>'Ὼ','á¿»'=>'ΩÌ','ῼ'=>'ῼ','´'=>'´',' '=>' ','â€'=>' ','Ω'=>'Ω','K'=>'K','â„«'=>'AÌŠ','↚'=>'â†Ì¸','↛'=>'↛','↮'=>'↮','â‡'=>'â‡Ì¸','⇎'=>'⇎','â‡'=>'⇏','∄'=>'∄','∉'=>'∉','∌'=>'∌','∤'=>'∤','∦'=>'∦','â‰'=>'≁','≄'=>'≄','≇'=>'≇','≉'=>'≉','≠'=>'≠','≢'=>'≢','â‰'=>'â‰Ì¸','≮'=>'≮','≯'=>'≯','≰'=>'≰','≱'=>'≱','≴'=>'≴','≵'=>'≵','≸'=>'≸','≹'=>'≹','⊀'=>'⊀','âŠ'=>'⊁','⊄'=>'⊄','⊅'=>'⊅','⊈'=>'⊈','⊉'=>'⊉','⊬'=>'⊬','âŠ'=>'⊭','⊮'=>'⊮','⊯'=>'⊯','â‹ '=>'⋠','â‹¡'=>'⋡','â‹¢'=>'⋢','â‹£'=>'⋣','⋪'=>'⋪','â‹«'=>'⋫','⋬'=>'⋬','â‹'=>'⋭','〈'=>'〈','〉'=>'〉','⫝̸'=>'â«Ì¸','ãŒ'=>'ã‹ã‚™','ãŽ'=>'ãã‚™','ã'=>'ãã‚™','ã’'=>'ã‘ã‚™','ã”'=>'ã“ã‚™','ã–'=>'ã•ã‚™','ã˜'=>'ã—ã‚™','ãš'=>'ã™ã‚™','ãœ'=>'ã›ã‚™','ãž'=>'ãã‚™','ã '=>'ãŸã‚™','ã¢'=>'ã¡ã‚™','ã¥'=>'ã¤ã‚™','ã§'=>'ã¦ã‚™','ã©'=>'ã¨ã‚™','ã°'=>'ã¯ã‚™','ã±'=>'ã¯ã‚š','ã³'=>'ã²ã‚™','ã´'=>'ã²ã‚š','ã¶'=>'ãµã‚™','ã·'=>'ãµã‚š','ã¹'=>'ã¸ã‚™','ãº'=>'ã¸ã‚š','ã¼'=>'ã»ã‚™','ã½'=>'ã»ã‚š','ã‚”'=>'ã†ã‚™','ゞ'=>'ã‚ã‚™','ガ'=>'ã‚«ã‚™','ã‚®'=>'ã‚ã‚™','ã‚°'=>'グ','ゲ'=>'ゲ','ã‚´'=>'ゴ','ã‚¶'=>'ザ','ジ'=>'ã‚·ã‚™','ズ'=>'ズ','ゼ'=>'ゼ','ゾ'=>'ゾ','ダ'=>'ã‚¿ã‚™','ヂ'=>'ãƒã‚™','ヅ'=>'ヅ','デ'=>'デ','ド'=>'ド','ãƒ'=>'ãƒã‚™','パ'=>'ãƒã‚š','ビ'=>'ビ','ピ'=>'ピ','ブ'=>'ブ','プ'=>'プ','ベ'=>'ベ','ペ'=>'ペ','ボ'=>'ボ','ãƒ'=>'ポ','ヴ'=>'ヴ','ヷ'=>'ヷ','ヸ'=>'ヸ','ヹ'=>'ヹ','ヺ'=>'ヺ','ヾ'=>'ヾ','豈'=>'豈','ï¤'=>'æ›´','車'=>'車','賈'=>'賈','滑'=>'滑','串'=>'串','句'=>'å¥','龜'=>'龜','龜'=>'龜','契'=>'契','金'=>'金','喇'=>'å–‡','奈'=>'奈','ï¤'=>'懶','癩'=>'癩','ï¤'=>'ç¾…','ï¤'=>'蘿','螺'=>'螺','裸'=>'裸','邏'=>'é‚','樂'=>'樂','洛'=>'æ´›','烙'=>'烙','珞'=>'çž','落'=>'è½','酪'=>'é…ª','駱'=>'é§±','亂'=>'亂','卵'=>'åµ','ï¤'=>'欄','爛'=>'爛','蘭'=>'è˜','ï¤ '=>'鸞','嵐'=>'åµ','濫'=>'æ¿«','藍'=>'è—','襤'=>'襤','拉'=>'拉','臘'=>'臘','蠟'=>'è Ÿ','廊'=>'廊','朗'=>'朗','浪'=>'浪','狼'=>'狼','郎'=>'郎','ï¤'=>'來','冷'=>'冷','勞'=>'勞','擄'=>'æ“„','櫓'=>'æ«“','爐'=>'çˆ','盧'=>'ç›§','老'=>'è€','蘆'=>'蘆','虜'=>'虜','路'=>'è·¯','露'=>'露','魯'=>'é¯','鷺'=>'é·º','碌'=>'碌','祿'=>'祿','綠'=>'ç¶ ','菉'=>'è‰','錄'=>'錄','鹿'=>'鹿','ï¥'=>'è«–','壟'=>'壟','弄'=>'弄','籠'=>'ç± ','聾'=>'è¾','牢'=>'牢','磊'=>'磊','賂'=>'賂','雷'=>'é›·','壘'=>'壘','屢'=>'å±¢','樓'=>'樓','ï¥'=>'æ·š','漏'=>'æ¼','ï¥'=>'ç´¯','ï¥'=>'縷','陋'=>'陋','勒'=>'å‹’','肋'=>'è‚‹','凜'=>'凜','凌'=>'凌','稜'=>'稜','綾'=>'ç¶¾','菱'=>'è±','陵'=>'陵','讀'=>'讀','拏'=>'æ‹','樂'=>'樂','ï¥'=>'諾','丹'=>'丹','寧'=>'寧','ï¥ '=>'怒','率'=>'率','異'=>'ç•°','北'=>'北','磻'=>'磻','便'=>'便','復'=>'復','不'=>'ä¸','泌'=>'泌','數'=>'數','索'=>'ç´¢','參'=>'åƒ','塞'=>'塞','ï¥'=>'çœ','葉'=>'葉','說'=>'說','殺'=>'殺','辰'=>'è¾°','沈'=>'沈','拾'=>'拾','若'=>'è‹¥','掠'=>'æŽ ','略'=>'ç•¥','亮'=>'亮','兩'=>'å…©','凉'=>'凉','梁'=>'æ¢','糧'=>'ç³§','良'=>'良','諒'=>'è«’','量'=>'é‡','勵'=>'勵','呂'=>'å‘‚','ï¦'=>'女','廬'=>'廬','旅'=>'æ—…','濾'=>'濾','礪'=>'礪','閭'=>'é–','驪'=>'驪','麗'=>'麗','黎'=>'黎','力'=>'力','曆'=>'曆','歷'=>'æ·','ï¦'=>'è½¢','年'=>'å¹´','ï¦'=>'æ†','ï¦'=>'戀','撚'=>'æ’š','漣'=>'æ¼£','煉'=>'ç…‰','璉'=>'ç’‰','秊'=>'ç§Š','練'=>'ç·´','聯'=>'è¯','輦'=>'輦','蓮'=>'è“®','連'=>'連','鍊'=>'éŠ','列'=>'列','ï¦'=>'劣','咽'=>'å’½','烈'=>'烈','ï¦ '=>'裂','說'=>'說','廉'=>'廉','念'=>'念','捻'=>'æ»','殮'=>'æ®®','簾'=>'ç°¾','獵'=>'çµ','令'=>'令','囹'=>'囹','寧'=>'寧','嶺'=>'嶺','怜'=>'怜','ï¦'=>'玲','瑩'=>'ç‘©','羚'=>'羚','聆'=>'è†','鈴'=>'鈴','零'=>'é›¶','靈'=>'éˆ','領'=>'é ˜','例'=>'例','禮'=>'禮','醴'=>'醴','隸'=>'隸','惡'=>'惡','了'=>'了','僚'=>'僚','寮'=>'寮','尿'=>'å°¿','料'=>'æ–™','樂'=>'樂','ï§€'=>'燎','ï§'=>'療','ï§‚'=>'蓼','遼'=>'é¼','ï§„'=>'é¾','ï§…'=>'暈','阮'=>'阮','劉'=>'劉','杻'=>'æ»','柳'=>'柳','ï§Š'=>'æµ','ï§‹'=>'溜','ï§Œ'=>'ç‰','ï§'=>'ç•™','ï§Ž'=>'ç¡«','ï§'=>'ç´','ï§'=>'類','ï§‘'=>'å…','ï§’'=>'戮','ï§“'=>'陸','ï§”'=>'倫','ï§•'=>'å´™','ï§–'=>'æ·ª','ï§—'=>'輪','律'=>'律','ï§™'=>'æ…„','ï§š'=>'æ —','ï§›'=>'率','ï§œ'=>'隆','ï§'=>'利','ï§ž'=>'å','ï§Ÿ'=>'å±¥','ï§ '=>'易','ï§¡'=>'æŽ','ï§¢'=>'梨','ï§£'=>'æ³¥','理'=>'ç†','ï§¥'=>'ç—¢','罹'=>'ç½¹','ï§§'=>'è£','裡'=>'裡','ï§©'=>'里','離'=>'離','ï§«'=>'匿','溺'=>'溺','ï§'=>'å','ï§®'=>'ç‡','璘'=>'ç’˜','ï§°'=>'è—º','ï§±'=>'隣','ï§²'=>'é±—','ï§³'=>'麟','ï§´'=>'æž—','ï§µ'=>'æ·‹','ï§¶'=>'臨','ï§·'=>'ç«‹','笠'=>'ç¬ ','ï§¹'=>'ç²’','狀'=>'ç‹€','ï§»'=>'ç‚™','ï§¼'=>'è˜','ï§½'=>'什','ï§¾'=>'茶','ï§¿'=>'刺','切'=>'切','ï¨'=>'度','拓'=>'æ‹“','糖'=>'ç³–','宅'=>'å®…','洞'=>'æ´ž','暴'=>'æš´','輻'=>'è¼»','行'=>'行','降'=>'é™','見'=>'見','廓'=>'廓','兀'=>'å…€','ï¨'=>'å—€','ï¨'=>'塚','晴'=>'æ™´','凞'=>'凞','猪'=>'猪','益'=>'益','礼'=>'礼','神'=>'神','祥'=>'祥','福'=>'ç¦','靖'=>'é–','ï¨'=>'ç²¾','羽'=>'ç¾½','ï¨ '=>'蘒','諸'=>'諸','逸'=>'逸','都'=>'都','飯'=>'飯','飼'=>'飼','館'=>'館','ï¨'=>'é¶´','侮'=>'ä¾®','僧'=>'僧','免'=>'å…','勉'=>'勉','勤'=>'勤','卑'=>'å‘','喝'=>'å–','嘆'=>'嘆','器'=>'器','塀'=>'å¡€','墨'=>'墨','層'=>'層','屮'=>'å±®','悔'=>'æ‚”','慨'=>'æ…¨','憎'=>'憎','ï©€'=>'懲','ï©'=>'æ•','ï©‚'=>'æ—¢','暑'=>'æš‘','ï©„'=>'梅','ï©…'=>'æµ·','渚'=>'渚','漢'=>'æ¼¢','煮'=>'ç…®','爫'=>'爫','琢'=>'ç¢','ï©‹'=>'碑','社'=>'社','ï©'=>'祉','祈'=>'祈','ï©'=>'ç¥','ï©'=>'祖','ï©‘'=>'ç¥','ï©’'=>'ç¦','ï©“'=>'禎','ï©”'=>'ç©€','ï©•'=>'çª','ï©–'=>'節','ï©—'=>'ç·´','縉'=>'縉','ï©™'=>'ç¹','署'=>'ç½²','ï©›'=>'者','臭'=>'è‡','ï©'=>'艹','艹'=>'艹','著'=>'è‘—','ï© '=>'è¤','ï©¡'=>'視','ï©¢'=>'è¬','ï©£'=>'謹','賓'=>'賓','ï©¥'=>'è´ˆ','辶'=>'è¾¶','ï©§'=>'逸','難'=>'難','ï©©'=>'響','頻'=>'é »','ï©°'=>'並','况'=>'况','全'=>'å…¨','侀'=>'ä¾€','ï©´'=>'å……','冀'=>'冀','ï©¶'=>'勇','ï©·'=>'勺','喝'=>'å–','啕'=>'å••','喙'=>'å–™','ï©»'=>'å—¢','塚'=>'塚','墳'=>'墳','奄'=>'奄','ï©¿'=>'奔','婢'=>'å©¢','ïª'=>'嬨','廒'=>'å»’','廙'=>'å»™','彩'=>'彩','徭'=>'å¾','惘'=>'惘','慎'=>'æ…Ž','愈'=>'愈','憎'=>'憎','慠'=>'æ… ','懲'=>'懲','戴'=>'戴','ïª'=>'æ„','搜'=>'æœ','ïª'=>'æ‘’','ïª'=>'æ•–','晴'=>'æ™´','朗'=>'朗','望'=>'望','杖'=>'æ–','歹'=>'æ¹','殺'=>'殺','流'=>'æµ','滛'=>'æ»›','滋'=>'滋','漢'=>'æ¼¢','瀞'=>'瀞','煮'=>'ç…®','ïª'=>'çž§','爵'=>'爵','犯'=>'犯','ïª '=>'猪','瑱'=>'瑱','甆'=>'甆','画'=>'ç”»','瘝'=>'ç˜','瘟'=>'瘟','益'=>'益','盛'=>'ç››','直'=>'ç›´','睊'=>'çŠ','着'=>'ç€','磌'=>'磌','窱'=>'窱','ïª'=>'節','类'=>'ç±»','絛'=>'çµ›','練'=>'ç·´','缾'=>'ç¼¾','者'=>'者','荒'=>'è’','華'=>'è¯','蝹'=>'è¹','襁'=>'è¥','覆'=>'覆','視'=>'視','調'=>'調','諸'=>'諸','請'=>'è«‹','謁'=>'è¬','諾'=>'諾','諭'=>'è«','謹'=>'謹','ï«€'=>'變','ï«'=>'è´ˆ','ï«‚'=>'輸','遲'=>'é²','ï«„'=>'醙','ï«…'=>'鉶','陼'=>'陼','難'=>'難','靖'=>'é–','韛'=>'韛','響'=>'響','ï«‹'=>'é ‹','頻'=>'é »','ï«'=>'鬒','龜'=>'龜','ï«'=>'𢡊','ï«'=>'𢡄','ï«‘'=>'ð£•','ï«’'=>'ã®','ï«“'=>'䀘','ï«”'=>'䀹','ï«•'=>'𥉉','ï«–'=>'ð¥³','ï«—'=>'𧻓','齃'=>'齃','ï«™'=>'龎','ï¬'=>'×™Ö´','ײַ'=>'ײַ','שׁ'=>'ש×','שׂ'=>'שׂ','שּׁ'=>'שּ×','ï¬'=>'שּׂ','אַ'=>'×Ö·','אָ'=>'×Ö¸','אּ'=>'×Ö¼','בּ'=>'בּ','גּ'=>'×’Ö¼','דּ'=>'דּ','הּ'=>'×”Ö¼','וּ'=>'וּ','זּ'=>'×–Ö¼','טּ'=>'טּ','יּ'=>'×™Ö¼','ךּ'=>'ךּ','כּ'=>'×›Ö¼','לּ'=>'לּ','מּ'=>'מּ','ï€'=>'× Ö¼','ï'=>'סּ','ïƒ'=>'×£Ö¼','ï„'=>'פּ','ï†'=>'צּ','ï‡'=>'×§Ö¼','ïˆ'=>'רּ','ï‰'=>'שּ','ïŠ'=>'תּ','ï‹'=>'וֹ','ïŒ'=>'בֿ','ï'=>'×›Ö¿','ïŽ'=>'פֿ','ð…ž'=>'ð…—ð…¥','ð…Ÿ'=>'ð…˜ð…¥','ð… '=>'ð…˜ð…¥ð…®','ð…¡'=>'ð…˜ð…¥ð…¯','ð…¢'=>'ð…˜ð…¥ð…°','ð…£'=>'ð…˜ð…¥ð…±','ð…¤'=>'ð…˜ð…¥ð…²','ð†»'=>'ð†¹ð…¥','ð†¼'=>'ð†ºð…¥','ð†½'=>'ð†¹ð…¥ð…®','ð†¾'=>'ð†ºð…¥ð…®','ð†¿'=>'ð†¹ð…¥ð…¯','ð‡€'=>'ð†ºð…¥ð…¯','丽'=>'丽','ð¯ '=>'丸','乁'=>'ä¹','𠄢'=>'ð „¢','你'=>'ä½ ','侮'=>'ä¾®','侻'=>'ä¾»','倂'=>'倂','偺'=>'åº','備'=>'å‚™','僧'=>'僧','像'=>'åƒ','㒞'=>'ã’ž','ð¯ '=>'𠘺','免'=>'å…','ð¯ '=>'å…”','ð¯ '=>'å…¤','具'=>'å…·','𠔜'=>'𠔜','㒹'=>'ã’¹','內'=>'å…§','再'=>'å†','𠕋'=>'ð •‹','冗'=>'冗','冤'=>'冤','仌'=>'仌','冬'=>'冬','况'=>'况','𩇟'=>'𩇟','ð¯ '=>'凵','刃'=>'刃','㓟'=>'㓟','ð¯ '=>'刻','剆'=>'剆','割'=>'割','剷'=>'剷','㔕'=>'㔕','勇'=>'勇','勉'=>'勉','勤'=>'勤','勺'=>'勺','包'=>'包','匆'=>'匆','北'=>'北','卉'=>'å‰','ð¯ '=>'å‘','博'=>'åš','即'=>'å³','卽'=>'å½','卿'=>'å¿','卿'=>'å¿','卿'=>'å¿','𠨬'=>'𠨬','灰'=>'ç°','及'=>'åŠ','叟'=>'åŸ','𠭣'=>'ð £','叫'=>'å«','叱'=>'å±','吆'=>'å†','咞'=>'å’ž','吸'=>'å¸','呈'=>'呈','周'=>'周','咢'=>'å’¢','ð¯¡'=>'å“¶','唐'=>'å”','啓'=>'å•“','啣'=>'å•£','善'=>'å–„','善'=>'å–„','喙'=>'å–™','喫'=>'å–«','喳'=>'å–³','嗂'=>'å—‚','圖'=>'圖','嘆'=>'嘆','ð¯¡'=>'圗','噑'=>'噑','ð¯¡'=>'å™´','ð¯¡'=>'切','壮'=>'壮','城'=>'城','埴'=>'埴','堍'=>'å ','型'=>'åž‹','堲'=>'å ²','報'=>'å ±','墬'=>'墬','𡓤'=>'𡓤','売'=>'売','壷'=>'壷','夆'=>'夆','ð¯¡'=>'多','夢'=>'夢','奢'=>'奢','𡚨'=>'𡚨','𡛪'=>'𡛪','姬'=>'姬','娛'=>'娛','娧'=>'娧','姘'=>'姘','婦'=>'婦','㛮'=>'ã›®','㛼'=>'㛼','嬈'=>'嬈','嬾'=>'嬾','嬾'=>'嬾','𡧈'=>'𡧈','ð¯¡'=>'寃','寘'=>'寘','寧'=>'寧','寳'=>'寳','𡬘'=>'𡬘','寿'=>'寿','将'=>'å°†','当'=>'当','尢'=>'å°¢','㞁'=>'ãž','屠'=>'å± ','屮'=>'å±®','峀'=>'å³€','岍'=>'å²','𡷤'=>'ð¡·¤','嵃'=>'嵃','𡷦'=>'ð¡·¦','嵮'=>'åµ®','嵫'=>'嵫','嵼'=>'åµ¼','ð¯¢'=>'å·¡','巢'=>'å·¢','㠯'=>'ã ¯','巽'=>'å·½','帨'=>'帨','帽'=>'帽','幩'=>'幩','㡢'=>'ã¡¢','𢆃'=>'𢆃','㡼'=>'㡼','庰'=>'庰','庳'=>'庳','ð¯¢'=>'庶','廊'=>'廊','ð¯¢'=>'𪎒','ð¯¢'=>'廾','𢌱'=>'𢌱','𢌱'=>'𢌱','舁'=>'èˆ','弢'=>'å¼¢','弢'=>'å¼¢','㣇'=>'㣇','𣊸'=>'𣊸','𦇚'=>'𦇚','形'=>'å½¢','彫'=>'彫','㣣'=>'㣣','徚'=>'徚','ð¯¢'=>'å¿','志'=>'å¿—','忹'=>'忹','悁'=>'æ‚','㤺'=>'㤺','㤜'=>'㤜','悔'=>'æ‚”','𢛔'=>'𢛔','惇'=>'惇','慈'=>'æ…ˆ','慌'=>'æ…Œ','慎'=>'æ…Ž','慌'=>'æ…Œ','慺'=>'æ…º','憎'=>'憎','憲'=>'憲','ð¯¢'=>'憤','憯'=>'憯','懞'=>'懞','懲'=>'懲','懶'=>'懶','成'=>'æˆ','戛'=>'戛','扝'=>'æ‰','抱'=>'抱','拔'=>'æ‹”','捐'=>'æ','𢬌'=>'𢬌','挽'=>'挽','拼'=>'拼','捨'=>'æ¨','掃'=>'掃','揤'=>'æ¤','𢯱'=>'𢯱','搢'=>'æ¢','揅'=>'æ…','ð¯£'=>'掩','㨮'=>'㨮','摩'=>'æ‘©','摾'=>'摾','撝'=>'æ’','摷'=>'æ‘·','㩬'=>'㩬','敏'=>'æ•','敬'=>'敬','𣀊'=>'𣀊','旣'=>'æ—£','書'=>'書','ð¯£'=>'晉','㬙'=>'㬙','ð¯£'=>'æš‘','ð¯£'=>'㬈','㫤'=>'㫤','冒'=>'冒','冕'=>'冕','最'=>'最','暜'=>'æšœ','肭'=>'è‚','䏙'=>'ä™','朗'=>'朗','望'=>'望','朡'=>'朡','杞'=>'æž','杓'=>'æ“','ð¯£'=>'ð£ƒ','㭉'=>'ã‰','柺'=>'柺','枅'=>'æž…','桒'=>'æ¡’','梅'=>'梅','𣑭'=>'ð£‘','梎'=>'梎','栟'=>'æ Ÿ','椔'=>'椔','㮝'=>'ã®','楂'=>'楂','榣'=>'榣','槪'=>'槪','檨'=>'檨','𣚣'=>'𣚣','ð¯£'=>'æ«›','㰘'=>'ã°˜','次'=>'次','𣢧'=>'𣢧','歔'=>'æ”','㱎'=>'㱎','歲'=>'æ²','殟'=>'殟','殺'=>'殺','殻'=>'æ®»','𣪍'=>'ð£ª','𡴋'=>'ð¡´‹','𣫺'=>'𣫺','汎'=>'汎','𣲼'=>'𣲼','沿'=>'沿','泍'=>'æ³','汧'=>'æ±§','洖'=>'æ´–','派'=>'æ´¾','ð¯¤'=>'æµ·','流'=>'æµ','浩'=>'浩','浸'=>'浸','涅'=>'æ¶…','𣴞'=>'𣴞','洴'=>'æ´´','港'=>'港','湮'=>'æ¹®','㴳'=>'ã´³','滋'=>'滋','滇'=>'滇','ð¯¤'=>'𣻑','淹'=>'æ·¹','ð¯¤'=>'æ½®','ð¯¤'=>'𣽞','𣾎'=>'𣾎','濆'=>'濆','瀹'=>'瀹','瀞'=>'瀞','瀛'=>'瀛','㶖'=>'ã¶–','灊'=>'çŠ','災'=>'ç½','灷'=>'ç·','炭'=>'ç‚','𠔥'=>'𠔥','煅'=>'ç……','ð¯¤'=>'𤉣','熜'=>'熜','𤎫'=>'𤎫','爨'=>'爨','爵'=>'爵','牐'=>'ç‰','𤘈'=>'𤘈','犀'=>'犀','犕'=>'犕','𤜵'=>'𤜵','𤠔'=>'𤠔','獺'=>'çº','王'=>'王','㺬'=>'㺬','玥'=>'玥','㺸'=>'㺸','ð¯¤'=>'㺸','瑇'=>'瑇','瑜'=>'瑜','瑱'=>'瑱','璅'=>'ç’…','瓊'=>'瓊','㼛'=>'ã¼›','甤'=>'甤','𤰶'=>'𤰶','甾'=>'甾','𤲒'=>'𤲒','異'=>'ç•°','𢆟'=>'𢆟','瘐'=>'ç˜','𤾡'=>'𤾡','𤾸'=>'𤾸','𥁄'=>'ð¥„','㿼'=>'㿼','䀈'=>'䀈','直'=>'ç›´','ð¯¥'=>'𥃳','𥃲'=>'𥃲','𥄙'=>'𥄙','𥄳'=>'𥄳','眞'=>'眞','真'=>'真','真'=>'真','睊'=>'çŠ','䀹'=>'䀹','瞋'=>'çž‹','䁆'=>'ä†','䂖'=>'ä‚–','ð¯¥'=>'ð¥','硎'=>'硎','ð¯¥'=>'碌','ð¯¥'=>'磌','䃣'=>'䃣','𥘦'=>'𥘦','祖'=>'祖','𥚚'=>'𥚚','𥛅'=>'𥛅','福'=>'ç¦','秫'=>'ç§«','䄯'=>'䄯','穀'=>'ç©€','穊'=>'穊','穏'=>'ç©','𥥼'=>'𥥼','ð¯¥'=>'𥪧','𥪧'=>'𥪧','竮'=>'ç«®','䈂'=>'䈂','𥮫'=>'𥮫','篆'=>'篆','築'=>'築','䈧'=>'䈧','𥲀'=>'𥲀','糒'=>'ç³’','䊠'=>'äŠ ','糨'=>'糨','糣'=>'ç³£','紀'=>'ç´€','𥾆'=>'𥾆','絣'=>'çµ£','ð¯¥'=>'äŒ','緇'=>'ç·‡','縂'=>'縂','繅'=>'ç¹…','䌴'=>'䌴','𦈨'=>'𦈨','𦉇'=>'𦉇','䍙'=>'ä™','𦋙'=>'𦋙','罺'=>'罺','𦌾'=>'𦌾','羕'=>'羕','翺'=>'翺','者'=>'者','𦓚'=>'𦓚','𦔣'=>'𦔣','聠'=>'è ','𦖨'=>'𦖨','聰'=>'è°','𣍟'=>'ð£Ÿ','ð¯¦'=>'ä•','育'=>'育','脃'=>'脃','䐋'=>'ä‹','脾'=>'脾','媵'=>'媵','𦞧'=>'𦞧','𦞵'=>'𦞵','𣎓'=>'𣎓','𣎜'=>'𣎜','舁'=>'èˆ','舄'=>'舄','ð¯¦'=>'辞','䑫'=>'ä‘«','ð¯¦'=>'芑','ð¯¦'=>'芋','芝'=>'èŠ','劳'=>'劳','花'=>'花','芳'=>'芳','芽'=>'芽','苦'=>'苦','𦬼'=>'𦬼','若'=>'è‹¥','茝'=>'èŒ','荣'=>'è£','莭'=>'èŽ','茣'=>'茣','ð¯¦'=>'莽','菧'=>'è§','著'=>'è‘—','荓'=>'è“','菊'=>'èŠ','菌'=>'èŒ','菜'=>'èœ','𦰶'=>'𦰶','𦵫'=>'𦵫','𦳕'=>'𦳕','䔫'=>'䔫','蓱'=>'蓱','蓳'=>'蓳','蔖'=>'è”–','𧏊'=>'ð§Š','蕤'=>'蕤','ð¯¦'=>'𦼬','䕝'=>'ä•','䕡'=>'ä•¡','𦾱'=>'𦾱','𧃒'=>'𧃒','䕫'=>'ä•«','虐'=>'è™','虜'=>'虜','虧'=>'è™§','虩'=>'虩','蚩'=>'èš©','蚈'=>'蚈','蜎'=>'蜎','蛢'=>'蛢','蝹'=>'è¹','蜨'=>'蜨','蝫'=>'è«','螆'=>'螆','䗗'=>'ä——','蟡'=>'蟡','ð¯§'=>'è ','䗹'=>'ä—¹','衠'=>'è¡ ','衣'=>'è¡£','𧙧'=>'ð§™§','裗'=>'裗','裞'=>'裞','䘵'=>'䘵','裺'=>'裺','㒻'=>'ã’»','𧢮'=>'ð§¢®','𧥦'=>'𧥦','ð¯§'=>'äš¾','䛇'=>'䛇','ð¯§'=>'èª ','ð¯§'=>'è«','變'=>'變','豕'=>'豕','𧲨'=>'𧲨','貫'=>'貫','賁'=>'è³','贛'=>'è´›','起'=>'èµ·','𧼯'=>'𧼯','𠠄'=>'ð „','跋'=>'è·‹','趼'=>'è¶¼','跰'=>'è·°','ð¯§'=>'𠣞','軔'=>'è»”','輸'=>'輸','𨗒'=>'𨗒','𨗭'=>'ð¨—','邔'=>'é‚”','郱'=>'郱','鄑'=>'é„‘','𨜮'=>'𨜮','鄛'=>'é„›','鈸'=>'鈸','鋗'=>'é‹—','鋘'=>'鋘','鉼'=>'鉼','鏹'=>'é¹','鐕'=>'é•','ð¯§'=>'𨯺','開'=>'é–‹','䦕'=>'䦕','閷'=>'é–·','𨵷'=>'𨵷','䧦'=>'䧦','雃'=>'雃','嶲'=>'å¶²','霣'=>'霣','𩅅'=>'ð©……','𩈚'=>'𩈚','䩮'=>'ä©®','䩶'=>'ä©¶','韠'=>'éŸ ','𩐊'=>'ð©Š','䪲'=>'䪲','𩒖'=>'ð©’–','頋'=>'é ‹','頋'=>'é ‹','頩'=>'é ©','ð¯¨'=>'ð©–¶','飢'=>'飢','䬳'=>'䬳','餩'=>'餩','馧'=>'馧','駂'=>'é§‚','駾'=>'é§¾','䯎'=>'䯎','𩬰'=>'𩬰','鬒'=>'鬒','鱀'=>'é±€','鳽'=>'é³½','ð¯¨'=>'䳎','䳭'=>'ä³','ð¯¨'=>'éµ§','ð¯¨'=>'𪃎','䳸'=>'䳸','𪄅'=>'𪄅','𪈎'=>'𪈎','𪊑'=>'𪊑','麻'=>'麻','䵖'=>'äµ–','黹'=>'黹','黾'=>'黾','鼅'=>'é¼…','鼏'=>'é¼','鼖'=>'é¼–','鼻'=>'é¼»','ð¯¨'=>'𪘀');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/utf_compatibility_decomp.php b/phpBB/includes/utf/data/utf_compatibility_decomp.php deleted file mode 100644 index 08a7a047a4..0000000000 --- a/phpBB/includes/utf/data/utf_compatibility_decomp.php +++ /dev/null @@ -1,2 +0,0 @@ -<?php -$GLOBALS['utf_compatibility_decomp']=array(' '=>' ','¨'=>' ̈','ª'=>'a','¯'=>' Ì„','²'=>'2','³'=>'3','´'=>' Ì','µ'=>'μ','¸'=>' ̧','¹'=>'1','º'=>'o','¼'=>'1â„4','½'=>'1â„2','¾'=>'3â„4','À'=>'AÌ€','Ã'=>'AÌ','Â'=>'AÌ‚','Ã'=>'Ã','Ä'=>'Ä','Ã…'=>'AÌŠ','Ç'=>'Ç','È'=>'EÌ€','É'=>'EÌ','Ê'=>'EÌ‚','Ë'=>'Ë','ÃŒ'=>'IÌ€','Ã'=>'IÌ','ÃŽ'=>'IÌ‚','Ã'=>'Ï','Ñ'=>'Ñ','Ã’'=>'OÌ€','Ó'=>'OÌ','Ô'=>'OÌ‚','Õ'=>'Õ','Ö'=>'Ö','Ù'=>'UÌ€','Ú'=>'UÌ','Û'=>'UÌ‚','Ü'=>'Ü','Ã'=>'YÌ','à '=>'aÌ€','á'=>'aÌ','â'=>'aÌ‚','ã'=>'ã','ä'=>'ä','Ã¥'=>'aÌŠ','ç'=>'ç','è'=>'eÌ€','é'=>'eÌ','ê'=>'eÌ‚','ë'=>'ë','ì'=>'iÌ€','Ã'=>'iÌ','î'=>'iÌ‚','ï'=>'ï','ñ'=>'ñ','ò'=>'oÌ€','ó'=>'oÌ','ô'=>'oÌ‚','õ'=>'õ','ö'=>'ö','ù'=>'uÌ€','ú'=>'uÌ','û'=>'uÌ‚','ü'=>'ü','ý'=>'yÌ','ÿ'=>'ÿ','Ä€'=>'AÌ„','Ä'=>'aÌ„','Ä‚'=>'Ă','ă'=>'ă','Ä„'=>'Ą','Ä…'=>'ą','Ć'=>'CÌ','ć'=>'cÌ','Ĉ'=>'CÌ‚','ĉ'=>'cÌ‚','ÄŠ'=>'Ċ','Ä‹'=>'ċ','ÄŒ'=>'CÌŒ','Ä'=>'cÌŒ','ÄŽ'=>'DÌŒ','Ä'=>'dÌŒ','Ä’'=>'EÌ„','Ä“'=>'eÌ„','Ä”'=>'Ĕ','Ä•'=>'ĕ','Ä–'=>'Ė','Ä—'=>'ė','Ę'=>'Ę','Ä™'=>'ę','Äš'=>'EÌŒ','Ä›'=>'eÌŒ','Äœ'=>'GÌ‚','Ä'=>'gÌ‚','Äž'=>'Ğ','ÄŸ'=>'ğ','Ä '=>'Ġ','Ä¡'=>'ġ','Ä¢'=>'Ģ','Ä£'=>'ģ','Ĥ'=>'HÌ‚','Ä¥'=>'hÌ‚','Ĩ'=>'Ĩ','Ä©'=>'ĩ','Ī'=>'IÌ„','Ä«'=>'iÌ„','Ĭ'=>'Ĭ','Ä'=>'ĭ','Ä®'=>'Į','į'=>'į','İ'=>'İ','IJ'=>'IJ','ij'=>'ij','Ä´'=>'JÌ‚','ĵ'=>'jÌ‚','Ķ'=>'Ķ','Ä·'=>'ķ','Ĺ'=>'LÌ','ĺ'=>'lÌ','Ä»'=>'Ļ','ļ'=>'ļ','Ľ'=>'LÌŒ','ľ'=>'lÌŒ','Ä¿'=>'L·','Å€'=>'l·','Ń'=>'NÌ','Å„'=>'nÌ','Å…'=>'Ņ','ņ'=>'ņ','Ň'=>'NÌŒ','ň'=>'nÌŒ','ʼn'=>'ʼn','ÅŒ'=>'OÌ„','Å'=>'oÌ„','ÅŽ'=>'Ŏ','Å'=>'ŏ','Å'=>'OÌ‹','Å‘'=>'oÌ‹','Å”'=>'RÌ','Å•'=>'rÌ','Å–'=>'Ŗ','Å—'=>'ŗ','Ř'=>'RÌŒ','Å™'=>'rÌŒ','Åš'=>'SÌ','Å›'=>'sÌ','Åœ'=>'SÌ‚','Å'=>'sÌ‚','Åž'=>'Ş','ÅŸ'=>'ş','Å '=>'SÌŒ','Å¡'=>'sÌŒ','Å¢'=>'Ţ','Å£'=>'ţ','Ť'=>'TÌŒ','Å¥'=>'tÌŒ','Ũ'=>'Ũ','Å©'=>'ũ','Ū'=>'UÌ„','Å«'=>'uÌ„','Ŭ'=>'Ŭ','Å'=>'ŭ','Å®'=>'UÌŠ','ů'=>'uÌŠ','Ű'=>'UÌ‹','ű'=>'uÌ‹','Ų'=>'Ų','ų'=>'ų','Å´'=>'WÌ‚','ŵ'=>'wÌ‚','Ŷ'=>'YÌ‚','Å·'=>'yÌ‚','Ÿ'=>'Ÿ','Ź'=>'ZÌ','ź'=>'zÌ','Å»'=>'Ż','ż'=>'ż','Ž'=>'ZÌŒ','ž'=>'zÌŒ','Å¿'=>'s','Æ '=>'OÌ›','Æ¡'=>'oÌ›','Ư'=>'UÌ›','ư'=>'uÌ›','Ç„'=>'DZÌŒ','Ç…'=>'DzÌŒ','dž'=>'dzÌŒ','LJ'=>'LJ','Lj'=>'Lj','lj'=>'lj','ÇŠ'=>'NJ','Ç‹'=>'Nj','ÇŒ'=>'nj','Ç'=>'AÌŒ','ÇŽ'=>'aÌŒ','Ç'=>'IÌŒ','Ç'=>'iÌŒ','Ç‘'=>'OÌŒ','Ç’'=>'oÌŒ','Ç“'=>'UÌŒ','Ç”'=>'uÌŒ','Ç•'=>'Ǖ','Ç–'=>'ǖ','Ç—'=>'ÜÌ','ǘ'=>'üÌ','Ç™'=>'Ǚ','Çš'=>'ǚ','Ç›'=>'Ǜ','Çœ'=>'ǜ','Çž'=>'Ǟ','ÇŸ'=>'ǟ','Ç '=>'Ǡ','Ç¡'=>'ǡ','Ç¢'=>'Ǣ','Ç£'=>'ǣ','Ǧ'=>'GÌŒ','ǧ'=>'gÌŒ','Ǩ'=>'KÌŒ','Ç©'=>'kÌŒ','Ǫ'=>'Ǫ','Ç«'=>'ǫ','Ǭ'=>'Ǭ','Ç'=>'ǭ','Ç®'=>'Æ·ÌŒ','ǯ'=>'Ê’ÌŒ','ǰ'=>'jÌŒ','DZ'=>'DZ','Dz'=>'Dz','dz'=>'dz','Ç´'=>'GÌ','ǵ'=>'gÌ','Ǹ'=>'NÌ€','ǹ'=>'nÌ€','Ǻ'=>'AÌŠÌ','Ç»'=>'aÌŠÌ','Ǽ'=>'ÆÌ','ǽ'=>'æÌ','Ǿ'=>'ØÌ','Ç¿'=>'øÌ','È€'=>'AÌ','È'=>'aÌ','È‚'=>'AÌ‘','ȃ'=>'aÌ‘','È„'=>'EÌ','È…'=>'eÌ','Ȇ'=>'EÌ‘','ȇ'=>'eÌ‘','Ȉ'=>'IÌ','ȉ'=>'iÌ','ÈŠ'=>'IÌ‘','È‹'=>'iÌ‘','ÈŒ'=>'OÌ','È'=>'oÌ','ÈŽ'=>'OÌ‘','È'=>'oÌ‘','È'=>'RÌ','È‘'=>'rÌ','È’'=>'RÌ‘','È“'=>'rÌ‘','È”'=>'UÌ','È•'=>'uÌ','È–'=>'UÌ‘','È—'=>'uÌ‘','Ș'=>'Ș','È™'=>'ș','Èš'=>'Ț','È›'=>'ț','Èž'=>'HÌŒ','ÈŸ'=>'hÌŒ','Ȧ'=>'Ȧ','ȧ'=>'ȧ','Ȩ'=>'Ȩ','È©'=>'ȩ','Ȫ'=>'Ȫ','È«'=>'ȫ','Ȭ'=>'Ȭ','È'=>'ȭ','È®'=>'Ȯ','ȯ'=>'ȯ','Ȱ'=>'Ȱ','ȱ'=>'ȱ','Ȳ'=>'YÌ„','ȳ'=>'yÌ„','ʰ'=>'h','ʱ'=>'ɦ','ʲ'=>'j','ʳ'=>'r','Ê´'=>'ɹ','ʵ'=>'É»','ʶ'=>'Ê','Ê·'=>'w','ʸ'=>'y','˘'=>' ̆','Ë™'=>' ̇','Ëš'=>' ÌŠ','Ë›'=>' ̨','Ëœ'=>' ̃','Ë'=>' Ì‹','Ë '=>'É£','Ë¡'=>'l','Ë¢'=>'s','Ë£'=>'x','ˤ'=>'Ê•','Í€'=>'Ì€','Í'=>'Ì','̓'=>'Ì“','Í„'=>'̈Ì','Í´'=>'ʹ','ͺ'=>' Í…',';'=>';','΄'=>' Ì','Î…'=>' ̈Ì','Ά'=>'ΑÌ','·'=>'·','Έ'=>'ΕÌ','Ή'=>'ΗÌ','Ί'=>'ΙÌ','ÎŒ'=>'ΟÌ','ÎŽ'=>'Î¥Ì','Î'=>'ΩÌ','Î'=>'ϊÌ','Ϊ'=>'Ϊ','Ϋ'=>'Ϋ','ά'=>'αÌ','Î'=>'εÌ','ή'=>'ηÌ','ί'=>'ιÌ','ΰ'=>'ϋÌ','ÏŠ'=>'ϊ','Ï‹'=>'ϋ','ÏŒ'=>'οÌ','Ï'=>'Ï…Ì','ÏŽ'=>'ωÌ','Ï'=>'β','Ï‘'=>'θ','Ï’'=>'Î¥','Ï“'=>'Î¥Ì','Ï”'=>'Ϋ','Ï•'=>'φ','Ï–'=>'Ï€','ϰ'=>'κ','ϱ'=>'Ï','ϲ'=>'Ï‚','Ï´'=>'Θ','ϵ'=>'ε','Ϲ'=>'Σ','Ѐ'=>'Ѐ','Ð'=>'Ё','Ѓ'=>'ГÌ','Ї'=>'Ї','ÐŒ'=>'КÌ','Ð'=>'Ѝ','ÐŽ'=>'Ў','Й'=>'Й','й'=>'й','Ñ'=>'ѐ','Ñ‘'=>'ё','Ñ“'=>'гÌ','Ñ—'=>'ї','Ñœ'=>'кÌ','Ñ'=>'ѝ','Ñž'=>'ў','Ѷ'=>'Ñ´Ì','Ñ·'=>'ѵÌ','Ó'=>'Ӂ','Ó‚'=>'ӂ','Ó'=>'Ð̆','Ó‘'=>'ӑ','Ó’'=>'Ð̈','Ó“'=>'ӓ','Ó–'=>'Ӗ','Ó—'=>'ӗ','Óš'=>'Ӛ','Ó›'=>'ӛ','Óœ'=>'Ӝ','Ó'=>'ӝ','Óž'=>'Ӟ','ÓŸ'=>'ӟ','Ó¢'=>'Ӣ','Ó£'=>'ӣ','Ó¤'=>'Ӥ','Ó¥'=>'ӥ','Ó¦'=>'Ӧ','Ó§'=>'ӧ','Óª'=>'Ӫ','Ó«'=>'ӫ','Ó¬'=>'Ð̈','Ó'=>'Ñ̈','Ó®'=>'Ӯ','Ó¯'=>'ӯ','Ó°'=>'Ӱ','Ó±'=>'ӱ','Ó²'=>'Ӳ','Ó³'=>'ӳ','Ó´'=>'Ӵ','Óµ'=>'ӵ','Ó¸'=>'Ӹ','Ó¹'=>'ӹ','Ö‡'=>'Õ¥Ö‚','Ø¢'=>'آ','Ø£'=>'أ','ؤ'=>'ÙˆÙ”','Ø¥'=>'إ','ئ'=>'ÙŠÙ”','Ùµ'=>'اٴ','Ù¶'=>'وٴ','Ù·'=>'Û‡Ù´','Ù¸'=>'يٴ','Û€'=>'Û•Ù”','Û‚'=>'ÛÙ”','Û“'=>'Û’Ù”','ऩ'=>'ऩ','ऱ'=>'ऱ','ऴ'=>'ऴ','क़'=>'क़','ख़'=>'ख़','ग़'=>'ग़','ज़'=>'ज़','ड़'=>'ड़','à¥'=>'ढ़','फ़'=>'फ़','य़'=>'य़','à§‹'=>'ো','à§Œ'=>'ৌ','à§œ'=>'ড়','à§'=>'ঢ়','à§Ÿ'=>'য়','ਲ਼'=>'ਲ਼','ਸ਼'=>'ਸ਼','à©™'=>'ਖ਼','ਗ਼'=>'ਗ਼','à©›'=>'ਜ਼','ਫ਼'=>'ਫ਼','àˆ'=>'à‡à–','à‹'=>'à‡à¬¾','àŒ'=>'à‡à—','àœ'=>'ଡ଼','à'=>'ଢ଼','à®”'=>'ஔ','ொ'=>'ொ','ோ'=>'ோ','ௌ'=>'ௌ','ై'=>'ై','à³€'=>'ೀ','ೇ'=>'ೇ','ೈ'=>'ೈ','ೊ'=>'ೊ','ೋ'=>'ೋ','ൊ'=>'ൊ','ോ'=>'ോ','ൌ'=>'ൌ','à·š'=>'ේ','à·œ'=>'à·™à·','à·'=>'à·™à·à·Š','à·ž'=>'ෞ','ำ'=>'à¹à¸²','ຳ'=>'à»àº²','ໜ'=>'ຫນ','à»'=>'ຫມ','༌'=>'་','གྷ'=>'གྷ','à½'=>'ཌྷ','དྷ'=>'དྷ','བྷ'=>'བྷ','ཛྷ'=>'ཛྷ','ཀྵ'=>'ཀྵ','ཱི'=>'ཱི','ཱུ'=>'ཱུ','ྲྀ'=>'ྲྀ','ཷ'=>'ྲཱྀ','ླྀ'=>'ླྀ','ཹ'=>'ླཱྀ','à¾'=>'ཱྀ','ྒྷ'=>'ྒྷ','à¾'=>'ྜྷ','ྡྷ'=>'ྡྷ','ྦྷ'=>'ྦྷ','ྫྷ'=>'ྫྷ','ྐྵ'=>'à¾à¾µ','ဦ'=>'ဦ','ჼ'=>'ნ','ᬆ'=>'ᬆ','ᬈ'=>'ᬈ','ᬊ'=>'ᬊ','ᬌ'=>'ᬌ','ᬎ'=>'á¬á¬µ','ᬒ'=>'ᬒ','ᬻ'=>'ᬻ','ᬽ'=>'ᬽ','á€'=>'ᭀ','á'=>'ᭁ','áƒ'=>'á‚ᬵ','á´¬'=>'A','á´'=>'Æ','á´®'=>'B','á´°'=>'D','á´±'=>'E','á´²'=>'ÆŽ','á´³'=>'G','á´´'=>'H','á´µ'=>'I','á´¶'=>'J','á´·'=>'K','á´¸'=>'L','á´¹'=>'M','á´º'=>'N','á´¼'=>'O','á´½'=>'È¢','á´¾'=>'P','á´¿'=>'R','áµ€'=>'T','áµ'=>'U','ᵂ'=>'W','ᵃ'=>'a','ᵄ'=>'É','áµ…'=>'É‘','ᵆ'=>'á´‚','ᵇ'=>'b','ᵈ'=>'d','ᵉ'=>'e','ᵊ'=>'É™','ᵋ'=>'É›','ᵌ'=>'Éœ','áµ'=>'g','áµ'=>'k','áµ'=>'m','ᵑ'=>'Å‹','áµ’'=>'o','ᵓ'=>'É”','áµ”'=>'á´–','ᵕ'=>'á´—','áµ–'=>'p','áµ—'=>'t','ᵘ'=>'u','áµ™'=>'á´','ᵚ'=>'ɯ','áµ›'=>'v','ᵜ'=>'á´¥','áµ'=>'β','ᵞ'=>'γ','ᵟ'=>'δ','áµ '=>'φ','ᵡ'=>'χ','áµ¢'=>'i','áµ£'=>'r','ᵤ'=>'u','áµ¥'=>'v','ᵦ'=>'β','áµ§'=>'γ','ᵨ'=>'Ï','ᵩ'=>'φ','ᵪ'=>'χ','ᵸ'=>'н','á¶›'=>'É’','á¶œ'=>'c','á¶'=>'É•','á¶ž'=>'ð','á¶Ÿ'=>'Éœ','á¶ '=>'f','á¶¡'=>'ÉŸ','á¶¢'=>'É¡','á¶£'=>'É¥','ᶤ'=>'ɨ','á¶¥'=>'É©','ᶦ'=>'ɪ','á¶§'=>'áµ»','ᶨ'=>'Ê','á¶©'=>'É','ᶪ'=>'á¶…','á¶«'=>'ÊŸ','ᶬ'=>'ɱ','á¶'=>'ɰ','á¶®'=>'ɲ','ᶯ'=>'ɳ','á¶°'=>'É´','á¶±'=>'ɵ','á¶²'=>'ɸ','á¶³'=>'Ê‚','á¶´'=>'ʃ','á¶µ'=>'Æ«','á¶¶'=>'ʉ','á¶·'=>'ÊŠ','ᶸ'=>'á´œ','á¶¹'=>'Ê‹','ᶺ'=>'ÊŒ','á¶»'=>'z','á¶¼'=>'Ê','á¶½'=>'Ê‘','á¶¾'=>'Ê’','á¶¿'=>'θ','Ḁ'=>'AÌ¥','á¸'=>'aÌ¥','Ḃ'=>'Ḃ','ḃ'=>'ḃ','Ḅ'=>'BÌ£','ḅ'=>'bÌ£','Ḇ'=>'Ḇ','ḇ'=>'ḇ','Ḉ'=>'ÇÌ','ḉ'=>'çÌ','Ḋ'=>'Ḋ','ḋ'=>'ḋ','Ḍ'=>'DÌ£','á¸'=>'dÌ£','Ḏ'=>'Ḏ','á¸'=>'ḏ','á¸'=>'Ḑ','ḑ'=>'ḑ','Ḓ'=>'DÌ','ḓ'=>'dÌ','Ḕ'=>'Ḕ','ḕ'=>'ḕ','Ḗ'=>'EÌ„Ì','ḗ'=>'eÌ„Ì','Ḙ'=>'EÌ','ḙ'=>'eÌ','Ḛ'=>'Ḛ','ḛ'=>'ḛ','Ḝ'=>'Ḝ','á¸'=>'ḝ','Ḟ'=>'Ḟ','ḟ'=>'ḟ','Ḡ'=>'GÌ„','ḡ'=>'gÌ„','Ḣ'=>'Ḣ','ḣ'=>'ḣ','Ḥ'=>'HÌ£','ḥ'=>'hÌ£','Ḧ'=>'Ḧ','ḧ'=>'ḧ','Ḩ'=>'Ḩ','ḩ'=>'ḩ','Ḫ'=>'HÌ®','ḫ'=>'hÌ®','Ḭ'=>'Ḭ','á¸'=>'ḭ','Ḯ'=>'ÏÌ','ḯ'=>'ïÌ','Ḱ'=>'KÌ','ḱ'=>'kÌ','Ḳ'=>'KÌ£','ḳ'=>'kÌ£','Ḵ'=>'Ḵ','ḵ'=>'ḵ','Ḷ'=>'LÌ£','ḷ'=>'lÌ£','Ḹ'=>'Ḹ','ḹ'=>'ḹ','Ḻ'=>'Ḻ','ḻ'=>'ḻ','Ḽ'=>'LÌ','ḽ'=>'lÌ','Ḿ'=>'MÌ','ḿ'=>'mÌ','á¹€'=>'Ṁ','á¹'=>'ṁ','Ṃ'=>'MÌ£','ṃ'=>'mÌ£','Ṅ'=>'Ṅ','á¹…'=>'ṅ','Ṇ'=>'NÌ£','ṇ'=>'nÌ£','Ṉ'=>'Ṉ','ṉ'=>'ṉ','Ṋ'=>'NÌ','ṋ'=>'nÌ','Ṍ'=>'ÕÌ','á¹'=>'õÌ','Ṏ'=>'Ṏ','á¹'=>'ṏ','á¹'=>'Ṑ','ṑ'=>'ṑ','á¹’'=>'OÌ„Ì','ṓ'=>'oÌ„Ì','á¹”'=>'PÌ','ṕ'=>'pÌ','á¹–'=>'Ṗ','á¹—'=>'ṗ','Ṙ'=>'Ṙ','á¹™'=>'ṙ','Ṛ'=>'RÌ£','á¹›'=>'rÌ£','Ṝ'=>'Ṝ','á¹'=>'ṝ','Ṟ'=>'Ṟ','ṟ'=>'ṟ','á¹ '=>'Ṡ','ṡ'=>'ṡ','á¹¢'=>'SÌ£','á¹£'=>'sÌ£','Ṥ'=>'SÌ̇','á¹¥'=>'sÌ̇','Ṧ'=>'Ṧ','á¹§'=>'ṧ','Ṩ'=>'Ṩ','ṩ'=>'ṩ','Ṫ'=>'Ṫ','ṫ'=>'ṫ','Ṭ'=>'TÌ£','á¹'=>'tÌ£','á¹®'=>'Ṯ','ṯ'=>'ṯ','á¹°'=>'TÌ','á¹±'=>'tÌ','á¹²'=>'Ṳ','á¹³'=>'ṳ','á¹´'=>'Ṵ','á¹µ'=>'ṵ','á¹¶'=>'UÌ','á¹·'=>'uÌ','Ṹ'=>'ŨÌ','á¹¹'=>'ũÌ','Ṻ'=>'Ṻ','á¹»'=>'ṻ','á¹¼'=>'Ṽ','á¹½'=>'ṽ','á¹¾'=>'VÌ£','ṿ'=>'vÌ£','Ẁ'=>'WÌ€','áº'=>'wÌ€','Ẃ'=>'WÌ','ẃ'=>'wÌ','Ẅ'=>'Ẅ','ẅ'=>'ẅ','Ẇ'=>'Ẇ','ẇ'=>'ẇ','Ẉ'=>'WÌ£','ẉ'=>'wÌ£','Ẋ'=>'Ẋ','ẋ'=>'ẋ','Ẍ'=>'Ẍ','áº'=>'ẍ','Ẏ'=>'Ẏ','áº'=>'ẏ','áº'=>'ZÌ‚','ẑ'=>'zÌ‚','Ẓ'=>'ZÌ£','ẓ'=>'zÌ£','Ẕ'=>'Ẕ','ẕ'=>'ẕ','ẖ'=>'ẖ','ẗ'=>'ẗ','ẘ'=>'wÌŠ','ẙ'=>'yÌŠ','ẚ'=>'aʾ','ẛ'=>'ṡ','Ạ'=>'AÌ£','ạ'=>'aÌ£','Ả'=>'Ả','ả'=>'ả','Ấ'=>'AÌ‚Ì','ấ'=>'aÌ‚Ì','Ầ'=>'Ầ','ầ'=>'ầ','Ẩ'=>'Ẩ','ẩ'=>'ẩ','Ẫ'=>'Ẫ','ẫ'=>'ẫ','Ậ'=>'Ậ','áº'=>'ậ','Ắ'=>'ĂÌ','ắ'=>'ăÌ','Ằ'=>'Ằ','ằ'=>'ằ','Ẳ'=>'Ẳ','ẳ'=>'ẳ','Ẵ'=>'Ẵ','ẵ'=>'ẵ','Ặ'=>'Ặ','ặ'=>'ặ','Ẹ'=>'EÌ£','ẹ'=>'eÌ£','Ẻ'=>'Ẻ','ẻ'=>'ẻ','Ẽ'=>'Ẽ','ẽ'=>'ẽ','Ế'=>'EÌ‚Ì','ế'=>'eÌ‚Ì','Ề'=>'Ề','á»'=>'ề','Ể'=>'Ể','ể'=>'ể','Ễ'=>'Ễ','á»…'=>'ễ','Ệ'=>'Ệ','ệ'=>'ệ','Ỉ'=>'Ỉ','ỉ'=>'ỉ','Ị'=>'IÌ£','ị'=>'iÌ£','Ọ'=>'OÌ£','á»'=>'oÌ£','Ỏ'=>'Ỏ','á»'=>'ỏ','á»'=>'OÌ‚Ì','ố'=>'oÌ‚Ì','á»’'=>'Ồ','ồ'=>'ồ','á»”'=>'Ổ','ổ'=>'ổ','á»–'=>'Ỗ','á»—'=>'ỗ','Ộ'=>'Ộ','á»™'=>'ộ','Ớ'=>'OÌ›Ì','á»›'=>'oÌ›Ì','Ờ'=>'Ờ','á»'=>'ờ','Ở'=>'Ở','ở'=>'ở','á» '=>'Ỡ','ỡ'=>'ỡ','Ợ'=>'Ợ','ợ'=>'ợ','Ụ'=>'UÌ£','ụ'=>'uÌ£','Ủ'=>'Ủ','á»§'=>'ủ','Ứ'=>'UÌ›Ì','ứ'=>'uÌ›Ì','Ừ'=>'Ừ','ừ'=>'ừ','Ử'=>'Ử','á»'=>'ử','á»®'=>'Ữ','ữ'=>'ữ','á»°'=>'Ự','á»±'=>'ự','Ỳ'=>'YÌ€','ỳ'=>'yÌ€','á»´'=>'YÌ£','ỵ'=>'yÌ£','á»¶'=>'Ỷ','á»·'=>'ỷ','Ỹ'=>'Ỹ','ỹ'=>'ỹ','á¼€'=>'ἀ','á¼'=>'ἁ','ἂ'=>'ἂ','ἃ'=>'ἃ','ἄ'=>'ἀÌ','á¼…'=>'ἁÌ','ἆ'=>'ἆ','ἇ'=>'ἇ','Ἀ'=>'Ἀ','Ἁ'=>'Ἁ','Ἂ'=>'Ἂ','Ἃ'=>'Ἃ','Ἄ'=>'ἈÌ','á¼'=>'ἉÌ','Ἆ'=>'Ἆ','á¼'=>'Ἇ','á¼'=>'ἐ','ἑ'=>'ἑ','á¼’'=>'ἒ','ἓ'=>'ἓ','á¼”'=>'ἐÌ','ἕ'=>'ἑÌ','Ἐ'=>'Ἐ','á¼™'=>'Ἑ','Ἒ'=>'Ἒ','á¼›'=>'Ἓ','Ἔ'=>'ἘÌ','á¼'=>'ἙÌ','á¼ '=>'ἠ','ἡ'=>'ἡ','á¼¢'=>'ἢ','á¼£'=>'ἣ','ἤ'=>'ἠÌ','á¼¥'=>'ἡÌ','ἦ'=>'ἦ','á¼§'=>'ἧ','Ἠ'=>'Ἠ','Ἡ'=>'Ἡ','Ἢ'=>'Ἢ','Ἣ'=>'Ἣ','Ἤ'=>'ἨÌ','á¼'=>'ἩÌ','á¼®'=>'Ἦ','Ἧ'=>'Ἧ','á¼°'=>'ἰ','á¼±'=>'ἱ','á¼²'=>'ἲ','á¼³'=>'ἳ','á¼´'=>'ἰÌ','á¼µ'=>'ἱÌ','á¼¶'=>'ἶ','á¼·'=>'ἷ','Ἰ'=>'Ἰ','á¼¹'=>'Ἱ','Ἲ'=>'Ἲ','á¼»'=>'Ἳ','á¼¼'=>'ἸÌ','á¼½'=>'ἹÌ','á¼¾'=>'Ἶ','Ἷ'=>'Ἷ','á½€'=>'ὀ','á½'=>'ὁ','ὂ'=>'ὂ','ὃ'=>'ὃ','ὄ'=>'ὀÌ','á½…'=>'ὁÌ','Ὀ'=>'Ὀ','Ὁ'=>'Ὁ','Ὂ'=>'Ὂ','Ὃ'=>'Ὃ','Ὄ'=>'ὈÌ','á½'=>'ὉÌ','á½'=>'Ï…Ì“','ὑ'=>'Ï…Ì”','á½’'=>'ὒ','ὓ'=>'ὓ','á½”'=>'Ï…Ì“Ì','ὕ'=>'Ï…Ì”Ì','á½–'=>'ὖ','á½—'=>'ὗ','á½™'=>'Ὑ','á½›'=>'Ὓ','á½'=>'ὙÌ','Ὗ'=>'Ὗ','á½ '=>'ὠ','ὡ'=>'ὡ','á½¢'=>'ὢ','á½£'=>'ὣ','ὤ'=>'ὠÌ','á½¥'=>'ὡÌ','ὦ'=>'ὦ','á½§'=>'ὧ','Ὠ'=>'Ὠ','Ὡ'=>'Ὡ','Ὢ'=>'Ὢ','Ὣ'=>'Ὣ','Ὤ'=>'ὨÌ','á½'=>'ὩÌ','á½®'=>'Ὦ','Ὧ'=>'Ὧ','á½°'=>'ὰ','á½±'=>'αÌ','á½²'=>'ὲ','á½³'=>'εÌ','á½´'=>'ὴ','á½µ'=>'ηÌ','á½¶'=>'ὶ','á½·'=>'ιÌ','ὸ'=>'ὸ','á½¹'=>'οÌ','ὺ'=>'Ï…Ì€','á½»'=>'Ï…Ì','á½¼'=>'ὼ','á½½'=>'ωÌ','á¾€'=>'ᾀ','á¾'=>'ᾁ','ᾂ'=>'ᾂ','ᾃ'=>'ᾃ','ᾄ'=>'ἀÌÍ…','á¾…'=>'ἁÌÍ…','ᾆ'=>'ᾆ','ᾇ'=>'ᾇ','ᾈ'=>'ᾈ','ᾉ'=>'ᾉ','ᾊ'=>'ᾊ','ᾋ'=>'ᾋ','ᾌ'=>'ἈÌÍ…','á¾'=>'ἉÌÍ…','ᾎ'=>'ᾎ','á¾'=>'ᾏ','á¾'=>'ᾐ','ᾑ'=>'ᾑ','á¾’'=>'ᾒ','ᾓ'=>'ᾓ','á¾”'=>'ἠÌÍ…','ᾕ'=>'ἡÌÍ…','á¾–'=>'ᾖ','á¾—'=>'ᾗ','ᾘ'=>'ᾘ','á¾™'=>'ᾙ','ᾚ'=>'ᾚ','á¾›'=>'ᾛ','ᾜ'=>'ἨÌÍ…','á¾'=>'ἩÌÍ…','ᾞ'=>'ᾞ','ᾟ'=>'ᾟ','á¾ '=>'ᾠ','ᾡ'=>'ᾡ','á¾¢'=>'ᾢ','á¾£'=>'ᾣ','ᾤ'=>'ὠÌÍ…','á¾¥'=>'ὡÌÍ…','ᾦ'=>'ᾦ','á¾§'=>'ᾧ','ᾨ'=>'ᾨ','ᾩ'=>'ᾩ','ᾪ'=>'ᾪ','ᾫ'=>'ᾫ','ᾬ'=>'ὨÌÍ…','á¾'=>'ὩÌÍ…','á¾®'=>'ᾮ','ᾯ'=>'ᾯ','á¾°'=>'ᾰ','á¾±'=>'ᾱ','á¾²'=>'ᾲ','á¾³'=>'ᾳ','á¾´'=>'αÌÍ…','á¾¶'=>'ᾶ','á¾·'=>'ᾷ','Ᾰ'=>'Ᾰ','á¾¹'=>'Ᾱ','Ὰ'=>'Ὰ','á¾»'=>'ΑÌ','á¾¼'=>'ᾼ','á¾½'=>' Ì“','á¾¾'=>'ι','᾿'=>' Ì“','á¿€'=>' Í‚','á¿'=>' ̈͂','á¿‚'=>'ῂ','ῃ'=>'ῃ','á¿„'=>'ηÌÍ…','ῆ'=>'ῆ','ῇ'=>'ῇ','Ὲ'=>'Ὲ','Έ'=>'ΕÌ','Ὴ'=>'Ὴ','á¿‹'=>'ΗÌ','ῌ'=>'ῌ','á¿'=>' ̓̀','῎'=>' Ì“Ì','á¿'=>' ̓͂','á¿'=>'ῐ','á¿‘'=>'ῑ','á¿’'=>'ῒ','á¿“'=>'ϊÌ','á¿–'=>'ῖ','á¿—'=>'ῗ','Ῐ'=>'Ῐ','á¿™'=>'Ῑ','Ὶ'=>'Ὶ','á¿›'=>'ΙÌ','á¿'=>' ̔̀','῞'=>' Ì”Ì','῟'=>' ̔͂','á¿ '=>'ῠ','á¿¡'=>'Ï…Ì„','á¿¢'=>'ῢ','á¿£'=>'ϋÌ','ῤ'=>'ÏÌ“','á¿¥'=>'ÏÌ”','ῦ'=>'Ï…Í‚','á¿§'=>'ῧ','Ῠ'=>'Ῠ','á¿©'=>'Ῡ','Ὺ'=>'Ὺ','á¿«'=>'Î¥Ì','Ῥ'=>'Ῥ','á¿'=>' ̈̀','á¿®'=>' ̈Ì','`'=>'`','ῲ'=>'ῲ','ῳ'=>'ῳ','á¿´'=>'ωÌÍ…','á¿¶'=>'ῶ','á¿·'=>'ῷ','Ὸ'=>'Ὸ','Ό'=>'ΟÌ','Ὼ'=>'Ὼ','á¿»'=>'ΩÌ','ῼ'=>'ῼ','´'=>' Ì','῾'=>' Ì”',' '=>' ','â€'=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ',' '=>' ','‑'=>'â€','‗'=>' ̳','․'=>'.','‥'=>'..','…'=>'...',' '=>' ','″'=>'′′','‴'=>'′′′','‶'=>'‵‵','‷'=>'‵‵‵','‼'=>'!!','‾'=>' Ì…','â‡'=>'??','âˆ'=>'?!','â‰'=>'!?','â—'=>'′′′′','âŸ'=>' ','â°'=>'0','â±'=>'i','â´'=>'4','âµ'=>'5','â¶'=>'6','â·'=>'7','â¸'=>'8','â¹'=>'9','âº'=>'+','â»'=>'−','â¼'=>'=','â½'=>'(','â¾'=>')','â¿'=>'n','â‚€'=>'0','â‚'=>'1','â‚‚'=>'2','₃'=>'3','â‚„'=>'4','â‚…'=>'5','₆'=>'6','₇'=>'7','₈'=>'8','₉'=>'9','₊'=>'+','â‚‹'=>'−','₌'=>'=','â‚'=>'(','₎'=>')','â‚'=>'a','â‚‘'=>'e','â‚’'=>'o','â‚“'=>'x','â‚”'=>'É™','₨'=>'Rs','â„€'=>'a/c','â„'=>'a/s','â„‚'=>'C','℃'=>'°C','â„…'=>'c/o','℆'=>'c/u','ℇ'=>'Æ','℉'=>'°F','ℊ'=>'g','â„‹'=>'H','ℌ'=>'H','â„'=>'H','ℎ'=>'h','â„'=>'ħ','â„'=>'I','â„‘'=>'I','â„’'=>'L','â„“'=>'l','â„•'=>'N','â„–'=>'No','â„™'=>'P','ℚ'=>'Q','â„›'=>'R','ℜ'=>'R','â„'=>'R','â„ '=>'SM','â„¡'=>'TEL','â„¢'=>'TM','ℤ'=>'Z','Ω'=>'Ω','ℨ'=>'Z','K'=>'K','â„«'=>'AÌŠ','ℬ'=>'B','â„'=>'C','ℯ'=>'e','â„°'=>'E','ℱ'=>'F','ℳ'=>'M','â„´'=>'o','ℵ'=>'×','â„¶'=>'ב','â„·'=>'×’','ℸ'=>'ד','ℹ'=>'i','â„»'=>'FAX','ℼ'=>'Ï€','ℽ'=>'γ','ℾ'=>'Γ','â„¿'=>'Î ','â…€'=>'∑','â……'=>'D','â…†'=>'d','â…‡'=>'e','â…ˆ'=>'i','â…‰'=>'j','â…“'=>'1â„3','â…”'=>'2â„3','â…•'=>'1â„5','â…–'=>'2â„5','â…—'=>'3â„5','â…˜'=>'4â„5','â…™'=>'1â„6','â…š'=>'5â„6','â…›'=>'1â„8','â…œ'=>'3â„8','â…'=>'5â„8','â…ž'=>'7â„8','â…Ÿ'=>'1â„','â… '=>'I','â…¡'=>'II','â…¢'=>'III','â…£'=>'IV','â…¤'=>'V','â…¥'=>'VI','â…¦'=>'VII','â…§'=>'VIII','â…¨'=>'IX','â…©'=>'X','â…ª'=>'XI','â…«'=>'XII','â…¬'=>'L','â…'=>'C','â…®'=>'D','â…¯'=>'M','â…°'=>'i','â…±'=>'ii','â…²'=>'iii','â…³'=>'iv','â…´'=>'v','â…µ'=>'vi','â…¶'=>'vii','â…·'=>'viii','â…¸'=>'ix','â…¹'=>'x','â…º'=>'xi','â…»'=>'xii','â…¼'=>'l','â…½'=>'c','â…¾'=>'d','â…¿'=>'m','↚'=>'â†Ì¸','↛'=>'↛','↮'=>'↮','â‡'=>'â‡Ì¸','⇎'=>'⇎','â‡'=>'⇏','∄'=>'∄','∉'=>'∉','∌'=>'∌','∤'=>'∤','∦'=>'∦','∬'=>'∫∫','âˆ'=>'∫∫∫','∯'=>'∮∮','∰'=>'∮∮∮','â‰'=>'≁','≄'=>'≄','≇'=>'≇','≉'=>'≉','≠'=>'≠','≢'=>'≢','â‰'=>'â‰Ì¸','≮'=>'≮','≯'=>'≯','≰'=>'≰','≱'=>'≱','≴'=>'≴','≵'=>'≵','≸'=>'≸','≹'=>'≹','⊀'=>'⊀','âŠ'=>'⊁','⊄'=>'⊄','⊅'=>'⊅','⊈'=>'⊈','⊉'=>'⊉','⊬'=>'⊬','âŠ'=>'⊭','⊮'=>'⊮','⊯'=>'⊯','â‹ '=>'⋠','â‹¡'=>'⋡','â‹¢'=>'⋢','â‹£'=>'⋣','⋪'=>'⋪','â‹«'=>'⋫','⋬'=>'⋬','â‹'=>'⋭','〈'=>'〈','〉'=>'〉','â‘ '=>'1','â‘¡'=>'2','â‘¢'=>'3','â‘£'=>'4','⑤'=>'5','â‘¥'=>'6','⑦'=>'7','â‘§'=>'8','⑨'=>'9','â‘©'=>'10','⑪'=>'11','â‘«'=>'12','⑬'=>'13','â‘'=>'14','â‘®'=>'15','⑯'=>'16','â‘°'=>'17','⑱'=>'18','⑲'=>'19','⑳'=>'20','â‘´'=>'(1)','⑵'=>'(2)','â‘¶'=>'(3)','â‘·'=>'(4)','⑸'=>'(5)','⑹'=>'(6)','⑺'=>'(7)','â‘»'=>'(8)','⑼'=>'(9)','⑽'=>'(10)','⑾'=>'(11)','â‘¿'=>'(12)','â’€'=>'(13)','â’'=>'(14)','â’‚'=>'(15)','â’ƒ'=>'(16)','â’„'=>'(17)','â’…'=>'(18)','â’†'=>'(19)','â’‡'=>'(20)','â’ˆ'=>'1.','â’‰'=>'2.','â’Š'=>'3.','â’‹'=>'4.','â’Œ'=>'5.','â’'=>'6.','â’Ž'=>'7.','â’'=>'8.','â’'=>'9.','â’‘'=>'10.','â’’'=>'11.','â’“'=>'12.','â’”'=>'13.','â’•'=>'14.','â’–'=>'15.','â’—'=>'16.','â’˜'=>'17.','â’™'=>'18.','â’š'=>'19.','â’›'=>'20.','â’œ'=>'(a)','â’'=>'(b)','â’ž'=>'(c)','â’Ÿ'=>'(d)','â’ '=>'(e)','â’¡'=>'(f)','â’¢'=>'(g)','â’£'=>'(h)','â’¤'=>'(i)','â’¥'=>'(j)','â’¦'=>'(k)','â’§'=>'(l)','â’¨'=>'(m)','â’©'=>'(n)','â’ª'=>'(o)','â’«'=>'(p)','â’¬'=>'(q)','â’'=>'(r)','â’®'=>'(s)','â’¯'=>'(t)','â’°'=>'(u)','â’±'=>'(v)','â’²'=>'(w)','â’³'=>'(x)','â’´'=>'(y)','â’µ'=>'(z)','â’¶'=>'A','â’·'=>'B','â’¸'=>'C','â’¹'=>'D','â’º'=>'E','â’»'=>'F','â’¼'=>'G','â’½'=>'H','â’¾'=>'I','â’¿'=>'J','â“€'=>'K','â“'=>'L','â“‚'=>'M','Ⓝ'=>'N','â“„'=>'O','â“…'=>'P','Ⓠ'=>'Q','Ⓡ'=>'R','Ⓢ'=>'S','Ⓣ'=>'T','Ⓤ'=>'U','â“‹'=>'V','Ⓦ'=>'W','â“'=>'X','Ⓨ'=>'Y','â“'=>'Z','â“'=>'a','â“‘'=>'b','â“’'=>'c','â““'=>'d','â“”'=>'e','â“•'=>'f','â“–'=>'g','â“—'=>'h','ⓘ'=>'i','â“™'=>'j','ⓚ'=>'k','â“›'=>'l','ⓜ'=>'m','â“'=>'n','ⓞ'=>'o','ⓟ'=>'p','â“ '=>'q','â“¡'=>'r','â“¢'=>'s','â“£'=>'t','ⓤ'=>'u','â“¥'=>'v','ⓦ'=>'w','â“§'=>'x','ⓨ'=>'y','â“©'=>'z','⓪'=>'0','⨌'=>'∫∫∫∫','â©´'=>'::=','⩵'=>'==','â©¶'=>'===','⫝̸'=>'â«Ì¸','ⵯ'=>'ⵡ','⺟'=>'æ¯','⻳'=>'龟','â¼€'=>'一','â¼'=>'丨','⼂'=>'丶','⼃'=>'丿','⼄'=>'ä¹™','â¼…'=>'亅','⼆'=>'二','⼇'=>'äº ','⼈'=>'人','⼉'=>'å„¿','⼊'=>'å…¥','⼋'=>'å…«','⼌'=>'冂','â¼'=>'冖','⼎'=>'冫','â¼'=>'å‡ ','â¼'=>'凵','⼑'=>'刀','â¼’'=>'力','⼓'=>'勹','â¼”'=>'匕','⼕'=>'匚','â¼–'=>'匸','â¼—'=>'å','⼘'=>'åœ','â¼™'=>'å©','⼚'=>'厂','â¼›'=>'厶','⼜'=>'åˆ','â¼'=>'å£','⼞'=>'å›—','⼟'=>'土','â¼ '=>'士','⼡'=>'夂','â¼¢'=>'夊','â¼£'=>'夕','⼤'=>'大','â¼¥'=>'女','⼦'=>'å','â¼§'=>'宀','⼨'=>'寸','⼩'=>'å°','⼪'=>'å°¢','⼫'=>'å°¸','⼬'=>'å±®','â¼'=>'å±±','â¼®'=>'å·›','⼯'=>'å·¥','â¼°'=>'å·±','â¼±'=>'å·¾','â¼²'=>'å¹²','â¼³'=>'幺','â¼´'=>'广','â¼µ'=>'å»´','â¼¶'=>'廾','â¼·'=>'弋','⼸'=>'弓','â¼¹'=>'å½','⼺'=>'彡','â¼»'=>'å½³','â¼¼'=>'心','â¼½'=>'戈','â¼¾'=>'戶','⼿'=>'手','â½€'=>'支','â½'=>'æ”´','⽂'=>'æ–‡','⽃'=>'æ–—','⽄'=>'æ–¤','â½…'=>'æ–¹','⽆'=>'æ— ','⽇'=>'æ—¥','⽈'=>'æ›°','⽉'=>'月','⽊'=>'木','⽋'=>'æ¬ ','⽌'=>'æ¢','â½'=>'æ¹','⽎'=>'殳','â½'=>'毋','â½'=>'比','⽑'=>'毛','â½’'=>'æ°','⽓'=>'æ°”','â½”'=>'æ°´','⽕'=>'ç«','â½–'=>'爪','â½—'=>'父','⽘'=>'爻','â½™'=>'爿','⽚'=>'片','â½›'=>'牙','⽜'=>'牛','â½'=>'犬','⽞'=>'玄','⽟'=>'玉','â½ '=>'瓜','⽡'=>'瓦','â½¢'=>'甘','â½£'=>'生','⽤'=>'用','â½¥'=>'ç”°','⽦'=>'ç–‹','â½§'=>'ç–’','⽨'=>'ç™¶','⽩'=>'白','⽪'=>'çš®','⽫'=>'çš¿','⽬'=>'ç›®','â½'=>'矛','â½®'=>'矢','⽯'=>'石','â½°'=>'示','â½±'=>'禸','â½²'=>'禾','â½³'=>'ç©´','â½´'=>'ç«‹','â½µ'=>'竹','â½¶'=>'ç±³','â½·'=>'糸','⽸'=>'ç¼¶','â½¹'=>'网','⽺'=>'羊','â½»'=>'ç¾½','â½¼'=>'è€','â½½'=>'而','â½¾'=>'耒','⽿'=>'耳','â¾€'=>'è¿','â¾'=>'肉','⾂'=>'臣','⾃'=>'自','⾄'=>'至','â¾…'=>'臼','⾆'=>'舌','⾇'=>'舛','⾈'=>'舟','⾉'=>'艮','⾊'=>'色','⾋'=>'艸','⾌'=>'è™','â¾'=>'虫','⾎'=>'è¡€','â¾'=>'行','â¾'=>'è¡£','⾑'=>'襾','â¾’'=>'見','⾓'=>'è§’','â¾”'=>'言','⾕'=>'è°·','â¾–'=>'豆','â¾—'=>'豕','⾘'=>'豸','â¾™'=>'è²','⾚'=>'赤','â¾›'=>'èµ°','⾜'=>'è¶³','â¾'=>'身','⾞'=>'車','⾟'=>'è¾›','â¾ '=>'è¾°','⾡'=>'è¾µ','â¾¢'=>'é‚‘','â¾£'=>'é…‰','⾤'=>'釆','â¾¥'=>'里','⾦'=>'金','â¾§'=>'é•·','⾨'=>'é–€','⾩'=>'阜','⾪'=>'éš¶','⾫'=>'éš¹','⾬'=>'雨','â¾'=>'é‘','â¾®'=>'éž','⾯'=>'é¢','â¾°'=>'é©','â¾±'=>'韋','â¾²'=>'éŸ','â¾³'=>'音','â¾´'=>'é ','â¾µ'=>'風','â¾¶'=>'飛','â¾·'=>'食','⾸'=>'首','â¾¹'=>'香','⾺'=>'馬','â¾»'=>'骨','â¾¼'=>'高','â¾½'=>'髟','â¾¾'=>'鬥','⾿'=>'鬯','â¿€'=>'鬲','â¿'=>'鬼','â¿‚'=>'éš','⿃'=>'é³¥','â¿„'=>'é¹µ','â¿…'=>'鹿','⿆'=>'麥','⿇'=>'麻','⿈'=>'黃','⿉'=>'é»','⿊'=>'黑','â¿‹'=>'黹','⿌'=>'黽','â¿'=>'鼎','⿎'=>'鼓','â¿'=>'é¼ ','â¿'=>'é¼»','â¿‘'=>'齊','â¿’'=>'é½’','â¿“'=>'é¾','â¿”'=>'龜','â¿•'=>'é¾ ',' '=>' ','〶'=>'〒','〸'=>'å','〹'=>'å„','〺'=>'å…','ãŒ'=>'ã‹ã‚™','ãŽ'=>'ãã‚™','ã'=>'ãã‚™','ã’'=>'ã‘ã‚™','ã”'=>'ã“ã‚™','ã–'=>'ã•ã‚™','ã˜'=>'ã—ã‚™','ãš'=>'ã™ã‚™','ãœ'=>'ã›ã‚™','ãž'=>'ãã‚™','ã '=>'ãŸã‚™','ã¢'=>'ã¡ã‚™','ã¥'=>'ã¤ã‚™','ã§'=>'ã¦ã‚™','ã©'=>'ã¨ã‚™','ã°'=>'ã¯ã‚™','ã±'=>'ã¯ã‚š','ã³'=>'ã²ã‚™','ã´'=>'ã²ã‚š','ã¶'=>'ãµã‚™','ã·'=>'ãµã‚š','ã¹'=>'ã¸ã‚™','ãº'=>'ã¸ã‚š','ã¼'=>'ã»ã‚™','ã½'=>'ã»ã‚š','ã‚”'=>'ã†ã‚™','ã‚›'=>' ã‚™','゜'=>' ゚','ゞ'=>'ã‚ã‚™','ゟ'=>'より','ガ'=>'ã‚«ã‚™','ã‚®'=>'ã‚ã‚™','ã‚°'=>'グ','ゲ'=>'ゲ','ã‚´'=>'ゴ','ã‚¶'=>'ザ','ジ'=>'ã‚·ã‚™','ズ'=>'ズ','ゼ'=>'ゼ','ゾ'=>'ゾ','ダ'=>'ã‚¿ã‚™','ヂ'=>'ãƒã‚™','ヅ'=>'ヅ','デ'=>'デ','ド'=>'ド','ãƒ'=>'ãƒã‚™','パ'=>'ãƒã‚š','ビ'=>'ビ','ピ'=>'ピ','ブ'=>'ブ','プ'=>'プ','ベ'=>'ベ','ペ'=>'ペ','ボ'=>'ボ','ãƒ'=>'ポ','ヴ'=>'ヴ','ヷ'=>'ヷ','ヸ'=>'ヸ','ヹ'=>'ヹ','ヺ'=>'ヺ','ヾ'=>'ヾ','ヿ'=>'コト','ㄱ'=>'á„€','ㄲ'=>'á„','ㄳ'=>'ᆪ','ã„´'=>'á„‚','ㄵ'=>'ᆬ','ã„¶'=>'á†','ã„·'=>'ᄃ','ㄸ'=>'á„„','ㄹ'=>'á„…','ㄺ'=>'ᆰ','ã„»'=>'ᆱ','ㄼ'=>'ᆲ','ㄽ'=>'ᆳ','ㄾ'=>'ᆴ','ã„¿'=>'ᆵ','ã…€'=>'ᄚ','ã…'=>'ᄆ','ã…‚'=>'ᄇ','ã…ƒ'=>'ᄈ','ã…„'=>'á„¡','ã……'=>'ᄉ','ã…†'=>'ᄊ','ã…‡'=>'á„‹','ã…ˆ'=>'ᄌ','ã…‰'=>'á„','ã…Š'=>'ᄎ','ã…‹'=>'á„','ã…Œ'=>'á„','ã…'=>'á„‘','ã…Ž'=>'á„’','ã…'=>'á…¡','ã…'=>'á…¢','ã…‘'=>'á…£','ã…’'=>'á…¤','ã…“'=>'á…¥','ã…”'=>'á…¦','ã…•'=>'á…§','ã…–'=>'á…¨','ã…—'=>'á…©','ã…˜'=>'á…ª','ã…™'=>'á…«','ã…š'=>'á…¬','ã…›'=>'á…','ã…œ'=>'á…®','ã…'=>'á…¯','ã…ž'=>'á…°','ã…Ÿ'=>'á…±','ã… '=>'á…²','ã…¡'=>'á…³','ã…¢'=>'á…´','ã…£'=>'á…µ','ã…¤'=>'á… ','ã…¥'=>'á„”','ã…¦'=>'á„•','ã…§'=>'ᇇ','ã…¨'=>'ᇈ','ã…©'=>'ᇌ','ã…ª'=>'ᇎ','ã…«'=>'ᇓ','ã…¬'=>'ᇗ','ã…'=>'ᇙ','ã…®'=>'ᄜ','ã…¯'=>'á‡','ã…°'=>'ᇟ','ã…±'=>'á„','ã…²'=>'ᄞ','ã…³'=>'á„ ','ã…´'=>'á„¢','ã…µ'=>'á„£','ã…¶'=>'á„§','ã…·'=>'á„©','ã…¸'=>'á„«','ã…¹'=>'ᄬ','ã…º'=>'á„','ã…»'=>'á„®','ã…¼'=>'ᄯ','ã…½'=>'ᄲ','ã…¾'=>'á„¶','ã…¿'=>'á…€','ㆀ'=>'á…‡','ã†'=>'á…Œ','ㆂ'=>'ᇱ','ㆃ'=>'ᇲ','ㆄ'=>'á…—','ㆅ'=>'á…˜','ㆆ'=>'á…™','ㆇ'=>'ᆄ','ㆈ'=>'ᆅ','ㆉ'=>'ᆈ','ㆊ'=>'ᆑ','ㆋ'=>'ᆒ','ㆌ'=>'ᆔ','ã†'=>'ᆞ','ㆎ'=>'ᆡ','㆒'=>'一','㆓'=>'二','㆔'=>'三','㆕'=>'å››','㆖'=>'上','㆗'=>'ä¸','㆘'=>'下','㆙'=>'甲','㆚'=>'ä¹™','㆛'=>'丙','㆜'=>'ä¸','ã†'=>'天','㆞'=>'地','㆟'=>'人','㈀'=>'(á„€)','ãˆ'=>'(á„‚)','㈂'=>'(ᄃ)','㈃'=>'(á„…)','㈄'=>'(ᄆ)','㈅'=>'(ᄇ)','㈆'=>'(ᄉ)','㈇'=>'(á„‹)','㈈'=>'(ᄌ)','㈉'=>'(ᄎ)','㈊'=>'(á„)','㈋'=>'(á„)','㈌'=>'(á„‘)','ãˆ'=>'(á„’)','㈎'=>'(가)','ãˆ'=>'(á„‚á…¡)','ãˆ'=>'(다)','㈑'=>'(á„…á…¡)','㈒'=>'(마)','㈓'=>'(바)','㈔'=>'(사)','㈕'=>'(á„‹á…¡)','㈖'=>'(자)','㈗'=>'(차)','㈘'=>'(á„á…¡)','㈙'=>'(á„á…¡)','㈚'=>'(á„‘á…¡)','㈛'=>'(á„’á…¡)','㈜'=>'(주)','ãˆ'=>'(오전)','㈞'=>'(á„‹á…©á„’á…®)','㈠'=>'(一)','㈡'=>'(二)','㈢'=>'(三)','㈣'=>'(å››)','㈤'=>'(五)','㈥'=>'(å…)','㈦'=>'(七)','㈧'=>'(å…«)','㈨'=>'(ä¹)','㈩'=>'(å)','㈪'=>'(月)','㈫'=>'(ç«)','㈬'=>'(æ°´)','ãˆ'=>'(木)','㈮'=>'(金)','㈯'=>'(土)','㈰'=>'(æ—¥)','㈱'=>'(æ ª)','㈲'=>'(有)','㈳'=>'(社)','㈴'=>'(å)','㈵'=>'(特)','㈶'=>'(財)','㈷'=>'(ç¥)','㈸'=>'(労)','㈹'=>'(代)','㈺'=>'(呼)','㈻'=>'(å¦)','㈼'=>'(監)','㈽'=>'(ä¼)','㈾'=>'(資)','㈿'=>'(å”)','㉀'=>'(ç¥)','ã‰'=>'(休)','㉂'=>'(自)','㉃'=>'(至)','ã‰'=>'PTE','㉑'=>'21','㉒'=>'22','㉓'=>'23','㉔'=>'24','㉕'=>'25','㉖'=>'26','㉗'=>'27','㉘'=>'28','㉙'=>'29','㉚'=>'30','㉛'=>'31','㉜'=>'32','ã‰'=>'33','㉞'=>'34','㉟'=>'35','㉠'=>'á„€','㉡'=>'á„‚','㉢'=>'ᄃ','㉣'=>'á„…','㉤'=>'ᄆ','㉥'=>'ᄇ','㉦'=>'ᄉ','㉧'=>'á„‹','㉨'=>'ᄌ','㉩'=>'ᄎ','㉪'=>'á„','㉫'=>'á„','㉬'=>'á„‘','ã‰'=>'á„’','㉮'=>'가','㉯'=>'á„‚á…¡','㉰'=>'다','㉱'=>'á„…á…¡','㉲'=>'마','㉳'=>'바','㉴'=>'사','㉵'=>'á„‹á…¡','㉶'=>'자','㉷'=>'차','㉸'=>'á„á…¡','㉹'=>'á„á…¡','㉺'=>'á„‘á…¡','㉻'=>'á„’á…¡','㉼'=>'참고','㉽'=>'주의','㉾'=>'á„‹á…®','㊀'=>'一','ãŠ'=>'二','㊂'=>'三','㊃'=>'å››','㊄'=>'五','㊅'=>'å…','㊆'=>'七','㊇'=>'å…«','㊈'=>'ä¹','㊉'=>'å','㊊'=>'月','㊋'=>'ç«','㊌'=>'æ°´','ãŠ'=>'木','㊎'=>'金','ãŠ'=>'土','ãŠ'=>'æ—¥','㊑'=>'æ ª','㊒'=>'有','㊓'=>'社','㊔'=>'å','㊕'=>'特','㊖'=>'財','㊗'=>'ç¥','㊘'=>'労','㊙'=>'秘','㊚'=>'ç”·','㊛'=>'女','㊜'=>'é©','ãŠ'=>'優','㊞'=>'å°','㊟'=>'注','㊠'=>'é …','㊡'=>'休','㊢'=>'写','㊣'=>'æ£','㊤'=>'上','㊥'=>'ä¸','㊦'=>'下','㊧'=>'å·¦','㊨'=>'å³','㊩'=>'医','㊪'=>'å®—','㊫'=>'å¦','㊬'=>'監','ãŠ'=>'ä¼','㊮'=>'資','㊯'=>'å”','㊰'=>'夜','㊱'=>'36','㊲'=>'37','㊳'=>'38','㊴'=>'39','㊵'=>'40','㊶'=>'41','㊷'=>'42','㊸'=>'43','㊹'=>'44','㊺'=>'45','㊻'=>'46','㊼'=>'47','㊽'=>'48','㊾'=>'49','㊿'=>'50','ã‹€'=>'1月','ã‹'=>'2月','ã‹‚'=>'3月','㋃'=>'4月','ã‹„'=>'5月','ã‹…'=>'6月','㋆'=>'7月','㋇'=>'8月','㋈'=>'9月','㋉'=>'10月','㋊'=>'11月','ã‹‹'=>'12月','㋌'=>'Hg','ã‹'=>'erg','㋎'=>'eV','ã‹'=>'LTD','ã‹'=>'ã‚¢','ã‹‘'=>'イ','ã‹’'=>'ウ','ã‹“'=>'エ','ã‹”'=>'オ','ã‹•'=>'ã‚«','ã‹–'=>'ã‚','ã‹—'=>'ク','㋘'=>'ケ','ã‹™'=>'コ','㋚'=>'サ','ã‹›'=>'ã‚·','㋜'=>'ス','ã‹'=>'ã‚»','㋞'=>'ソ','㋟'=>'ã‚¿','ã‹ '=>'ãƒ','ã‹¡'=>'ツ','ã‹¢'=>'テ','ã‹£'=>'ト','㋤'=>'ナ','ã‹¥'=>'ニ','㋦'=>'ヌ','ã‹§'=>'ãƒ','㋨'=>'ノ','ã‹©'=>'ãƒ','㋪'=>'ヒ','ã‹«'=>'フ','㋬'=>'ヘ','ã‹'=>'ホ','ã‹®'=>'マ','㋯'=>'ミ','ã‹°'=>'ム','㋱'=>'メ','㋲'=>'モ','㋳'=>'ヤ','ã‹´'=>'ユ','㋵'=>'ヨ','ã‹¶'=>'ラ','ã‹·'=>'リ','㋸'=>'ル','㋹'=>'レ','㋺'=>'ãƒ','ã‹»'=>'ワ','㋼'=>'ヰ','㋽'=>'ヱ','㋾'=>'ヲ','㌀'=>'ã‚¢ãƒã‚šãƒ¼ãƒˆ','ãŒ'=>'アルファ','㌂'=>'アンペア','㌃'=>'アール','㌄'=>'イニング','㌅'=>'インãƒ','㌆'=>'ウォン','㌇'=>'エスクード','㌈'=>'エーカー','㌉'=>'オンス','㌊'=>'オーム','㌋'=>'カイリ','㌌'=>'カラット','ãŒ'=>'ã‚«ãƒãƒªãƒ¼','㌎'=>'ã‚«ã‚™ãƒãƒ³','ãŒ'=>'ガンマ','ãŒ'=>'ã‚゙ガ','㌑'=>'ã‚゙ニー','㌒'=>'ã‚ュリー','㌓'=>'ã‚゙ルダー','㌔'=>'ã‚ãƒ','㌕'=>'ã‚ãƒã‚¯ã‚™ãƒ©ãƒ ','㌖'=>'ã‚ãƒãƒ¡ãƒ¼ãƒˆãƒ«','㌗'=>'ã‚ãƒãƒ¯ãƒƒãƒˆ','㌘'=>'グラム','㌙'=>'グラムトン','㌚'=>'クルゼイãƒ','㌛'=>'クãƒãƒ¼ãƒ','㌜'=>'ケース','ãŒ'=>'コルナ','㌞'=>'コーポ','㌟'=>'サイクル','㌠'=>'サンãƒãƒ¼ãƒ ','㌡'=>'シリング','㌢'=>'センãƒ','㌣'=>'セント','㌤'=>'ダース','㌥'=>'デシ','㌦'=>'ドル','㌧'=>'トン','㌨'=>'ナノ','㌩'=>'ノット','㌪'=>'ãƒã‚¤ãƒ„','㌫'=>'ãƒã‚šãƒ¼ã‚»ãƒ³ãƒˆ','㌬'=>'ãƒã‚šãƒ¼ãƒ„','ãŒ'=>'ãƒã‚™ãƒ¼ãƒ¬ãƒ«','㌮'=>'ピアストル','㌯'=>'ピクル','㌰'=>'ピコ','㌱'=>'ビル','㌲'=>'ファラッド','㌳'=>'フィート','㌴'=>'ブッシェル','㌵'=>'フラン','㌶'=>'ヘクタール','㌷'=>'ペソ','㌸'=>'ペニヒ','㌹'=>'ヘルツ','㌺'=>'ペンス','㌻'=>'ページ','㌼'=>'ベータ','㌽'=>'ポイント','㌾'=>'ボルト','㌿'=>'ホン','ã€'=>'ポンド','ã'=>'ホール','ã‚'=>'ホーン','ãƒ'=>'マイクãƒ','ã„'=>'マイル','ã…'=>'マッãƒ','ã†'=>'マルク','ã‡'=>'マンション','ãˆ'=>'ミクãƒãƒ³','ã‰'=>'ミリ','ãŠ'=>'ミリãƒã‚™ãƒ¼ãƒ«','ã‹'=>'メガ','ãŒ'=>'メガトン','ã'=>'メートル','ãŽ'=>'ヤード','ã'=>'ヤール','ã'=>'ユアン','ã‘'=>'リットル','ã’'=>'リラ','ã“'=>'ルピー','ã”'=>'ルーブル','ã•'=>'レム','ã–'=>'レントゲン','ã—'=>'ワット','ã˜'=>'0点','ã™'=>'1点','ãš'=>'2点','ã›'=>'3点','ãœ'=>'4点','ã'=>'5点','ãž'=>'6点','ãŸ'=>'7点','ã '=>'8点','ã¡'=>'9点','ã¢'=>'10点','ã£'=>'11点','ã¤'=>'12点','ã¥'=>'13点','ã¦'=>'14点','ã§'=>'15点','ã¨'=>'16点','ã©'=>'17点','ãª'=>'18点','ã«'=>'19点','ã¬'=>'20点','ã'=>'21点','ã®'=>'22点','ã¯'=>'23点','ã°'=>'24点','ã±'=>'hPa','ã²'=>'da','ã³'=>'AU','ã´'=>'bar','ãµ'=>'oV','ã¶'=>'pc','ã·'=>'dm','ã¸'=>'dm2','ã¹'=>'dm3','ãº'=>'IU','ã»'=>'å¹³æˆ','ã¼'=>'æ˜å’Œ','ã½'=>'大æ£','ã¾'=>'明治','ã¿'=>'æ ªå¼ä¼šç¤¾','㎀'=>'pA','ãŽ'=>'nA','㎂'=>'μA','㎃'=>'mA','㎄'=>'kA','㎅'=>'KB','㎆'=>'MB','㎇'=>'GB','㎈'=>'cal','㎉'=>'kcal','㎊'=>'pF','㎋'=>'nF','㎌'=>'μF','ãŽ'=>'μg','㎎'=>'mg','ãŽ'=>'kg','ãŽ'=>'Hz','㎑'=>'kHz','㎒'=>'MHz','㎓'=>'GHz','㎔'=>'THz','㎕'=>'μl','㎖'=>'ml','㎗'=>'dl','㎘'=>'kl','㎙'=>'fm','㎚'=>'nm','㎛'=>'μm','㎜'=>'mm','ãŽ'=>'cm','㎞'=>'km','㎟'=>'mm2','㎠'=>'cm2','㎡'=>'m2','㎢'=>'km2','㎣'=>'mm3','㎤'=>'cm3','㎥'=>'m3','㎦'=>'km3','㎧'=>'m∕s','㎨'=>'m∕s2','㎩'=>'Pa','㎪'=>'kPa','㎫'=>'MPa','㎬'=>'GPa','ãŽ'=>'rad','㎮'=>'rad∕s','㎯'=>'rad∕s2','㎰'=>'ps','㎱'=>'ns','㎲'=>'μs','㎳'=>'ms','㎴'=>'pV','㎵'=>'nV','㎶'=>'μV','㎷'=>'mV','㎸'=>'kV','㎹'=>'MV','㎺'=>'pW','㎻'=>'nW','㎼'=>'μW','㎽'=>'mW','㎾'=>'kW','㎿'=>'MW','ã€'=>'kΩ','ã'=>'MΩ','ã‚'=>'a.m.','ãƒ'=>'Bq','ã„'=>'cc','ã…'=>'cd','ã†'=>'C∕kg','ã‡'=>'Co.','ãˆ'=>'dB','ã‰'=>'Gy','ãŠ'=>'ha','ã‹'=>'HP','ãŒ'=>'in','ã'=>'KK','ãŽ'=>'KM','ã'=>'kt','ã'=>'lm','ã‘'=>'ln','ã’'=>'log','ã“'=>'lx','ã”'=>'mb','ã•'=>'mil','ã–'=>'mol','ã—'=>'PH','ã˜'=>'p.m.','ã™'=>'PPM','ãš'=>'PR','ã›'=>'sr','ãœ'=>'Sv','ã'=>'Wb','ãž'=>'V∕m','ãŸ'=>'A∕m','ã '=>'1æ—¥','ã¡'=>'2æ—¥','ã¢'=>'3æ—¥','ã£'=>'4æ—¥','ã¤'=>'5æ—¥','ã¥'=>'6æ—¥','ã¦'=>'7æ—¥','ã§'=>'8æ—¥','ã¨'=>'9æ—¥','ã©'=>'10æ—¥','ãª'=>'11æ—¥','ã«'=>'12æ—¥','ã¬'=>'13æ—¥','ã'=>'14æ—¥','ã®'=>'15æ—¥','ã¯'=>'16æ—¥','ã°'=>'17æ—¥','ã±'=>'18æ—¥','ã²'=>'19æ—¥','ã³'=>'20æ—¥','ã´'=>'21æ—¥','ãµ'=>'22æ—¥','ã¶'=>'23æ—¥','ã·'=>'24æ—¥','ã¸'=>'25æ—¥','ã¹'=>'26æ—¥','ãº'=>'27æ—¥','ã»'=>'28æ—¥','ã¼'=>'29æ—¥','ã½'=>'30æ—¥','ã¾'=>'31æ—¥','ã¿'=>'gal','豈'=>'豈','ï¤'=>'æ›´','車'=>'車','賈'=>'賈','滑'=>'滑','串'=>'串','句'=>'å¥','龜'=>'龜','龜'=>'龜','契'=>'契','金'=>'金','喇'=>'å–‡','奈'=>'奈','ï¤'=>'懶','癩'=>'癩','ï¤'=>'ç¾…','ï¤'=>'蘿','螺'=>'螺','裸'=>'裸','邏'=>'é‚','樂'=>'樂','洛'=>'æ´›','烙'=>'烙','珞'=>'çž','落'=>'è½','酪'=>'é…ª','駱'=>'é§±','亂'=>'亂','卵'=>'åµ','ï¤'=>'欄','爛'=>'爛','蘭'=>'è˜','ï¤ '=>'鸞','嵐'=>'åµ','濫'=>'æ¿«','藍'=>'è—','襤'=>'襤','拉'=>'拉','臘'=>'臘','蠟'=>'è Ÿ','廊'=>'廊','朗'=>'朗','浪'=>'浪','狼'=>'狼','郎'=>'郎','ï¤'=>'來','冷'=>'冷','勞'=>'勞','擄'=>'æ“„','櫓'=>'æ«“','爐'=>'çˆ','盧'=>'ç›§','老'=>'è€','蘆'=>'蘆','虜'=>'虜','路'=>'è·¯','露'=>'露','魯'=>'é¯','鷺'=>'é·º','碌'=>'碌','祿'=>'祿','綠'=>'ç¶ ','菉'=>'è‰','錄'=>'錄','鹿'=>'鹿','ï¥'=>'è«–','壟'=>'壟','弄'=>'弄','籠'=>'ç± ','聾'=>'è¾','牢'=>'牢','磊'=>'磊','賂'=>'賂','雷'=>'é›·','壘'=>'壘','屢'=>'å±¢','樓'=>'樓','ï¥'=>'æ·š','漏'=>'æ¼','ï¥'=>'ç´¯','ï¥'=>'縷','陋'=>'陋','勒'=>'å‹’','肋'=>'è‚‹','凜'=>'凜','凌'=>'凌','稜'=>'稜','綾'=>'ç¶¾','菱'=>'è±','陵'=>'陵','讀'=>'讀','拏'=>'æ‹','樂'=>'樂','ï¥'=>'諾','丹'=>'丹','寧'=>'寧','ï¥ '=>'怒','率'=>'率','異'=>'ç•°','北'=>'北','磻'=>'磻','便'=>'便','復'=>'復','不'=>'ä¸','泌'=>'泌','數'=>'數','索'=>'ç´¢','參'=>'åƒ','塞'=>'塞','ï¥'=>'çœ','葉'=>'葉','說'=>'說','殺'=>'殺','辰'=>'è¾°','沈'=>'沈','拾'=>'拾','若'=>'è‹¥','掠'=>'æŽ ','略'=>'ç•¥','亮'=>'亮','兩'=>'å…©','凉'=>'凉','梁'=>'æ¢','糧'=>'ç³§','良'=>'良','諒'=>'è«’','量'=>'é‡','勵'=>'勵','呂'=>'å‘‚','ï¦'=>'女','廬'=>'廬','旅'=>'æ—…','濾'=>'濾','礪'=>'礪','閭'=>'é–','驪'=>'驪','麗'=>'麗','黎'=>'黎','力'=>'力','曆'=>'曆','歷'=>'æ·','ï¦'=>'è½¢','年'=>'å¹´','ï¦'=>'æ†','ï¦'=>'戀','撚'=>'æ’š','漣'=>'æ¼£','煉'=>'ç…‰','璉'=>'ç’‰','秊'=>'ç§Š','練'=>'ç·´','聯'=>'è¯','輦'=>'輦','蓮'=>'è“®','連'=>'連','鍊'=>'éŠ','列'=>'列','ï¦'=>'劣','咽'=>'å’½','烈'=>'烈','ï¦ '=>'裂','說'=>'說','廉'=>'廉','念'=>'念','捻'=>'æ»','殮'=>'æ®®','簾'=>'ç°¾','獵'=>'çµ','令'=>'令','囹'=>'囹','寧'=>'寧','嶺'=>'嶺','怜'=>'怜','ï¦'=>'玲','瑩'=>'ç‘©','羚'=>'羚','聆'=>'è†','鈴'=>'鈴','零'=>'é›¶','靈'=>'éˆ','領'=>'é ˜','例'=>'例','禮'=>'禮','醴'=>'醴','隸'=>'隸','惡'=>'惡','了'=>'了','僚'=>'僚','寮'=>'寮','尿'=>'å°¿','料'=>'æ–™','樂'=>'樂','ï§€'=>'燎','ï§'=>'療','ï§‚'=>'蓼','遼'=>'é¼','ï§„'=>'é¾','ï§…'=>'暈','阮'=>'阮','劉'=>'劉','杻'=>'æ»','柳'=>'柳','ï§Š'=>'æµ','ï§‹'=>'溜','ï§Œ'=>'ç‰','ï§'=>'ç•™','ï§Ž'=>'ç¡«','ï§'=>'ç´','ï§'=>'類','ï§‘'=>'å…','ï§’'=>'戮','ï§“'=>'陸','ï§”'=>'倫','ï§•'=>'å´™','ï§–'=>'æ·ª','ï§—'=>'輪','律'=>'律','ï§™'=>'æ…„','ï§š'=>'æ —','ï§›'=>'率','ï§œ'=>'隆','ï§'=>'利','ï§ž'=>'å','ï§Ÿ'=>'å±¥','ï§ '=>'易','ï§¡'=>'æŽ','ï§¢'=>'梨','ï§£'=>'æ³¥','理'=>'ç†','ï§¥'=>'ç—¢','罹'=>'ç½¹','ï§§'=>'è£','裡'=>'裡','ï§©'=>'里','離'=>'離','ï§«'=>'匿','溺'=>'溺','ï§'=>'å','ï§®'=>'ç‡','璘'=>'ç’˜','ï§°'=>'è—º','ï§±'=>'隣','ï§²'=>'é±—','ï§³'=>'麟','ï§´'=>'æž—','ï§µ'=>'æ·‹','ï§¶'=>'臨','ï§·'=>'ç«‹','笠'=>'ç¬ ','ï§¹'=>'ç²’','狀'=>'ç‹€','ï§»'=>'ç‚™','ï§¼'=>'è˜','ï§½'=>'什','ï§¾'=>'茶','ï§¿'=>'刺','切'=>'切','ï¨'=>'度','拓'=>'æ‹“','糖'=>'ç³–','宅'=>'å®…','洞'=>'æ´ž','暴'=>'æš´','輻'=>'è¼»','行'=>'行','降'=>'é™','見'=>'見','廓'=>'廓','兀'=>'å…€','ï¨'=>'å—€','ï¨'=>'塚','晴'=>'æ™´','凞'=>'凞','猪'=>'猪','益'=>'益','礼'=>'礼','神'=>'神','祥'=>'祥','福'=>'ç¦','靖'=>'é–','ï¨'=>'ç²¾','羽'=>'ç¾½','ï¨ '=>'蘒','諸'=>'諸','逸'=>'逸','都'=>'都','飯'=>'飯','飼'=>'飼','館'=>'館','ï¨'=>'é¶´','侮'=>'ä¾®','僧'=>'僧','免'=>'å…','勉'=>'勉','勤'=>'勤','卑'=>'å‘','喝'=>'å–','嘆'=>'嘆','器'=>'器','塀'=>'å¡€','墨'=>'墨','層'=>'層','屮'=>'å±®','悔'=>'æ‚”','慨'=>'æ…¨','憎'=>'憎','ï©€'=>'懲','ï©'=>'æ•','ï©‚'=>'æ—¢','暑'=>'æš‘','ï©„'=>'梅','ï©…'=>'æµ·','渚'=>'渚','漢'=>'æ¼¢','煮'=>'ç…®','爫'=>'爫','琢'=>'ç¢','ï©‹'=>'碑','社'=>'社','ï©'=>'祉','祈'=>'祈','ï©'=>'ç¥','ï©'=>'祖','ï©‘'=>'ç¥','ï©’'=>'ç¦','ï©“'=>'禎','ï©”'=>'ç©€','ï©•'=>'çª','ï©–'=>'節','ï©—'=>'ç·´','縉'=>'縉','ï©™'=>'ç¹','署'=>'ç½²','ï©›'=>'者','臭'=>'è‡','ï©'=>'艹','艹'=>'艹','著'=>'è‘—','ï© '=>'è¤','ï©¡'=>'視','ï©¢'=>'è¬','ï©£'=>'謹','賓'=>'賓','ï©¥'=>'è´ˆ','辶'=>'è¾¶','ï©§'=>'逸','難'=>'難','ï©©'=>'響','頻'=>'é »','ï©°'=>'並','况'=>'况','全'=>'å…¨','侀'=>'ä¾€','ï©´'=>'å……','冀'=>'冀','ï©¶'=>'勇','ï©·'=>'勺','喝'=>'å–','啕'=>'å••','喙'=>'å–™','ï©»'=>'å—¢','塚'=>'塚','墳'=>'墳','奄'=>'奄','ï©¿'=>'奔','婢'=>'å©¢','ïª'=>'嬨','廒'=>'å»’','廙'=>'å»™','彩'=>'彩','徭'=>'å¾','惘'=>'惘','慎'=>'æ…Ž','愈'=>'愈','憎'=>'憎','慠'=>'æ… ','懲'=>'懲','戴'=>'戴','ïª'=>'æ„','搜'=>'æœ','ïª'=>'æ‘’','ïª'=>'æ•–','晴'=>'æ™´','朗'=>'朗','望'=>'望','杖'=>'æ–','歹'=>'æ¹','殺'=>'殺','流'=>'æµ','滛'=>'æ»›','滋'=>'滋','漢'=>'æ¼¢','瀞'=>'瀞','煮'=>'ç…®','ïª'=>'çž§','爵'=>'爵','犯'=>'犯','ïª '=>'猪','瑱'=>'瑱','甆'=>'甆','画'=>'ç”»','瘝'=>'ç˜','瘟'=>'瘟','益'=>'益','盛'=>'ç››','直'=>'ç›´','睊'=>'çŠ','着'=>'ç€','磌'=>'磌','窱'=>'窱','ïª'=>'節','类'=>'ç±»','絛'=>'çµ›','練'=>'ç·´','缾'=>'ç¼¾','者'=>'者','荒'=>'è’','華'=>'è¯','蝹'=>'è¹','襁'=>'è¥','覆'=>'覆','視'=>'視','調'=>'調','諸'=>'諸','請'=>'è«‹','謁'=>'è¬','諾'=>'諾','諭'=>'è«','謹'=>'謹','ï«€'=>'變','ï«'=>'è´ˆ','ï«‚'=>'輸','遲'=>'é²','ï«„'=>'醙','ï«…'=>'鉶','陼'=>'陼','難'=>'難','靖'=>'é–','韛'=>'韛','響'=>'響','ï«‹'=>'é ‹','頻'=>'é »','ï«'=>'鬒','龜'=>'龜','ï«'=>'𢡊','ï«'=>'𢡄','ï«‘'=>'ð£•','ï«’'=>'ã®','ï«“'=>'䀘','ï«”'=>'䀹','ï«•'=>'𥉉','ï«–'=>'ð¥³','ï«—'=>'𧻓','齃'=>'齃','ï«™'=>'龎','ff'=>'ff','ï¬'=>'fi','fl'=>'fl','ffi'=>'ffi','ffl'=>'ffl','ſt'=>'st','st'=>'st','ﬓ'=>'Õ´Õ¶','ﬔ'=>'Õ´Õ¥','ﬕ'=>'Õ´Õ«','ﬖ'=>'Õ¾Õ¶','ﬗ'=>'Õ´Õ','ï¬'=>'×™Ö´','ײַ'=>'ײַ','ï¬ '=>'×¢','ﬡ'=>'×','ﬢ'=>'ד','ﬣ'=>'×”','ﬤ'=>'×›','ﬥ'=>'ל','ﬦ'=>'×','ﬧ'=>'ר','ﬨ'=>'ת','﬩'=>'+','שׁ'=>'ש×','שׂ'=>'שׂ','שּׁ'=>'שּ×','ï¬'=>'שּׂ','אַ'=>'×Ö·','אָ'=>'×Ö¸','אּ'=>'×Ö¼','בּ'=>'בּ','גּ'=>'×’Ö¼','דּ'=>'דּ','הּ'=>'×”Ö¼','וּ'=>'וּ','זּ'=>'×–Ö¼','טּ'=>'טּ','יּ'=>'×™Ö¼','ךּ'=>'ךּ','כּ'=>'×›Ö¼','לּ'=>'לּ','מּ'=>'מּ','ï€'=>'× Ö¼','ï'=>'סּ','ïƒ'=>'×£Ö¼','ï„'=>'פּ','ï†'=>'צּ','ï‡'=>'×§Ö¼','ïˆ'=>'רּ','ï‰'=>'שּ','ïŠ'=>'תּ','ï‹'=>'וֹ','ïŒ'=>'בֿ','ï'=>'×›Ö¿','ïŽ'=>'פֿ','ï'=>'×ל','ï'=>'Ù±','ï‘'=>'Ù±','ï’'=>'Ù»','ï“'=>'Ù»','ï”'=>'Ù»','ï•'=>'Ù»','ï–'=>'Ù¾','ï—'=>'Ù¾','ï˜'=>'Ù¾','ï™'=>'Ù¾','ïš'=>'Ú€','ï›'=>'Ú€','ïœ'=>'Ú€','ï'=>'Ú€','ïž'=>'Ùº','ïŸ'=>'Ùº','ï '=>'Ùº','ï¡'=>'Ùº','ï¢'=>'Ù¿','ï£'=>'Ù¿','ï¤'=>'Ù¿','ï¥'=>'Ù¿','ï¦'=>'Ù¹','ï§'=>'Ù¹','ï¨'=>'Ù¹','ï©'=>'Ù¹','ïª'=>'Ú¤','ï«'=>'Ú¤','ï¬'=>'Ú¤','ï'=>'Ú¤','ï®'=>'Ú¦','ï¯'=>'Ú¦','ï°'=>'Ú¦','ï±'=>'Ú¦','ï²'=>'Ú„','ï³'=>'Ú„','ï´'=>'Ú„','ïµ'=>'Ú„','ï¶'=>'Úƒ','ï·'=>'Úƒ','ï¸'=>'Úƒ','ï¹'=>'Úƒ','ïº'=>'Ú†','ï»'=>'Ú†','ï¼'=>'Ú†','ï½'=>'Ú†','ï¾'=>'Ú‡','ï¿'=>'Ú‡','ﮀ'=>'Ú‡','ï®'=>'Ú‡','ﮂ'=>'Ú','ﮃ'=>'Ú','ﮄ'=>'ÚŒ','ï®…'=>'ÚŒ','ﮆ'=>'ÚŽ','ﮇ'=>'ÚŽ','ﮈ'=>'Úˆ','ﮉ'=>'Úˆ','ﮊ'=>'Ú˜','ﮋ'=>'Ú˜','ﮌ'=>'Ú‘','ï®'=>'Ú‘','ﮎ'=>'Ú©','ï®'=>'Ú©','ï®'=>'Ú©','ﮑ'=>'Ú©','ï®’'=>'Ú¯','ﮓ'=>'Ú¯','ï®”'=>'Ú¯','ﮕ'=>'Ú¯','ï®–'=>'Ú³','ï®—'=>'Ú³','ﮘ'=>'Ú³','ï®™'=>'Ú³','ﮚ'=>'Ú±','ï®›'=>'Ú±','ﮜ'=>'Ú±','ï®'=>'Ú±','ﮞ'=>'Úº','ﮟ'=>'Úº','ï® '=>'Ú»','ﮡ'=>'Ú»','ﮢ'=>'Ú»','ﮣ'=>'Ú»','ﮤ'=>'Û•Ù”','ﮥ'=>'Û•Ù”','ﮦ'=>'Û','ï®§'=>'Û','ﮨ'=>'Û','ﮩ'=>'Û','ﮪ'=>'Ú¾','ﮫ'=>'Ú¾','ﮬ'=>'Ú¾','ï®'=>'Ú¾','ï®®'=>'Û’','ﮯ'=>'Û’','ï®°'=>'Û’Ù”','ï®±'=>'Û’Ù”','ﯓ'=>'Ú','ﯔ'=>'Ú','ﯕ'=>'Ú','ﯖ'=>'Ú','ﯗ'=>'Û‡','ﯘ'=>'Û‡','ﯙ'=>'Û†','ﯚ'=>'Û†','ﯛ'=>'Ûˆ','ﯜ'=>'Ûˆ','ï¯'=>'Û‡Ù´','ﯞ'=>'Û‹','ﯟ'=>'Û‹','ï¯ '=>'Û…','ﯡ'=>'Û…','ﯢ'=>'Û‰','ﯣ'=>'Û‰','ﯤ'=>'Û','ﯥ'=>'Û','ﯦ'=>'Û','ﯧ'=>'Û','ﯨ'=>'Ù‰','ﯩ'=>'Ù‰','ﯪ'=>'ئا','ﯫ'=>'ئا','ﯬ'=>'ÙŠÙ”Û•','ï¯'=>'ÙŠÙ”Û•','ﯮ'=>'ÙŠÙ”Ùˆ','ﯯ'=>'ÙŠÙ”Ùˆ','ﯰ'=>'ÙŠÙ”Û‡','ﯱ'=>'ÙŠÙ”Û‡','ﯲ'=>'ÙŠÙ”Û†','ﯳ'=>'ÙŠÙ”Û†','ﯴ'=>'ÙŠÙ”Ûˆ','ﯵ'=>'ÙŠÙ”Ûˆ','ﯶ'=>'ÙŠÙ”Û','ﯷ'=>'ÙŠÙ”Û','ﯸ'=>'ÙŠÙ”Û','ﯹ'=>'ÙŠÙ”Ù‰','ﯺ'=>'ÙŠÙ”Ù‰','ﯻ'=>'ÙŠÙ”Ù‰','ﯼ'=>'ÛŒ','ﯽ'=>'ÛŒ','ﯾ'=>'ÛŒ','ﯿ'=>'ÛŒ','ï°€'=>'ئج','ï°'=>'ÙŠÙ”Ø','ï°‚'=>'ÙŠÙ”Ù…','ï°ƒ'=>'ÙŠÙ”Ù‰','ï°„'=>'ÙŠÙ”ÙŠ','ï°…'=>'بج','ï°†'=>'بØ','ï°‡'=>'بخ','ï°ˆ'=>'بم','ï°‰'=>'بى','ï°Š'=>'بي','ï°‹'=>'تج','ï°Œ'=>'تØ','ï°'=>'تخ','ï°Ž'=>'تم','ï°'=>'تى','ï°'=>'تي','ï°‘'=>'ثج','ï°’'=>'ثم','ï°“'=>'ثى','ï°”'=>'ثي','ï°•'=>'جØ','ï°–'=>'جم','ï°—'=>'ØØ¬','ï°˜'=>'ØÙ…','ï°™'=>'خج','ï°š'=>'Ø®Ø','ï°›'=>'خم','ï°œ'=>'سج','ï°'=>'سØ','ï°ž'=>'سخ','ï°Ÿ'=>'سم','ï° '=>'صØ','ï°¡'=>'صم','ï°¢'=>'ضج','ï°£'=>'ضØ','ï°¤'=>'ضخ','ï°¥'=>'ضم','ï°¦'=>'Ø·Ø','ï°§'=>'طم','ï°¨'=>'ظم','ï°©'=>'عج','ï°ª'=>'عم','ï°«'=>'غج','ï°¬'=>'غم','ï°'=>'ÙØ¬','ï°®'=>'ÙØ','ï°¯'=>'ÙØ®','ï°°'=>'ÙÙ…','ï°±'=>'ÙÙ‰','ï°²'=>'ÙÙŠ','ï°³'=>'Ù‚Ø','ï°´'=>'قم','ï°µ'=>'قى','ï°¶'=>'قي','ï°·'=>'كا','ï°¸'=>'كج','ï°¹'=>'ÙƒØ','ï°º'=>'كخ','ï°»'=>'كل','ï°¼'=>'كم','ï°½'=>'كى','ï°¾'=>'كي','ï°¿'=>'لج','ï±€'=>'Ù„Ø','ï±'=>'لخ','ﱂ'=>'لم','ﱃ'=>'لى','ﱄ'=>'لي','ï±…'=>'مج','ﱆ'=>'Ù…Ø','ﱇ'=>'مخ','ﱈ'=>'مم','ﱉ'=>'مى','ﱊ'=>'مي','ﱋ'=>'نج','ﱌ'=>'Ù†Ø','ï±'=>'نخ','ﱎ'=>'نم','ï±'=>'نى','ï±'=>'ني','ﱑ'=>'هج','ï±’'=>'هم','ﱓ'=>'هى','ï±”'=>'هي','ﱕ'=>'يج','ï±–'=>'ÙŠØ','ï±—'=>'يخ','ﱘ'=>'يم','ï±™'=>'يى','ﱚ'=>'يي','ï±›'=>'ذٰ','ﱜ'=>'رٰ','ï±'=>'ىٰ','ﱞ'=>' ٌّ','ﱟ'=>' ÙÙ‘','ï± '=>' ÙŽÙ‘','ﱡ'=>' ÙÙ‘','ï±¢'=>' ÙÙ‘','ï±£'=>' ّٰ','ﱤ'=>'ئر','ï±¥'=>'ئز','ﱦ'=>'ÙŠÙ”Ù…','ï±§'=>'ÙŠÙ”Ù†','ﱨ'=>'ÙŠÙ”Ù‰','ﱩ'=>'ÙŠÙ”ÙŠ','ﱪ'=>'بر','ﱫ'=>'بز','ﱬ'=>'بم','ï±'=>'بن','ï±®'=>'بى','ﱯ'=>'بي','ï±°'=>'تر','ï±±'=>'تز','ï±²'=>'تم','ï±³'=>'تن','ï±´'=>'تى','ï±µ'=>'تي','ï±¶'=>'ثر','ï±·'=>'ثز','ﱸ'=>'ثم','ï±¹'=>'ثن','ﱺ'=>'ثى','ï±»'=>'ثي','ï±¼'=>'ÙÙ‰','ï±½'=>'ÙÙŠ','ï±¾'=>'قى','ﱿ'=>'قي','ï²€'=>'كا','ï²'=>'كل','ﲂ'=>'كم','ﲃ'=>'كى','ﲄ'=>'كي','ï²…'=>'لم','ﲆ'=>'لى','ﲇ'=>'لي','ﲈ'=>'ما','ﲉ'=>'مم','ﲊ'=>'نر','ﲋ'=>'نز','ﲌ'=>'نم','ï²'=>'نن','ﲎ'=>'نى','ï²'=>'ني','ï²'=>'ىٰ','ﲑ'=>'ير','ï²’'=>'يز','ﲓ'=>'يم','ï²”'=>'ين','ﲕ'=>'يى','ï²–'=>'يي','ï²—'=>'ئج','ﲘ'=>'ÙŠÙ”Ø','ï²™'=>'ئخ','ﲚ'=>'ÙŠÙ”Ù…','ï²›'=>'ÙŠÙ”Ù‡','ﲜ'=>'بج','ï²'=>'بØ','ﲞ'=>'بخ','ﲟ'=>'بم','ï² '=>'به','ﲡ'=>'تج','ï²¢'=>'تØ','ï²£'=>'تخ','ﲤ'=>'تم','ï²¥'=>'ته','ﲦ'=>'ثم','ï²§'=>'جØ','ﲨ'=>'جم','ﲩ'=>'ØØ¬','ﲪ'=>'ØÙ…','ﲫ'=>'خج','ﲬ'=>'خم','ï²'=>'سج','ï²®'=>'سØ','ﲯ'=>'سخ','ï²°'=>'سم','ï²±'=>'صØ','ï²²'=>'صخ','ï²³'=>'صم','ï²´'=>'ضج','ï²µ'=>'ضØ','ï²¶'=>'ضخ','ï²·'=>'ضم','ﲸ'=>'Ø·Ø','ï²¹'=>'ظم','ﲺ'=>'عج','ï²»'=>'عم','ï²¼'=>'غج','ï²½'=>'غم','ï²¾'=>'ÙØ¬','ﲿ'=>'ÙØ','ï³€'=>'ÙØ®','ï³'=>'ÙÙ…','ﳂ'=>'Ù‚Ø','ﳃ'=>'قم','ﳄ'=>'كج','ï³…'=>'ÙƒØ','ﳆ'=>'كخ','ﳇ'=>'كل','ﳈ'=>'كم','ﳉ'=>'لج','ﳊ'=>'Ù„Ø','ﳋ'=>'لخ','ﳌ'=>'لم','ï³'=>'له','ﳎ'=>'مج','ï³'=>'Ù…Ø','ï³'=>'مخ','ﳑ'=>'مم','ï³’'=>'نج','ﳓ'=>'Ù†Ø','ï³”'=>'نخ','ﳕ'=>'نم','ï³–'=>'نه','ï³—'=>'هج','ﳘ'=>'هم','ï³™'=>'هٰ','ﳚ'=>'يج','ï³›'=>'ÙŠØ','ﳜ'=>'يخ','ï³'=>'يم','ﳞ'=>'يه','ﳟ'=>'ÙŠÙ”Ù…','ï³ '=>'ÙŠÙ”Ù‡','ﳡ'=>'بم','ï³¢'=>'به','ï³£'=>'تم','ﳤ'=>'ته','ï³¥'=>'ثم','ﳦ'=>'ثه','ï³§'=>'سم','ﳨ'=>'سه','ﳩ'=>'شم','ﳪ'=>'شه','ﳫ'=>'كل','ﳬ'=>'كم','ï³'=>'لم','ï³®'=>'نم','ﳯ'=>'نه','ï³°'=>'يم','ï³±'=>'يه','ï³²'=>'Ù€ÙŽÙ‘','ï³³'=>'Ù€ÙÙ‘','ï³´'=>'Ù€ÙÙ‘','ï³µ'=>'طى','ï³¶'=>'طي','ï³·'=>'عى','ﳸ'=>'عي','ï³¹'=>'غى','ﳺ'=>'غي','ï³»'=>'سى','ï³¼'=>'سي','ï³½'=>'شى','ï³¾'=>'شي','ﳿ'=>'ØÙ‰','ï´€'=>'ØÙŠ','ï´'=>'جى','ï´‚'=>'جي','ï´ƒ'=>'خى','ï´„'=>'خي','ï´…'=>'صى','ï´†'=>'صي','ï´‡'=>'ضى','ï´ˆ'=>'ضي','ï´‰'=>'شج','ï´Š'=>'Ø´Ø','ï´‹'=>'شخ','ï´Œ'=>'شم','ï´'=>'شر','ï´Ž'=>'سر','ï´'=>'صر','ï´'=>'ضر','ï´‘'=>'طى','ï´’'=>'طي','ï´“'=>'عى','ï´”'=>'عي','ï´•'=>'غى','ï´–'=>'غي','ï´—'=>'سى','ï´˜'=>'سي','ï´™'=>'شى','ï´š'=>'شي','ï´›'=>'ØÙ‰','ï´œ'=>'ØÙŠ','ï´'=>'جى','ï´ž'=>'جي','ï´Ÿ'=>'خى','ï´ '=>'خي','ï´¡'=>'صى','ï´¢'=>'صي','ï´£'=>'ضى','ï´¤'=>'ضي','ï´¥'=>'شج','ï´¦'=>'Ø´Ø','ï´§'=>'شخ','ï´¨'=>'شم','ï´©'=>'شر','ï´ª'=>'سر','ï´«'=>'صر','ï´¬'=>'ضر','ï´'=>'شج','ï´®'=>'Ø´Ø','ï´¯'=>'شخ','ï´°'=>'شم','ï´±'=>'سه','ï´²'=>'شه','ï´³'=>'طم','ï´´'=>'سج','ï´µ'=>'سØ','ï´¶'=>'سخ','ï´·'=>'شج','ï´¸'=>'Ø´Ø','ï´¹'=>'شخ','ï´º'=>'طم','ï´»'=>'ظم','ï´¼'=>'اً','ï´½'=>'اً','ïµ'=>'تجم','ﵑ'=>'ØªØØ¬','ïµ’'=>'ØªØØ¬','ﵓ'=>'تØÙ…','ïµ”'=>'تخم','ﵕ'=>'تمج','ïµ–'=>'تمØ','ïµ—'=>'تمخ','ﵘ'=>'جمØ','ïµ™'=>'جمØ','ﵚ'=>'ØÙ…ÙŠ','ïµ›'=>'ØÙ…Ù‰','ﵜ'=>'Ø³ØØ¬','ïµ'=>'سجØ','ﵞ'=>'سجى','ﵟ'=>'سمØ','ïµ '=>'سمØ','ﵡ'=>'سمج','ïµ¢'=>'سمم','ïµ£'=>'سمم','ﵤ'=>'ØµØØ','ïµ¥'=>'ØµØØ','ﵦ'=>'صمم','ïµ§'=>'Ø´ØÙ…','ﵨ'=>'Ø´ØÙ…','ﵩ'=>'شجي','ﵪ'=>'شمخ','ﵫ'=>'شمخ','ﵬ'=>'شمم','ïµ'=>'شمم','ïµ®'=>'ضØÙ‰','ﵯ'=>'ضخم','ïµ°'=>'ضخم','ïµ±'=>'طمØ','ïµ²'=>'طمØ','ïµ³'=>'طمم','ïµ´'=>'طمي','ïµµ'=>'عجم','ïµ¶'=>'عمم','ïµ·'=>'عمم','ﵸ'=>'عمى','ïµ¹'=>'غمم','ﵺ'=>'غمي','ïµ»'=>'غمى','ïµ¼'=>'ÙØ®Ù…','ïµ½'=>'ÙØ®Ù…','ïµ¾'=>'قمØ','ﵿ'=>'قمم','ï¶€'=>'Ù„ØÙ…','ï¶'=>'Ù„ØÙŠ','ï¶‚'=>'Ù„ØÙ‰','ﶃ'=>'لجج','ï¶„'=>'لجج','ï¶…'=>'لخم','ﶆ'=>'لخم','ﶇ'=>'لمØ','ﶈ'=>'لمØ','ﶉ'=>'Ù…ØØ¬','ï¶Š'=>'Ù…ØÙ…','ï¶‹'=>'Ù…ØÙŠ','ï¶Œ'=>'مجØ','ï¶'=>'مجم','ï¶Ž'=>'مخج','ï¶'=>'مخم','ï¶’'=>'مجخ','ï¶“'=>'همج','ï¶”'=>'همم','ï¶•'=>'Ù†ØÙ…','ï¶–'=>'Ù†ØÙ‰','ï¶—'=>'نجم','ﶘ'=>'نجم','ï¶™'=>'نجى','ï¶š'=>'نمي','ï¶›'=>'نمى','ï¶œ'=>'يمم','ï¶'=>'يمم','ï¶ž'=>'بخي','ï¶Ÿ'=>'تجي','ï¶ '=>'تجى','ï¶¡'=>'تخي','ï¶¢'=>'تخى','ï¶£'=>'تمي','ﶤ'=>'تمى','ï¶¥'=>'جمي','ﶦ'=>'جØÙ‰','ï¶§'=>'جمى','ﶨ'=>'سخى','ï¶©'=>'صØÙŠ','ﶪ'=>'Ø´ØÙŠ','ï¶«'=>'ضØÙŠ','ﶬ'=>'لجي','ï¶'=>'لمي','ï¶®'=>'ÙŠØÙŠ','ﶯ'=>'يجي','ï¶°'=>'يمي','ï¶±'=>'ممي','ï¶²'=>'قمي','ï¶³'=>'Ù†ØÙŠ','ï¶´'=>'قمØ','ï¶µ'=>'Ù„ØÙ…','ï¶¶'=>'عمي','ï¶·'=>'كمي','ﶸ'=>'نجØ','ï¶¹'=>'مخي','ﶺ'=>'لجم','ï¶»'=>'كمم','ï¶¼'=>'لجم','ï¶½'=>'نجØ','ï¶¾'=>'جØÙŠ','ï¶¿'=>'ØØ¬ÙŠ','ï·€'=>'مجي','ï·'=>'Ùمي','ï·‚'=>'بØÙŠ','ï·ƒ'=>'كمم','ï·„'=>'عجم','ï·…'=>'صمم','ï·†'=>'سخي','ï·‡'=>'نجي','ï·°'=>'صلے','ï·±'=>'قلے','ï·²'=>'الله','ï·³'=>'اكبر','ï·´'=>'Ù…ØÙ…د','ï·µ'=>'صلعم','ï·¶'=>'رسول','ï··'=>'عليه','ï·¸'=>'وسلم','ï·¹'=>'صلى','ï·º'=>'صلى الله عليه وسلم','ï·»'=>'جل جلاله','ï·¼'=>'ریال','ï¸'=>',','︑'=>'ã€','︒'=>'。','︓'=>':','︔'=>';','︕'=>'!','︖'=>'?','︗'=>'〖','︘'=>'〗','︙'=>'...','︰'=>'..','︱'=>'—','︲'=>'–','︳'=>'_','︴'=>'_','︵'=>'(','︶'=>')','︷'=>'{','︸'=>'}','︹'=>'〔','︺'=>'〕','︻'=>'ã€','︼'=>'】','︽'=>'《','︾'=>'》','︿'=>'〈','ï¹€'=>'〉','ï¹'=>'「','﹂'=>'ã€','﹃'=>'『','﹄'=>'ã€','﹇'=>'[','﹈'=>']','﹉'=>' Ì…','﹊'=>' Ì…','﹋'=>' Ì…','﹌'=>' Ì…','ï¹'=>'_','﹎'=>'_','ï¹'=>'_','ï¹'=>',','﹑'=>'ã€','ï¹’'=>'.','ï¹”'=>';','﹕'=>':','ï¹–'=>'?','ï¹—'=>'!','﹘'=>'—','ï¹™'=>'(','﹚'=>')','ï¹›'=>'{','﹜'=>'}','ï¹'=>'〔','﹞'=>'〕','﹟'=>'#','ï¹ '=>'&','﹡'=>'*','ï¹¢'=>'+','ï¹£'=>'-','﹤'=>'<','ï¹¥'=>'>','﹦'=>'=','﹨'=>'\\','﹩'=>'$','﹪'=>'%','﹫'=>'@','ï¹°'=>' Ù‹','ï¹±'=>'ـً','ï¹²'=>' ÙŒ','ï¹´'=>' Ù','ï¹¶'=>' ÙŽ','ï¹·'=>'Ù€ÙŽ','ﹸ'=>' Ù','ï¹¹'=>'Ù€Ù','ﹺ'=>' Ù','ï¹»'=>'Ù€Ù','ï¹¼'=>' Ù‘','ï¹½'=>'ـّ','ï¹¾'=>' Ù’','ﹿ'=>'ـْ','ﺀ'=>'Ø¡','ïº'=>'آ','ﺂ'=>'آ','ﺃ'=>'أ','ﺄ'=>'أ','ﺅ'=>'ÙˆÙ”','ﺆ'=>'ÙˆÙ”','ﺇ'=>'إ','ﺈ'=>'إ','ﺉ'=>'ÙŠÙ”','ﺊ'=>'ÙŠÙ”','ﺋ'=>'ÙŠÙ”','ﺌ'=>'ÙŠÙ”','ïº'=>'ا','ﺎ'=>'ا','ïº'=>'ب','ïº'=>'ب','ﺑ'=>'ب','ﺒ'=>'ب','ﺓ'=>'Ø©','ﺔ'=>'Ø©','ﺕ'=>'ت','ﺖ'=>'ت','ﺗ'=>'ت','ﺘ'=>'ت','ﺙ'=>'Ø«','ﺚ'=>'Ø«','ﺛ'=>'Ø«','ﺜ'=>'Ø«','ïº'=>'ج','ﺞ'=>'ج','ﺟ'=>'ج','ïº '=>'ج','ﺡ'=>'Ø','ﺢ'=>'Ø','ﺣ'=>'Ø','ﺤ'=>'Ø','ﺥ'=>'Ø®','ﺦ'=>'Ø®','ﺧ'=>'Ø®','ﺨ'=>'Ø®','ﺩ'=>'د','ﺪ'=>'د','ﺫ'=>'ذ','ﺬ'=>'ذ','ïº'=>'ر','ﺮ'=>'ر','ﺯ'=>'ز','ﺰ'=>'ز','ﺱ'=>'س','ﺲ'=>'س','ﺳ'=>'س','ﺴ'=>'س','ﺵ'=>'Ø´','ﺶ'=>'Ø´','ﺷ'=>'Ø´','ﺸ'=>'Ø´','ﺹ'=>'ص','ﺺ'=>'ص','ﺻ'=>'ص','ﺼ'=>'ص','ﺽ'=>'ض','ﺾ'=>'ض','ﺿ'=>'ض','ﻀ'=>'ض','ï»'=>'Ø·','ﻂ'=>'Ø·','ﻃ'=>'Ø·','ﻄ'=>'Ø·','ï»…'=>'ظ','ﻆ'=>'ظ','ﻇ'=>'ظ','ﻈ'=>'ظ','ﻉ'=>'ع','ﻊ'=>'ع','ﻋ'=>'ع','ﻌ'=>'ع','ï»'=>'غ','ﻎ'=>'غ','ï»'=>'غ','ï»'=>'غ','ﻑ'=>'Ù','ï»’'=>'Ù','ﻓ'=>'Ù','ï»”'=>'Ù','ﻕ'=>'Ù‚','ï»–'=>'Ù‚','ï»—'=>'Ù‚','ﻘ'=>'Ù‚','ï»™'=>'Ùƒ','ﻚ'=>'Ùƒ','ï»›'=>'Ùƒ','ﻜ'=>'Ùƒ','ï»'=>'Ù„','ﻞ'=>'Ù„','ﻟ'=>'Ù„','ï» '=>'Ù„','ﻡ'=>'Ù…','ﻢ'=>'Ù…','ﻣ'=>'Ù…','ﻤ'=>'Ù…','ﻥ'=>'Ù†','ﻦ'=>'Ù†','ï»§'=>'Ù†','ﻨ'=>'Ù†','ﻩ'=>'Ù‡','ﻪ'=>'Ù‡','ﻫ'=>'Ù‡','ﻬ'=>'Ù‡','ï»'=>'Ùˆ','ï»®'=>'Ùˆ','ﻯ'=>'Ù‰','ï»°'=>'Ù‰','ï»±'=>'ÙŠ','ﻲ'=>'ÙŠ','ﻳ'=>'ÙŠ','ï»´'=>'ÙŠ','ﻵ'=>'لآ','ï»¶'=>'لآ','ï»·'=>'لأ','ﻸ'=>'لأ','ﻹ'=>'لإ','ﻺ'=>'لإ','ï»»'=>'لا','ﻼ'=>'لا','ï¼'=>'!','"'=>'"','#'=>'#','$'=>'$','ï¼…'=>'%','&'=>'&','''=>'\'','('=>'(',')'=>')','*'=>'*','+'=>'+',','=>',','ï¼'=>'-','.'=>'.','ï¼'=>'/','ï¼'=>'0','1'=>'1','ï¼’'=>'2','3'=>'3','ï¼”'=>'4','5'=>'5','ï¼–'=>'6','ï¼—'=>'7','8'=>'8','ï¼™'=>'9',':'=>':','ï¼›'=>';','<'=>'<','ï¼'=>'=','>'=>'>','?'=>'?','ï¼ '=>'@','A'=>'A','ï¼¢'=>'B','ï¼£'=>'C','D'=>'D','ï¼¥'=>'E','F'=>'F','ï¼§'=>'G','H'=>'H','I'=>'I','J'=>'J','K'=>'K','L'=>'L','ï¼'=>'M','ï¼®'=>'N','O'=>'O','ï¼°'=>'P','ï¼±'=>'Q','ï¼²'=>'R','ï¼³'=>'S','ï¼´'=>'T','ï¼µ'=>'U','ï¼¶'=>'V','ï¼·'=>'W','X'=>'X','ï¼¹'=>'Y','Z'=>'Z','ï¼»'=>'[','ï¼¼'=>'\\','ï¼½'=>']','ï¼¾'=>'^','_'=>'_','ï½€'=>'`','ï½'=>'a','b'=>'b','c'=>'c','d'=>'d','ï½…'=>'e','f'=>'f','g'=>'g','h'=>'h','i'=>'i','j'=>'j','k'=>'k','l'=>'l','ï½'=>'m','n'=>'n','ï½'=>'o','ï½'=>'p','q'=>'q','ï½’'=>'r','s'=>'s','ï½”'=>'t','u'=>'u','ï½–'=>'v','ï½—'=>'w','x'=>'x','ï½™'=>'y','z'=>'z','ï½›'=>'{','|'=>'|','ï½'=>'}','~'=>'~','⦅'=>'⦅','ï½ '=>'⦆','。'=>'。','ï½¢'=>'「','ï½£'=>'ã€','、'=>'ã€','ï½¥'=>'・','ヲ'=>'ヲ','ï½§'=>'ã‚¡','ィ'=>'ã‚£','ゥ'=>'ã‚¥','ェ'=>'ã‚§','ォ'=>'ã‚©','ャ'=>'ャ','ï½'=>'ュ','ï½®'=>'ョ','ッ'=>'ッ','ï½°'=>'ー','ï½±'=>'ã‚¢','ï½²'=>'イ','ï½³'=>'ウ','ï½´'=>'エ','ï½µ'=>'オ','ï½¶'=>'ã‚«','ï½·'=>'ã‚','ク'=>'ク','ï½¹'=>'ケ','コ'=>'コ','ï½»'=>'サ','ï½¼'=>'ã‚·','ï½½'=>'ス','ï½¾'=>'ã‚»','ソ'=>'ソ','ï¾€'=>'ã‚¿','ï¾'=>'ãƒ','ツ'=>'ツ','テ'=>'テ','ト'=>'ト','ï¾…'=>'ナ','ニ'=>'ニ','ヌ'=>'ヌ','ネ'=>'ãƒ','ノ'=>'ノ','ハ'=>'ãƒ','ヒ'=>'ヒ','フ'=>'フ','ï¾'=>'ヘ','ホ'=>'ホ','ï¾'=>'マ','ï¾'=>'ミ','ム'=>'ム','ï¾’'=>'メ','モ'=>'モ','ï¾”'=>'ヤ','ユ'=>'ユ','ï¾–'=>'ヨ','ï¾—'=>'ラ','リ'=>'リ','ï¾™'=>'ル','レ'=>'レ','ï¾›'=>'ãƒ','ワ'=>'ワ','ï¾'=>'ン','゙'=>'ã‚™','゚'=>'゚','ï¾ '=>'á… ','ᄀ'=>'á„€','ï¾¢'=>'á„','ï¾£'=>'ᆪ','ᄂ'=>'á„‚','ï¾¥'=>'ᆬ','ᆭ'=>'á†','ï¾§'=>'ᄃ','ᄄ'=>'á„„','ᄅ'=>'á„…','ᆰ'=>'ᆰ','ᆱ'=>'ᆱ','ᆲ'=>'ᆲ','ï¾'=>'ᆳ','ï¾®'=>'ᆴ','ᆵ'=>'ᆵ','ï¾°'=>'ᄚ','ï¾±'=>'ᄆ','ï¾²'=>'ᄇ','ï¾³'=>'ᄈ','ï¾´'=>'á„¡','ï¾µ'=>'ᄉ','ï¾¶'=>'ᄊ','ï¾·'=>'á„‹','ᄌ'=>'ᄌ','ï¾¹'=>'á„','ᄎ'=>'ᄎ','ï¾»'=>'á„','ï¾¼'=>'á„','ï¾½'=>'á„‘','ï¾¾'=>'á„’','ï¿‚'=>'á…¡','ᅢ'=>'á…¢','ï¿„'=>'á…£','ï¿…'=>'á…¤','ᅥ'=>'á…¥','ᅦ'=>'á…¦','ᅧ'=>'á…§','ï¿‹'=>'á…¨','ᅩ'=>'á…©','ï¿'=>'á…ª','ᅫ'=>'á…«','ï¿'=>'á…¬','ï¿’'=>'á…','ï¿“'=>'á…®','ï¿”'=>'á…¯','ï¿•'=>'á…°','ï¿–'=>'á…±','ï¿—'=>'á…²','ᅳ'=>'á…³','ï¿›'=>'á…´','ᅵ'=>'á…µ','ï¿ '=>'¢','ï¿¡'=>'£','ï¿¢'=>'¬','ï¿£'=>' Ì„','¦'=>'¦','ï¿¥'=>'Â¥','₩'=>'â‚©','│'=>'│','ï¿©'=>'â†','↑'=>'↑','ï¿«'=>'→','↓'=>'↓','ï¿'=>'â– ','ï¿®'=>'â—‹','ð…ž'=>'ð…—ð…¥','ð…Ÿ'=>'ð…˜ð…¥','ð… '=>'ð…˜ð…¥ð…®','ð…¡'=>'ð…˜ð…¥ð…¯','ð…¢'=>'ð…˜ð…¥ð…°','ð…£'=>'ð…˜ð…¥ð…±','ð…¤'=>'ð…˜ð…¥ð…²','ð†»'=>'ð†¹ð…¥','ð†¼'=>'ð†ºð…¥','ð†½'=>'ð†¹ð…¥ð…®','ð†¾'=>'ð†ºð…¥ð…®','ð†¿'=>'ð†¹ð…¥ð…¯','ð‡€'=>'ð†ºð…¥ð…¯','ð€'=>'A','ð'=>'B','ð‚'=>'C','ðƒ'=>'D','ð„'=>'E','ð…'=>'F','ð†'=>'G','ð‡'=>'H','ðˆ'=>'I','ð‰'=>'J','ðŠ'=>'K','ð‹'=>'L','ðŒ'=>'M','ð'=>'N','ðŽ'=>'O','ð'=>'P','ð'=>'Q','ð‘'=>'R','ð’'=>'S','ð“'=>'T','ð”'=>'U','ð•'=>'V','ð–'=>'W','ð—'=>'X','ð˜'=>'Y','ð™'=>'Z','ðš'=>'a','ð›'=>'b','ðœ'=>'c','ð'=>'d','ðž'=>'e','ðŸ'=>'f','ð '=>'g','ð¡'=>'h','ð¢'=>'i','ð£'=>'j','ð¤'=>'k','ð¥'=>'l','ð¦'=>'m','ð§'=>'n','ð¨'=>'o','ð©'=>'p','ðª'=>'q','ð«'=>'r','ð¬'=>'s','ð'=>'t','ð®'=>'u','ð¯'=>'v','ð°'=>'w','ð±'=>'x','ð²'=>'y','ð³'=>'z','ð´'=>'A','ðµ'=>'B','ð¶'=>'C','ð·'=>'D','ð¸'=>'E','ð¹'=>'F','ðº'=>'G','ð»'=>'H','ð¼'=>'I','ð½'=>'J','ð¾'=>'K','ð¿'=>'L','ð‘€'=>'M','ð‘'=>'N','ð‘‚'=>'O','ð‘ƒ'=>'P','ð‘„'=>'Q','ð‘…'=>'R','ð‘†'=>'S','ð‘‡'=>'T','ð‘ˆ'=>'U','ð‘‰'=>'V','ð‘Š'=>'W','ð‘‹'=>'X','ð‘Œ'=>'Y','ð‘'=>'Z','ð‘Ž'=>'a','ð‘'=>'b','ð‘'=>'c','ð‘‘'=>'d','ð‘’'=>'e','ð‘“'=>'f','ð‘”'=>'g','ð‘–'=>'i','ð‘—'=>'j','ð‘˜'=>'k','ð‘™'=>'l','ð‘š'=>'m','ð‘›'=>'n','ð‘œ'=>'o','ð‘'=>'p','ð‘ž'=>'q','ð‘Ÿ'=>'r','ð‘ '=>'s','ð‘¡'=>'t','ð‘¢'=>'u','ð‘£'=>'v','ð‘¤'=>'w','ð‘¥'=>'x','ð‘¦'=>'y','ð‘§'=>'z','ð‘¨'=>'A','ð‘©'=>'B','ð‘ª'=>'C','ð‘«'=>'D','ð‘¬'=>'E','ð‘'=>'F','ð‘®'=>'G','ð‘¯'=>'H','ð‘°'=>'I','ð‘±'=>'J','ð‘²'=>'K','ð‘³'=>'L','ð‘´'=>'M','ð‘µ'=>'N','ð‘¶'=>'O','ð‘·'=>'P','ð‘¸'=>'Q','ð‘¹'=>'R','ð‘º'=>'S','ð‘»'=>'T','ð‘¼'=>'U','ð‘½'=>'V','ð‘¾'=>'W','ð‘¿'=>'X','ð’€'=>'Y','ð’'=>'Z','ð’‚'=>'a','ð’ƒ'=>'b','ð’„'=>'c','ð’…'=>'d','ð’†'=>'e','ð’‡'=>'f','ð’ˆ'=>'g','ð’‰'=>'h','ð’Š'=>'i','ð’‹'=>'j','ð’Œ'=>'k','ð’'=>'l','ð’Ž'=>'m','ð’'=>'n','ð’'=>'o','ð’‘'=>'p','ð’’'=>'q','ð’“'=>'r','ð’”'=>'s','ð’•'=>'t','ð’–'=>'u','ð’—'=>'v','ð’˜'=>'w','ð’™'=>'x','ð’š'=>'y','ð’›'=>'z','ð’œ'=>'A','ð’ž'=>'C','ð’Ÿ'=>'D','ð’¢'=>'G','ð’¥'=>'J','ð’¦'=>'K','ð’©'=>'N','ð’ª'=>'O','ð’«'=>'P','ð’¬'=>'Q','ð’®'=>'S','ð’¯'=>'T','ð’°'=>'U','ð’±'=>'V','ð’²'=>'W','ð’³'=>'X','ð’´'=>'Y','ð’µ'=>'Z','ð’¶'=>'a','ð’·'=>'b','ð’¸'=>'c','ð’¹'=>'d','ð’»'=>'f','ð’½'=>'h','ð’¾'=>'i','ð’¿'=>'j','ð“€'=>'k','ð“'=>'l','ð“‚'=>'m','ð“ƒ'=>'n','ð“…'=>'p','ð“†'=>'q','ð“‡'=>'r','ð“ˆ'=>'s','ð“‰'=>'t','ð“Š'=>'u','ð“‹'=>'v','ð“Œ'=>'w','ð“'=>'x','ð“Ž'=>'y','ð“'=>'z','ð“'=>'A','ð“‘'=>'B','ð“’'=>'C','ð““'=>'D','ð“”'=>'E','ð“•'=>'F','ð“–'=>'G','ð“—'=>'H','ð“˜'=>'I','ð“™'=>'J','ð“š'=>'K','ð“›'=>'L','ð“œ'=>'M','ð“'=>'N','ð“ž'=>'O','ð“Ÿ'=>'P','ð“ '=>'Q','ð“¡'=>'R','ð“¢'=>'S','ð“£'=>'T','ð“¤'=>'U','ð“¥'=>'V','ð“¦'=>'W','ð“§'=>'X','ð“¨'=>'Y','ð“©'=>'Z','ð“ª'=>'a','ð“«'=>'b','ð“¬'=>'c','ð“'=>'d','ð“®'=>'e','ð“¯'=>'f','ð“°'=>'g','ð“±'=>'h','ð“²'=>'i','ð“³'=>'j','ð“´'=>'k','ð“µ'=>'l','ð“¶'=>'m','ð“·'=>'n','ð“¸'=>'o','ð“¹'=>'p','ð“º'=>'q','ð“»'=>'r','ð“¼'=>'s','ð“½'=>'t','ð“¾'=>'u','ð“¿'=>'v','ð”€'=>'w','ð”'=>'x','ð”‚'=>'y','ð”ƒ'=>'z','ð”„'=>'A','ð”…'=>'B','ð”‡'=>'D','ð”ˆ'=>'E','ð”‰'=>'F','ð”Š'=>'G','ð”'=>'J','ð”Ž'=>'K','ð”'=>'L','ð”'=>'M','ð”‘'=>'N','ð”’'=>'O','ð”“'=>'P','ð””'=>'Q','ð”–'=>'S','ð”—'=>'T','ð”˜'=>'U','ð”™'=>'V','ð”š'=>'W','ð”›'=>'X','ð”œ'=>'Y','ð”ž'=>'a','ð”Ÿ'=>'b','ð” '=>'c','ð”¡'=>'d','ð”¢'=>'e','ð”£'=>'f','ð”¤'=>'g','ð”¥'=>'h','ð”¦'=>'i','ð”§'=>'j','ð”¨'=>'k','ð”©'=>'l','ð”ª'=>'m','ð”«'=>'n','ð”¬'=>'o','ð”'=>'p','ð”®'=>'q','ð”¯'=>'r','ð”°'=>'s','ð”±'=>'t','ð”²'=>'u','ð”³'=>'v','ð”´'=>'w','ð”µ'=>'x','ð”¶'=>'y','ð”·'=>'z','ð”¸'=>'A','ð”¹'=>'B','ð”»'=>'D','ð”¼'=>'E','ð”½'=>'F','ð”¾'=>'G','ð•€'=>'I','ð•'=>'J','ð•‚'=>'K','ð•ƒ'=>'L','ð•„'=>'M','ð•†'=>'O','ð•Š'=>'S','ð•‹'=>'T','ð•Œ'=>'U','ð•'=>'V','ð•Ž'=>'W','ð•'=>'X','ð•'=>'Y','ð•’'=>'a','ð•“'=>'b','ð•”'=>'c','ð••'=>'d','ð•–'=>'e','ð•—'=>'f','ð•˜'=>'g','ð•™'=>'h','ð•š'=>'i','ð•›'=>'j','ð•œ'=>'k','ð•'=>'l','ð•ž'=>'m','ð•Ÿ'=>'n','ð• '=>'o','ð•¡'=>'p','ð•¢'=>'q','ð•£'=>'r','ð•¤'=>'s','ð•¥'=>'t','ð•¦'=>'u','ð•§'=>'v','ð•¨'=>'w','ð•©'=>'x','ð•ª'=>'y','ð•«'=>'z','ð•¬'=>'A','ð•'=>'B','ð•®'=>'C','ð•¯'=>'D','ð•°'=>'E','ð•±'=>'F','ð•²'=>'G','ð•³'=>'H','ð•´'=>'I','ð•µ'=>'J','ð•¶'=>'K','ð•·'=>'L','ð•¸'=>'M','ð•¹'=>'N','ð•º'=>'O','ð•»'=>'P','ð•¼'=>'Q','ð•½'=>'R','ð•¾'=>'S','ð•¿'=>'T','ð–€'=>'U','ð–'=>'V','ð–‚'=>'W','ð–ƒ'=>'X','ð–„'=>'Y','ð–…'=>'Z','ð–†'=>'a','ð–‡'=>'b','ð–ˆ'=>'c','ð–‰'=>'d','ð–Š'=>'e','ð–‹'=>'f','ð–Œ'=>'g','ð–'=>'h','ð–Ž'=>'i','ð–'=>'j','ð–'=>'k','ð–‘'=>'l','ð–’'=>'m','ð–“'=>'n','ð–”'=>'o','ð–•'=>'p','ð––'=>'q','ð–—'=>'r','ð–˜'=>'s','ð–™'=>'t','ð–š'=>'u','ð–›'=>'v','ð–œ'=>'w','ð–'=>'x','ð–ž'=>'y','ð–Ÿ'=>'z','ð– '=>'A','ð–¡'=>'B','ð–¢'=>'C','ð–£'=>'D','ð–¤'=>'E','ð–¥'=>'F','ð–¦'=>'G','ð–§'=>'H','ð–¨'=>'I','ð–©'=>'J','ð–ª'=>'K','ð–«'=>'L','ð–¬'=>'M','ð–'=>'N','ð–®'=>'O','ð–¯'=>'P','ð–°'=>'Q','ð–±'=>'R','ð–²'=>'S','ð–³'=>'T','ð–´'=>'U','ð–µ'=>'V','ð–¶'=>'W','ð–·'=>'X','ð–¸'=>'Y','ð–¹'=>'Z','ð–º'=>'a','ð–»'=>'b','ð–¼'=>'c','ð–½'=>'d','ð–¾'=>'e','ð–¿'=>'f','ð—€'=>'g','ð—'=>'h','ð—‚'=>'i','ð—ƒ'=>'j','ð—„'=>'k','ð—…'=>'l','ð—†'=>'m','ð—‡'=>'n','ð—ˆ'=>'o','ð—‰'=>'p','ð—Š'=>'q','ð—‹'=>'r','ð—Œ'=>'s','ð—'=>'t','ð—Ž'=>'u','ð—'=>'v','ð—'=>'w','ð—‘'=>'x','ð—’'=>'y','ð—“'=>'z','ð—”'=>'A','ð—•'=>'B','ð—–'=>'C','ð——'=>'D','ð—˜'=>'E','ð—™'=>'F','ð—š'=>'G','ð—›'=>'H','ð—œ'=>'I','ð—'=>'J','ð—ž'=>'K','ð—Ÿ'=>'L','ð— '=>'M','ð—¡'=>'N','ð—¢'=>'O','ð—£'=>'P','ð—¤'=>'Q','ð—¥'=>'R','ð—¦'=>'S','ð—§'=>'T','ð—¨'=>'U','ð—©'=>'V','ð—ª'=>'W','ð—«'=>'X','ð—¬'=>'Y','ð—'=>'Z','ð—®'=>'a','ð—¯'=>'b','ð—°'=>'c','ð—±'=>'d','ð—²'=>'e','ð—³'=>'f','ð—´'=>'g','ð—µ'=>'h','ð—¶'=>'i','ð—·'=>'j','ð—¸'=>'k','ð—¹'=>'l','ð—º'=>'m','ð—»'=>'n','ð—¼'=>'o','ð—½'=>'p','ð—¾'=>'q','ð—¿'=>'r','ð˜€'=>'s','ð˜'=>'t','ð˜‚'=>'u','ð˜ƒ'=>'v','ð˜„'=>'w','ð˜…'=>'x','ð˜†'=>'y','ð˜‡'=>'z','ð˜ˆ'=>'A','ð˜‰'=>'B','ð˜Š'=>'C','ð˜‹'=>'D','ð˜Œ'=>'E','ð˜'=>'F','ð˜Ž'=>'G','ð˜'=>'H','ð˜'=>'I','ð˜‘'=>'J','ð˜’'=>'K','ð˜“'=>'L','ð˜”'=>'M','ð˜•'=>'N','ð˜–'=>'O','ð˜—'=>'P','ð˜˜'=>'Q','ð˜™'=>'R','ð˜š'=>'S','ð˜›'=>'T','ð˜œ'=>'U','ð˜'=>'V','ð˜ž'=>'W','ð˜Ÿ'=>'X','ð˜ '=>'Y','ð˜¡'=>'Z','ð˜¢'=>'a','ð˜£'=>'b','ð˜¤'=>'c','ð˜¥'=>'d','ð˜¦'=>'e','ð˜§'=>'f','ð˜¨'=>'g','ð˜©'=>'h','ð˜ª'=>'i','ð˜«'=>'j','ð˜¬'=>'k','ð˜'=>'l','ð˜®'=>'m','ð˜¯'=>'n','ð˜°'=>'o','ð˜±'=>'p','ð˜²'=>'q','ð˜³'=>'r','ð˜´'=>'s','ð˜µ'=>'t','ð˜¶'=>'u','ð˜·'=>'v','ð˜¸'=>'w','ð˜¹'=>'x','ð˜º'=>'y','ð˜»'=>'z','ð˜¼'=>'A','ð˜½'=>'B','ð˜¾'=>'C','ð˜¿'=>'D','ð™€'=>'E','ð™'=>'F','ð™‚'=>'G','ð™ƒ'=>'H','ð™„'=>'I','ð™…'=>'J','ð™†'=>'K','ð™‡'=>'L','ð™ˆ'=>'M','ð™‰'=>'N','ð™Š'=>'O','ð™‹'=>'P','ð™Œ'=>'Q','ð™'=>'R','ð™Ž'=>'S','ð™'=>'T','ð™'=>'U','ð™‘'=>'V','ð™’'=>'W','ð™“'=>'X','ð™”'=>'Y','ð™•'=>'Z','ð™–'=>'a','ð™—'=>'b','ð™˜'=>'c','ð™™'=>'d','ð™š'=>'e','ð™›'=>'f','ð™œ'=>'g','ð™'=>'h','ð™ž'=>'i','ð™Ÿ'=>'j','ð™ '=>'k','ð™¡'=>'l','ð™¢'=>'m','ð™£'=>'n','ð™¤'=>'o','ð™¥'=>'p','ð™¦'=>'q','ð™§'=>'r','ð™¨'=>'s','ð™©'=>'t','ð™ª'=>'u','ð™«'=>'v','ð™¬'=>'w','ð™'=>'x','ð™®'=>'y','ð™¯'=>'z','ð™°'=>'A','ð™±'=>'B','ð™²'=>'C','ð™³'=>'D','ð™´'=>'E','ð™µ'=>'F','ð™¶'=>'G','ð™·'=>'H','ð™¸'=>'I','ð™¹'=>'J','ð™º'=>'K','ð™»'=>'L','ð™¼'=>'M','ð™½'=>'N','ð™¾'=>'O','ð™¿'=>'P','ðš€'=>'Q','ðš'=>'R','ðš‚'=>'S','ðšƒ'=>'T','ðš„'=>'U','ðš…'=>'V','ðš†'=>'W','ðš‡'=>'X','ðšˆ'=>'Y','ðš‰'=>'Z','ðšŠ'=>'a','ðš‹'=>'b','ðšŒ'=>'c','ðš'=>'d','ðšŽ'=>'e','ðš'=>'f','ðš'=>'g','ðš‘'=>'h','ðš’'=>'i','ðš“'=>'j','ðš”'=>'k','ðš•'=>'l','ðš–'=>'m','ðš—'=>'n','ðš˜'=>'o','ðš™'=>'p','ðšš'=>'q','ðš›'=>'r','ðšœ'=>'s','ðš'=>'t','ðšž'=>'u','ðšŸ'=>'v','ðš '=>'w','ðš¡'=>'x','ðš¢'=>'y','ðš£'=>'z','ðš¤'=>'ı','ðš¥'=>'È·','ðš¨'=>'Α','ðš©'=>'Î’','ðšª'=>'Γ','ðš«'=>'Δ','ðš¬'=>'Ε','ðš'=>'Ζ','ðš®'=>'Η','ðš¯'=>'Θ','ðš°'=>'Ι','ðš±'=>'Κ','ðš²'=>'Λ','ðš³'=>'Μ','ðš´'=>'Î','ðšµ'=>'Ξ','ðš¶'=>'Ο','ðš·'=>'Î ','ðš¸'=>'Ρ','ðš¹'=>'Θ','ðšº'=>'Σ','ðš»'=>'Τ','ðš¼'=>'Î¥','ðš½'=>'Φ','ðš¾'=>'Χ','ðš¿'=>'Ψ','ð›€'=>'Ω','ð›'=>'∇','ð›‚'=>'α','ð›ƒ'=>'β','ð›„'=>'γ','ð›…'=>'δ','ð›†'=>'ε','ð›‡'=>'ζ','ð›ˆ'=>'η','ð›‰'=>'θ','ð›Š'=>'ι','ð›‹'=>'κ','ð›Œ'=>'λ','ð›'=>'μ','ð›Ž'=>'ν','ð›'=>'ξ','ð›'=>'ο','ð›‘'=>'Ï€','ð›’'=>'Ï','ð›“'=>'Ï‚','ð›”'=>'σ','ð›•'=>'Ï„','ð›–'=>'Ï…','ð›—'=>'φ','ð›˜'=>'χ','ð›™'=>'ψ','ð›š'=>'ω','ð››'=>'∂','ð›œ'=>'ε','ð›'=>'θ','ð›ž'=>'κ','ð›Ÿ'=>'φ','ð› '=>'Ï','ð›¡'=>'Ï€','ð›¢'=>'Α','ð›£'=>'Î’','ð›¤'=>'Γ','ð›¥'=>'Δ','ð›¦'=>'Ε','ð›§'=>'Ζ','ð›¨'=>'Η','ð›©'=>'Θ','ð›ª'=>'Ι','ð›«'=>'Κ','ð›¬'=>'Λ','ð›'=>'Μ','ð›®'=>'Î','ð›¯'=>'Ξ','ð›°'=>'Ο','ð›±'=>'Î ','ð›²'=>'Ρ','ð›³'=>'Θ','ð›´'=>'Σ','ð›µ'=>'Τ','ð›¶'=>'Î¥','ð›·'=>'Φ','ð›¸'=>'Χ','ð›¹'=>'Ψ','ð›º'=>'Ω','ð›»'=>'∇','ð›¼'=>'α','ð›½'=>'β','ð›¾'=>'γ','ð›¿'=>'δ','ðœ€'=>'ε','ðœ'=>'ζ','ðœ‚'=>'η','ðœƒ'=>'θ','ðœ„'=>'ι','ðœ…'=>'κ','ðœ†'=>'λ','ðœ‡'=>'μ','ðœˆ'=>'ν','ðœ‰'=>'ξ','ðœŠ'=>'ο','ðœ‹'=>'Ï€','ðœŒ'=>'Ï','ðœ'=>'Ï‚','ðœŽ'=>'σ','ðœ'=>'Ï„','ðœ'=>'Ï…','ðœ‘'=>'φ','ðœ’'=>'χ','ðœ“'=>'ψ','ðœ”'=>'ω','ðœ•'=>'∂','ðœ–'=>'ε','ðœ—'=>'θ','ðœ˜'=>'κ','ðœ™'=>'φ','ðœš'=>'Ï','ðœ›'=>'Ï€','ðœœ'=>'Α','ðœ'=>'Î’','ðœž'=>'Γ','ðœŸ'=>'Δ','ðœ '=>'Ε','ðœ¡'=>'Ζ','ðœ¢'=>'Η','ðœ£'=>'Θ','ðœ¤'=>'Ι','ðœ¥'=>'Κ','ðœ¦'=>'Λ','ðœ§'=>'Μ','ðœ¨'=>'Î','ðœ©'=>'Ξ','ðœª'=>'Ο','ðœ«'=>'Î ','ðœ¬'=>'Ρ','ðœ'=>'Θ','ðœ®'=>'Σ','ðœ¯'=>'Τ','ðœ°'=>'Î¥','ðœ±'=>'Φ','ðœ²'=>'Χ','ðœ³'=>'Ψ','ðœ´'=>'Ω','ðœµ'=>'∇','ðœ¶'=>'α','ðœ·'=>'β','ðœ¸'=>'γ','ðœ¹'=>'δ','ðœº'=>'ε','ðœ»'=>'ζ','ðœ¼'=>'η','ðœ½'=>'θ','ðœ¾'=>'ι','ðœ¿'=>'κ','ð€'=>'λ','ð'=>'μ','ð‚'=>'ν','ðƒ'=>'ξ','ð„'=>'ο','ð…'=>'Ï€','ð†'=>'Ï','ð‡'=>'Ï‚','ðˆ'=>'σ','ð‰'=>'Ï„','ðŠ'=>'Ï…','ð‹'=>'φ','ðŒ'=>'χ','ð'=>'ψ','ðŽ'=>'ω','ð'=>'∂','ð'=>'ε','ð‘'=>'θ','ð’'=>'κ','ð“'=>'φ','ð”'=>'Ï','ð•'=>'Ï€','ð–'=>'Α','ð—'=>'Î’','ð˜'=>'Γ','ð™'=>'Δ','ðš'=>'Ε','ð›'=>'Ζ','ðœ'=>'Η','ð'=>'Θ','ðž'=>'Ι','ðŸ'=>'Κ','ð '=>'Λ','ð¡'=>'Μ','ð¢'=>'Î','ð£'=>'Ξ','ð¤'=>'Ο','ð¥'=>'Î ','ð¦'=>'Ρ','ð§'=>'Θ','ð¨'=>'Σ','ð©'=>'Τ','ðª'=>'Î¥','ð«'=>'Φ','ð¬'=>'Χ','ð'=>'Ψ','ð®'=>'Ω','ð¯'=>'∇','ð°'=>'α','ð±'=>'β','ð²'=>'γ','ð³'=>'δ','ð´'=>'ε','ðµ'=>'ζ','ð¶'=>'η','ð·'=>'θ','ð¸'=>'ι','ð¹'=>'κ','ðº'=>'λ','ð»'=>'μ','ð¼'=>'ν','ð½'=>'ξ','ð¾'=>'ο','ð¿'=>'Ï€','ðž€'=>'Ï','ðž'=>'Ï‚','ðž‚'=>'σ','ðžƒ'=>'Ï„','ðž„'=>'Ï…','ðž…'=>'φ','ðž†'=>'χ','ðž‡'=>'ψ','ðžˆ'=>'ω','ðž‰'=>'∂','ðžŠ'=>'ε','ðž‹'=>'θ','ðžŒ'=>'κ','ðž'=>'φ','ðžŽ'=>'Ï','ðž'=>'Ï€','ðž'=>'Α','ðž‘'=>'Î’','ðž’'=>'Γ','ðž“'=>'Δ','ðž”'=>'Ε','ðž•'=>'Ζ','ðž–'=>'Η','ðž—'=>'Θ','ðž˜'=>'Ι','ðž™'=>'Κ','ðžš'=>'Λ','ðž›'=>'Μ','ðžœ'=>'Î','ðž'=>'Ξ','ðžž'=>'Ο','ðžŸ'=>'Î ','ðž '=>'Ρ','ðž¡'=>'Θ','ðž¢'=>'Σ','ðž£'=>'Τ','ðž¤'=>'Î¥','ðž¥'=>'Φ','ðž¦'=>'Χ','ðž§'=>'Ψ','ðž¨'=>'Ω','ðž©'=>'∇','ðžª'=>'α','ðž«'=>'β','ðž¬'=>'γ','ðž'=>'δ','ðž®'=>'ε','ðž¯'=>'ζ','ðž°'=>'η','ðž±'=>'θ','ðž²'=>'ι','ðž³'=>'κ','ðž´'=>'λ','ðžµ'=>'μ','ðž¶'=>'ν','ðž·'=>'ξ','ðž¸'=>'ο','ðž¹'=>'Ï€','ðžº'=>'Ï','ðž»'=>'Ï‚','ðž¼'=>'σ','ðž½'=>'Ï„','ðž¾'=>'Ï…','ðž¿'=>'φ','ðŸ€'=>'χ','ðŸ'=>'ψ','ðŸ‚'=>'ω','ðŸƒ'=>'∂','ðŸ„'=>'ε','ðŸ…'=>'θ','ðŸ†'=>'κ','ðŸ‡'=>'φ','ðŸˆ'=>'Ï','ðŸ‰'=>'Ï€','ðŸŠ'=>'Ïœ','ðŸ‹'=>'Ï','ðŸŽ'=>'0','ðŸ'=>'1','ðŸ'=>'2','ðŸ‘'=>'3','ðŸ’'=>'4','ðŸ“'=>'5','ðŸ”'=>'6','ðŸ•'=>'7','ðŸ–'=>'8','ðŸ—'=>'9','ðŸ˜'=>'0','ðŸ™'=>'1','ðŸš'=>'2','ðŸ›'=>'3','ðŸœ'=>'4','ðŸ'=>'5','ðŸž'=>'6','ðŸŸ'=>'7','ðŸ '=>'8','ðŸ¡'=>'9','ðŸ¢'=>'0','ðŸ£'=>'1','ðŸ¤'=>'2','ðŸ¥'=>'3','ðŸ¦'=>'4','ðŸ§'=>'5','ðŸ¨'=>'6','ðŸ©'=>'7','ðŸª'=>'8','ðŸ«'=>'9','ðŸ¬'=>'0','ðŸ'=>'1','ðŸ®'=>'2','ðŸ¯'=>'3','ðŸ°'=>'4','ðŸ±'=>'5','ðŸ²'=>'6','ðŸ³'=>'7','ðŸ´'=>'8','ðŸµ'=>'9','ðŸ¶'=>'0','ðŸ·'=>'1','ðŸ¸'=>'2','ðŸ¹'=>'3','ðŸº'=>'4','ðŸ»'=>'5','ðŸ¼'=>'6','ðŸ½'=>'7','ðŸ¾'=>'8','ðŸ¿'=>'9','丽'=>'丽','ð¯ '=>'丸','乁'=>'ä¹','𠄢'=>'ð „¢','你'=>'ä½ ','侮'=>'ä¾®','侻'=>'ä¾»','倂'=>'倂','偺'=>'åº','備'=>'å‚™','僧'=>'僧','像'=>'åƒ','㒞'=>'ã’ž','ð¯ '=>'𠘺','免'=>'å…','ð¯ '=>'å…”','ð¯ '=>'å…¤','具'=>'å…·','𠔜'=>'𠔜','㒹'=>'ã’¹','內'=>'å…§','再'=>'å†','𠕋'=>'ð •‹','冗'=>'冗','冤'=>'冤','仌'=>'仌','冬'=>'冬','况'=>'况','𩇟'=>'𩇟','ð¯ '=>'凵','刃'=>'刃','㓟'=>'㓟','ð¯ '=>'刻','剆'=>'剆','割'=>'割','剷'=>'剷','㔕'=>'㔕','勇'=>'勇','勉'=>'勉','勤'=>'勤','勺'=>'勺','包'=>'包','匆'=>'匆','北'=>'北','卉'=>'å‰','ð¯ '=>'å‘','博'=>'åš','即'=>'å³','卽'=>'å½','卿'=>'å¿','卿'=>'å¿','卿'=>'å¿','𠨬'=>'𠨬','灰'=>'ç°','及'=>'åŠ','叟'=>'åŸ','𠭣'=>'ð £','叫'=>'å«','叱'=>'å±','吆'=>'å†','咞'=>'å’ž','吸'=>'å¸','呈'=>'呈','周'=>'周','咢'=>'å’¢','ð¯¡'=>'å“¶','唐'=>'å”','啓'=>'å•“','啣'=>'å•£','善'=>'å–„','善'=>'å–„','喙'=>'å–™','喫'=>'å–«','喳'=>'å–³','嗂'=>'å—‚','圖'=>'圖','嘆'=>'嘆','ð¯¡'=>'圗','噑'=>'噑','ð¯¡'=>'å™´','ð¯¡'=>'切','壮'=>'壮','城'=>'城','埴'=>'埴','堍'=>'å ','型'=>'åž‹','堲'=>'å ²','報'=>'å ±','墬'=>'墬','𡓤'=>'𡓤','売'=>'売','壷'=>'壷','夆'=>'夆','ð¯¡'=>'多','夢'=>'夢','奢'=>'奢','𡚨'=>'𡚨','𡛪'=>'𡛪','姬'=>'姬','娛'=>'娛','娧'=>'娧','姘'=>'姘','婦'=>'婦','㛮'=>'ã›®','㛼'=>'㛼','嬈'=>'嬈','嬾'=>'嬾','嬾'=>'嬾','𡧈'=>'𡧈','ð¯¡'=>'寃','寘'=>'寘','寧'=>'寧','寳'=>'寳','𡬘'=>'𡬘','寿'=>'寿','将'=>'å°†','当'=>'当','尢'=>'å°¢','㞁'=>'ãž','屠'=>'å± ','屮'=>'å±®','峀'=>'å³€','岍'=>'å²','𡷤'=>'ð¡·¤','嵃'=>'嵃','𡷦'=>'ð¡·¦','嵮'=>'åµ®','嵫'=>'嵫','嵼'=>'åµ¼','ð¯¢'=>'å·¡','巢'=>'å·¢','㠯'=>'ã ¯','巽'=>'å·½','帨'=>'帨','帽'=>'帽','幩'=>'幩','㡢'=>'ã¡¢','𢆃'=>'𢆃','㡼'=>'㡼','庰'=>'庰','庳'=>'庳','ð¯¢'=>'庶','廊'=>'廊','ð¯¢'=>'𪎒','ð¯¢'=>'廾','𢌱'=>'𢌱','𢌱'=>'𢌱','舁'=>'èˆ','弢'=>'å¼¢','弢'=>'å¼¢','㣇'=>'㣇','𣊸'=>'𣊸','𦇚'=>'𦇚','形'=>'å½¢','彫'=>'彫','㣣'=>'㣣','徚'=>'徚','ð¯¢'=>'å¿','志'=>'å¿—','忹'=>'忹','悁'=>'æ‚','㤺'=>'㤺','㤜'=>'㤜','悔'=>'æ‚”','𢛔'=>'𢛔','惇'=>'惇','慈'=>'æ…ˆ','慌'=>'æ…Œ','慎'=>'æ…Ž','慌'=>'æ…Œ','慺'=>'æ…º','憎'=>'憎','憲'=>'憲','ð¯¢'=>'憤','憯'=>'憯','懞'=>'懞','懲'=>'懲','懶'=>'懶','成'=>'æˆ','戛'=>'戛','扝'=>'æ‰','抱'=>'抱','拔'=>'æ‹”','捐'=>'æ','𢬌'=>'𢬌','挽'=>'挽','拼'=>'拼','捨'=>'æ¨','掃'=>'掃','揤'=>'æ¤','𢯱'=>'𢯱','搢'=>'æ¢','揅'=>'æ…','ð¯£'=>'掩','㨮'=>'㨮','摩'=>'æ‘©','摾'=>'摾','撝'=>'æ’','摷'=>'æ‘·','㩬'=>'㩬','敏'=>'æ•','敬'=>'敬','𣀊'=>'𣀊','旣'=>'æ—£','書'=>'書','ð¯£'=>'晉','㬙'=>'㬙','ð¯£'=>'æš‘','ð¯£'=>'㬈','㫤'=>'㫤','冒'=>'冒','冕'=>'冕','最'=>'最','暜'=>'æšœ','肭'=>'è‚','䏙'=>'ä™','朗'=>'朗','望'=>'望','朡'=>'朡','杞'=>'æž','杓'=>'æ“','ð¯£'=>'ð£ƒ','㭉'=>'ã‰','柺'=>'柺','枅'=>'æž…','桒'=>'æ¡’','梅'=>'梅','𣑭'=>'ð£‘','梎'=>'梎','栟'=>'æ Ÿ','椔'=>'椔','㮝'=>'ã®','楂'=>'楂','榣'=>'榣','槪'=>'槪','檨'=>'檨','𣚣'=>'𣚣','ð¯£'=>'æ«›','㰘'=>'ã°˜','次'=>'次','𣢧'=>'𣢧','歔'=>'æ”','㱎'=>'㱎','歲'=>'æ²','殟'=>'殟','殺'=>'殺','殻'=>'æ®»','𣪍'=>'ð£ª','𡴋'=>'ð¡´‹','𣫺'=>'𣫺','汎'=>'汎','𣲼'=>'𣲼','沿'=>'沿','泍'=>'æ³','汧'=>'æ±§','洖'=>'æ´–','派'=>'æ´¾','ð¯¤'=>'æµ·','流'=>'æµ','浩'=>'浩','浸'=>'浸','涅'=>'æ¶…','𣴞'=>'𣴞','洴'=>'æ´´','港'=>'港','湮'=>'æ¹®','㴳'=>'ã´³','滋'=>'滋','滇'=>'滇','ð¯¤'=>'𣻑','淹'=>'æ·¹','ð¯¤'=>'æ½®','ð¯¤'=>'𣽞','𣾎'=>'𣾎','濆'=>'濆','瀹'=>'瀹','瀞'=>'瀞','瀛'=>'瀛','㶖'=>'ã¶–','灊'=>'çŠ','災'=>'ç½','灷'=>'ç·','炭'=>'ç‚','𠔥'=>'𠔥','煅'=>'ç……','ð¯¤'=>'𤉣','熜'=>'熜','𤎫'=>'𤎫','爨'=>'爨','爵'=>'爵','牐'=>'ç‰','𤘈'=>'𤘈','犀'=>'犀','犕'=>'犕','𤜵'=>'𤜵','𤠔'=>'𤠔','獺'=>'çº','王'=>'王','㺬'=>'㺬','玥'=>'玥','㺸'=>'㺸','ð¯¤'=>'㺸','瑇'=>'瑇','瑜'=>'瑜','瑱'=>'瑱','璅'=>'ç’…','瓊'=>'瓊','㼛'=>'ã¼›','甤'=>'甤','𤰶'=>'𤰶','甾'=>'甾','𤲒'=>'𤲒','異'=>'ç•°','𢆟'=>'𢆟','瘐'=>'ç˜','𤾡'=>'𤾡','𤾸'=>'𤾸','𥁄'=>'ð¥„','㿼'=>'㿼','䀈'=>'䀈','直'=>'ç›´','ð¯¥'=>'𥃳','𥃲'=>'𥃲','𥄙'=>'𥄙','𥄳'=>'𥄳','眞'=>'眞','真'=>'真','真'=>'真','睊'=>'çŠ','䀹'=>'䀹','瞋'=>'çž‹','䁆'=>'ä†','䂖'=>'ä‚–','ð¯¥'=>'ð¥','硎'=>'硎','ð¯¥'=>'碌','ð¯¥'=>'磌','䃣'=>'䃣','𥘦'=>'𥘦','祖'=>'祖','𥚚'=>'𥚚','𥛅'=>'𥛅','福'=>'ç¦','秫'=>'ç§«','䄯'=>'䄯','穀'=>'ç©€','穊'=>'穊','穏'=>'ç©','𥥼'=>'𥥼','ð¯¥'=>'𥪧','𥪧'=>'𥪧','竮'=>'ç«®','䈂'=>'䈂','𥮫'=>'𥮫','篆'=>'篆','築'=>'築','䈧'=>'䈧','𥲀'=>'𥲀','糒'=>'ç³’','䊠'=>'äŠ ','糨'=>'糨','糣'=>'ç³£','紀'=>'ç´€','𥾆'=>'𥾆','絣'=>'çµ£','ð¯¥'=>'äŒ','緇'=>'ç·‡','縂'=>'縂','繅'=>'ç¹…','䌴'=>'䌴','𦈨'=>'𦈨','𦉇'=>'𦉇','䍙'=>'ä™','𦋙'=>'𦋙','罺'=>'罺','𦌾'=>'𦌾','羕'=>'羕','翺'=>'翺','者'=>'者','𦓚'=>'𦓚','𦔣'=>'𦔣','聠'=>'è ','𦖨'=>'𦖨','聰'=>'è°','𣍟'=>'ð£Ÿ','ð¯¦'=>'ä•','育'=>'育','脃'=>'脃','䐋'=>'ä‹','脾'=>'脾','媵'=>'媵','𦞧'=>'𦞧','𦞵'=>'𦞵','𣎓'=>'𣎓','𣎜'=>'𣎜','舁'=>'èˆ','舄'=>'舄','ð¯¦'=>'辞','䑫'=>'ä‘«','ð¯¦'=>'芑','ð¯¦'=>'芋','芝'=>'èŠ','劳'=>'劳','花'=>'花','芳'=>'芳','芽'=>'芽','苦'=>'苦','𦬼'=>'𦬼','若'=>'è‹¥','茝'=>'èŒ','荣'=>'è£','莭'=>'èŽ','茣'=>'茣','ð¯¦'=>'莽','菧'=>'è§','著'=>'è‘—','荓'=>'è“','菊'=>'èŠ','菌'=>'èŒ','菜'=>'èœ','𦰶'=>'𦰶','𦵫'=>'𦵫','𦳕'=>'𦳕','䔫'=>'䔫','蓱'=>'蓱','蓳'=>'蓳','蔖'=>'è”–','𧏊'=>'ð§Š','蕤'=>'蕤','ð¯¦'=>'𦼬','䕝'=>'ä•','䕡'=>'ä•¡','𦾱'=>'𦾱','𧃒'=>'𧃒','䕫'=>'ä•«','虐'=>'è™','虜'=>'虜','虧'=>'è™§','虩'=>'虩','蚩'=>'èš©','蚈'=>'蚈','蜎'=>'蜎','蛢'=>'蛢','蝹'=>'è¹','蜨'=>'蜨','蝫'=>'è«','螆'=>'螆','䗗'=>'ä——','蟡'=>'蟡','ð¯§'=>'è ','䗹'=>'ä—¹','衠'=>'è¡ ','衣'=>'è¡£','𧙧'=>'ð§™§','裗'=>'裗','裞'=>'裞','䘵'=>'䘵','裺'=>'裺','㒻'=>'ã’»','𧢮'=>'ð§¢®','𧥦'=>'𧥦','ð¯§'=>'äš¾','䛇'=>'䛇','ð¯§'=>'èª ','ð¯§'=>'è«','變'=>'變','豕'=>'豕','𧲨'=>'𧲨','貫'=>'貫','賁'=>'è³','贛'=>'è´›','起'=>'èµ·','𧼯'=>'𧼯','𠠄'=>'ð „','跋'=>'è·‹','趼'=>'è¶¼','跰'=>'è·°','ð¯§'=>'𠣞','軔'=>'è»”','輸'=>'輸','𨗒'=>'𨗒','𨗭'=>'ð¨—','邔'=>'é‚”','郱'=>'郱','鄑'=>'é„‘','𨜮'=>'𨜮','鄛'=>'é„›','鈸'=>'鈸','鋗'=>'é‹—','鋘'=>'鋘','鉼'=>'鉼','鏹'=>'é¹','鐕'=>'é•','ð¯§'=>'𨯺','開'=>'é–‹','䦕'=>'䦕','閷'=>'é–·','𨵷'=>'𨵷','䧦'=>'䧦','雃'=>'雃','嶲'=>'å¶²','霣'=>'霣','𩅅'=>'ð©……','𩈚'=>'𩈚','䩮'=>'ä©®','䩶'=>'ä©¶','韠'=>'éŸ ','𩐊'=>'ð©Š','䪲'=>'䪲','𩒖'=>'ð©’–','頋'=>'é ‹','頋'=>'é ‹','頩'=>'é ©','ð¯¨'=>'ð©–¶','飢'=>'飢','䬳'=>'䬳','餩'=>'餩','馧'=>'馧','駂'=>'é§‚','駾'=>'é§¾','䯎'=>'䯎','𩬰'=>'𩬰','鬒'=>'鬒','鱀'=>'é±€','鳽'=>'é³½','ð¯¨'=>'䳎','䳭'=>'ä³','ð¯¨'=>'éµ§','ð¯¨'=>'𪃎','䳸'=>'䳸','𪄅'=>'𪄅','𪈎'=>'𪈎','𪊑'=>'𪊑','麻'=>'麻','䵖'=>'äµ–','黹'=>'黹','黾'=>'黾','鼅'=>'é¼…','鼏'=>'é¼','鼖'=>'é¼–','鼻'=>'é¼»','ð¯¨'=>'𪘀');
\ No newline at end of file diff --git a/phpBB/includes/utf/data/utf_nfc_qc.php b/phpBB/includes/utf/data/utf_nfc_qc.php deleted file mode 100644 index 03031f8b6d..0000000000 --- a/phpBB/includes/utf/data/utf_nfc_qc.php +++ /dev/null @@ -1,2 +0,0 @@ -<?php -$GLOBALS['utf_nfc_qc']=array('Í€'=>1,'Í'=>1,'̓'=>1,'Í„'=>1,'Í´'=>1,';'=>1,'·'=>1,'क़'=>1,'ख़'=>1,'ग़'=>1,'ज़'=>1,'ड़'=>1,'à¥'=>1,'फ़'=>1,'य़'=>1,'à§œ'=>1,'à§'=>1,'à§Ÿ'=>1,'ਲ਼'=>1,'ਸ਼'=>1,'à©™'=>1,'ਗ਼'=>1,'à©›'=>1,'ਫ਼'=>1,'àœ'=>1,'à'=>1,'གྷ'=>1,'à½'=>1,'དྷ'=>1,'བྷ'=>1,'ཛྷ'=>1,'ཀྵ'=>1,'ཱི'=>1,'ཱུ'=>1,'ྲྀ'=>1,'ླྀ'=>1,'à¾'=>1,'ྒྷ'=>1,'à¾'=>1,'ྡྷ'=>1,'ྦྷ'=>1,'ྫྷ'=>1,'ྐྵ'=>1,'á½±'=>1,'á½³'=>1,'á½µ'=>1,'á½·'=>1,'á½¹'=>1,'á½»'=>1,'á½½'=>1,'á¾»'=>1,'á¾¾'=>1,'Έ'=>1,'á¿‹'=>1,'á¿“'=>1,'á¿›'=>1,'á¿£'=>1,'á¿«'=>1,'á¿®'=>1,'`'=>1,'Ό'=>1,'á¿»'=>1,'´'=>1,' '=>1,'â€'=>1,'Ω'=>1,'K'=>1,'â„«'=>1,'〈'=>1,'〉'=>1,'⫝̸'=>1,'豈'=>1,'ï¤'=>1,'車'=>1,'賈'=>1,'滑'=>1,'串'=>1,'句'=>1,'龜'=>1,'龜'=>1,'契'=>1,'金'=>1,'喇'=>1,'奈'=>1,'ï¤'=>1,'癩'=>1,'ï¤'=>1,'ï¤'=>1,'螺'=>1,'裸'=>1,'邏'=>1,'樂'=>1,'洛'=>1,'烙'=>1,'珞'=>1,'落'=>1,'酪'=>1,'駱'=>1,'亂'=>1,'卵'=>1,'ï¤'=>1,'爛'=>1,'蘭'=>1,'ï¤ '=>1,'嵐'=>1,'濫'=>1,'藍'=>1,'襤'=>1,'拉'=>1,'臘'=>1,'蠟'=>1,'廊'=>1,'朗'=>1,'浪'=>1,'狼'=>1,'郎'=>1,'ï¤'=>1,'冷'=>1,'勞'=>1,'擄'=>1,'櫓'=>1,'爐'=>1,'盧'=>1,'老'=>1,'蘆'=>1,'虜'=>1,'路'=>1,'露'=>1,'魯'=>1,'鷺'=>1,'碌'=>1,'祿'=>1,'綠'=>1,'菉'=>1,'錄'=>1,'鹿'=>1,'ï¥'=>1,'壟'=>1,'弄'=>1,'籠'=>1,'聾'=>1,'牢'=>1,'磊'=>1,'賂'=>1,'雷'=>1,'壘'=>1,'屢'=>1,'樓'=>1,'ï¥'=>1,'漏'=>1,'ï¥'=>1,'ï¥'=>1,'陋'=>1,'勒'=>1,'肋'=>1,'凜'=>1,'凌'=>1,'稜'=>1,'綾'=>1,'菱'=>1,'陵'=>1,'讀'=>1,'拏'=>1,'樂'=>1,'ï¥'=>1,'丹'=>1,'寧'=>1,'ï¥ '=>1,'率'=>1,'異'=>1,'北'=>1,'磻'=>1,'便'=>1,'復'=>1,'不'=>1,'泌'=>1,'數'=>1,'索'=>1,'參'=>1,'塞'=>1,'ï¥'=>1,'葉'=>1,'說'=>1,'殺'=>1,'辰'=>1,'沈'=>1,'拾'=>1,'若'=>1,'掠'=>1,'略'=>1,'亮'=>1,'兩'=>1,'凉'=>1,'梁'=>1,'糧'=>1,'良'=>1,'諒'=>1,'量'=>1,'勵'=>1,'呂'=>1,'ï¦'=>1,'廬'=>1,'旅'=>1,'濾'=>1,'礪'=>1,'閭'=>1,'驪'=>1,'麗'=>1,'黎'=>1,'力'=>1,'曆'=>1,'歷'=>1,'ï¦'=>1,'年'=>1,'ï¦'=>1,'ï¦'=>1,'撚'=>1,'漣'=>1,'煉'=>1,'璉'=>1,'秊'=>1,'練'=>1,'聯'=>1,'輦'=>1,'蓮'=>1,'連'=>1,'鍊'=>1,'列'=>1,'ï¦'=>1,'咽'=>1,'烈'=>1,'ï¦ '=>1,'說'=>1,'廉'=>1,'念'=>1,'捻'=>1,'殮'=>1,'簾'=>1,'獵'=>1,'令'=>1,'囹'=>1,'寧'=>1,'嶺'=>1,'怜'=>1,'ï¦'=>1,'瑩'=>1,'羚'=>1,'聆'=>1,'鈴'=>1,'零'=>1,'靈'=>1,'領'=>1,'例'=>1,'禮'=>1,'醴'=>1,'隸'=>1,'惡'=>1,'了'=>1,'僚'=>1,'寮'=>1,'尿'=>1,'料'=>1,'樂'=>1,'ï§€'=>1,'ï§'=>1,'ï§‚'=>1,'遼'=>1,'ï§„'=>1,'ï§…'=>1,'阮'=>1,'劉'=>1,'杻'=>1,'柳'=>1,'ï§Š'=>1,'ï§‹'=>1,'ï§Œ'=>1,'ï§'=>1,'ï§Ž'=>1,'ï§'=>1,'ï§'=>1,'ï§‘'=>1,'ï§’'=>1,'ï§“'=>1,'ï§”'=>1,'ï§•'=>1,'ï§–'=>1,'ï§—'=>1,'律'=>1,'ï§™'=>1,'ï§š'=>1,'ï§›'=>1,'ï§œ'=>1,'ï§'=>1,'ï§ž'=>1,'ï§Ÿ'=>1,'ï§ '=>1,'ï§¡'=>1,'ï§¢'=>1,'ï§£'=>1,'理'=>1,'ï§¥'=>1,'罹'=>1,'ï§§'=>1,'裡'=>1,'ï§©'=>1,'離'=>1,'ï§«'=>1,'溺'=>1,'ï§'=>1,'ï§®'=>1,'璘'=>1,'ï§°'=>1,'ï§±'=>1,'ï§²'=>1,'ï§³'=>1,'ï§´'=>1,'ï§µ'=>1,'ï§¶'=>1,'ï§·'=>1,'笠'=>1,'ï§¹'=>1,'狀'=>1,'ï§»'=>1,'ï§¼'=>1,'ï§½'=>1,'ï§¾'=>1,'ï§¿'=>1,'切'=>1,'ï¨'=>1,'拓'=>1,'糖'=>1,'宅'=>1,'洞'=>1,'暴'=>1,'輻'=>1,'行'=>1,'降'=>1,'見'=>1,'廓'=>1,'兀'=>1,'ï¨'=>1,'ï¨'=>1,'晴'=>1,'凞'=>1,'猪'=>1,'益'=>1,'礼'=>1,'神'=>1,'祥'=>1,'福'=>1,'靖'=>1,'ï¨'=>1,'羽'=>1,'ï¨ '=>1,'諸'=>1,'逸'=>1,'都'=>1,'飯'=>1,'飼'=>1,'館'=>1,'ï¨'=>1,'侮'=>1,'僧'=>1,'免'=>1,'勉'=>1,'勤'=>1,'卑'=>1,'喝'=>1,'嘆'=>1,'器'=>1,'塀'=>1,'墨'=>1,'層'=>1,'屮'=>1,'悔'=>1,'慨'=>1,'憎'=>1,'ï©€'=>1,'ï©'=>1,'ï©‚'=>1,'暑'=>1,'ï©„'=>1,'ï©…'=>1,'渚'=>1,'漢'=>1,'煮'=>1,'爫'=>1,'琢'=>1,'ï©‹'=>1,'社'=>1,'ï©'=>1,'祈'=>1,'ï©'=>1,'ï©'=>1,'ï©‘'=>1,'ï©’'=>1,'ï©“'=>1,'ï©”'=>1,'ï©•'=>1,'ï©–'=>1,'ï©—'=>1,'縉'=>1,'ï©™'=>1,'署'=>1,'ï©›'=>1,'臭'=>1,'ï©'=>1,'艹'=>1,'著'=>1,'ï© '=>1,'ï©¡'=>1,'ï©¢'=>1,'ï©£'=>1,'賓'=>1,'ï©¥'=>1,'辶'=>1,'ï©§'=>1,'難'=>1,'ï©©'=>1,'頻'=>1,'ï©°'=>1,'况'=>1,'全'=>1,'侀'=>1,'ï©´'=>1,'冀'=>1,'ï©¶'=>1,'ï©·'=>1,'喝'=>1,'啕'=>1,'喙'=>1,'ï©»'=>1,'塚'=>1,'墳'=>1,'奄'=>1,'ï©¿'=>1,'婢'=>1,'ïª'=>1,'廒'=>1,'廙'=>1,'彩'=>1,'徭'=>1,'惘'=>1,'慎'=>1,'愈'=>1,'憎'=>1,'慠'=>1,'懲'=>1,'戴'=>1,'ïª'=>1,'搜'=>1,'ïª'=>1,'ïª'=>1,'晴'=>1,'朗'=>1,'望'=>1,'杖'=>1,'歹'=>1,'殺'=>1,'流'=>1,'滛'=>1,'滋'=>1,'漢'=>1,'瀞'=>1,'煮'=>1,'ïª'=>1,'爵'=>1,'犯'=>1,'ïª '=>1,'瑱'=>1,'甆'=>1,'画'=>1,'瘝'=>1,'瘟'=>1,'益'=>1,'盛'=>1,'直'=>1,'睊'=>1,'着'=>1,'磌'=>1,'窱'=>1,'ïª'=>1,'类'=>1,'絛'=>1,'練'=>1,'缾'=>1,'者'=>1,'荒'=>1,'華'=>1,'蝹'=>1,'襁'=>1,'覆'=>1,'視'=>1,'調'=>1,'諸'=>1,'請'=>1,'謁'=>1,'諾'=>1,'諭'=>1,'謹'=>1,'ï«€'=>1,'ï«'=>1,'ï«‚'=>1,'遲'=>1,'ï«„'=>1,'ï«…'=>1,'陼'=>1,'難'=>1,'靖'=>1,'韛'=>1,'響'=>1,'ï«‹'=>1,'頻'=>1,'ï«'=>1,'龜'=>1,'ï«'=>1,'ï«'=>1,'ï«‘'=>1,'ï«’'=>1,'ï«“'=>1,'ï«”'=>1,'ï«•'=>1,'ï«–'=>1,'ï«—'=>1,'齃'=>1,'ï«™'=>1,'ï¬'=>1,'ײַ'=>1,'שׁ'=>1,'שׂ'=>1,'שּׁ'=>1,'ï¬'=>1,'אַ'=>1,'אָ'=>1,'אּ'=>1,'בּ'=>1,'גּ'=>1,'דּ'=>1,'הּ'=>1,'וּ'=>1,'זּ'=>1,'טּ'=>1,'יּ'=>1,'ךּ'=>1,'כּ'=>1,'לּ'=>1,'מּ'=>1,'ï€'=>1,'ï'=>1,'ïƒ'=>1,'ï„'=>1,'ï†'=>1,'ï‡'=>1,'ïˆ'=>1,'ï‰'=>1,'ïŠ'=>1,'ï‹'=>1,'ïŒ'=>1,'ï'=>1,'ïŽ'=>1,'ð…ž'=>1,'ð…Ÿ'=>1,'ð… '=>1,'ð…¡'=>1,'ð…¢'=>1,'ð…£'=>1,'ð…¤'=>1,'ð†»'=>1,'ð†¼'=>1,'ð†½'=>1,'ð†¾'=>1,'ð†¿'=>1,'ð‡€'=>1,'丽'=>1,'ð¯ '=>1,'乁'=>1,'𠄢'=>1,'你'=>1,'侮'=>1,'侻'=>1,'倂'=>1,'偺'=>1,'備'=>1,'僧'=>1,'像'=>1,'㒞'=>1,'ð¯ '=>1,'免'=>1,'ð¯ '=>1,'ð¯ '=>1,'具'=>1,'𠔜'=>1,'㒹'=>1,'內'=>1,'再'=>1,'𠕋'=>1,'冗'=>1,'冤'=>1,'仌'=>1,'冬'=>1,'况'=>1,'𩇟'=>1,'ð¯ '=>1,'刃'=>1,'㓟'=>1,'ð¯ '=>1,'剆'=>1,'割'=>1,'剷'=>1,'㔕'=>1,'勇'=>1,'勉'=>1,'勤'=>1,'勺'=>1,'包'=>1,'匆'=>1,'北'=>1,'卉'=>1,'ð¯ '=>1,'博'=>1,'即'=>1,'卽'=>1,'卿'=>1,'卿'=>1,'卿'=>1,'𠨬'=>1,'灰'=>1,'及'=>1,'叟'=>1,'𠭣'=>1,'叫'=>1,'叱'=>1,'吆'=>1,'咞'=>1,'吸'=>1,'呈'=>1,'周'=>1,'咢'=>1,'ð¯¡'=>1,'唐'=>1,'啓'=>1,'啣'=>1,'善'=>1,'善'=>1,'喙'=>1,'喫'=>1,'喳'=>1,'嗂'=>1,'圖'=>1,'嘆'=>1,'ð¯¡'=>1,'噑'=>1,'ð¯¡'=>1,'ð¯¡'=>1,'壮'=>1,'城'=>1,'埴'=>1,'堍'=>1,'型'=>1,'堲'=>1,'報'=>1,'墬'=>1,'𡓤'=>1,'売'=>1,'壷'=>1,'夆'=>1,'ð¯¡'=>1,'夢'=>1,'奢'=>1,'𡚨'=>1,'𡛪'=>1,'姬'=>1,'娛'=>1,'娧'=>1,'姘'=>1,'婦'=>1,'㛮'=>1,'㛼'=>1,'嬈'=>1,'嬾'=>1,'嬾'=>1,'𡧈'=>1,'ð¯¡'=>1,'寘'=>1,'寧'=>1,'寳'=>1,'𡬘'=>1,'寿'=>1,'将'=>1,'当'=>1,'尢'=>1,'㞁'=>1,'屠'=>1,'屮'=>1,'峀'=>1,'岍'=>1,'𡷤'=>1,'嵃'=>1,'𡷦'=>1,'嵮'=>1,'嵫'=>1,'嵼'=>1,'ð¯¢'=>1,'巢'=>1,'㠯'=>1,'巽'=>1,'帨'=>1,'帽'=>1,'幩'=>1,'㡢'=>1,'𢆃'=>1,'㡼'=>1,'庰'=>1,'庳'=>1,'ð¯¢'=>1,'廊'=>1,'ð¯¢'=>1,'ð¯¢'=>1,'𢌱'=>1,'𢌱'=>1,'舁'=>1,'弢'=>1,'弢'=>1,'㣇'=>1,'𣊸'=>1,'𦇚'=>1,'形'=>1,'彫'=>1,'㣣'=>1,'徚'=>1,'ð¯¢'=>1,'志'=>1,'忹'=>1,'悁'=>1,'㤺'=>1,'㤜'=>1,'悔'=>1,'𢛔'=>1,'惇'=>1,'慈'=>1,'慌'=>1,'慎'=>1,'慌'=>1,'慺'=>1,'憎'=>1,'憲'=>1,'ð¯¢'=>1,'憯'=>1,'懞'=>1,'懲'=>1,'懶'=>1,'成'=>1,'戛'=>1,'扝'=>1,'抱'=>1,'拔'=>1,'捐'=>1,'𢬌'=>1,'挽'=>1,'拼'=>1,'捨'=>1,'掃'=>1,'揤'=>1,'𢯱'=>1,'搢'=>1,'揅'=>1,'ð¯£'=>1,'㨮'=>1,'摩'=>1,'摾'=>1,'撝'=>1,'摷'=>1,'㩬'=>1,'敏'=>1,'敬'=>1,'𣀊'=>1,'旣'=>1,'書'=>1,'ð¯£'=>1,'㬙'=>1,'ð¯£'=>1,'ð¯£'=>1,'㫤'=>1,'冒'=>1,'冕'=>1,'最'=>1,'暜'=>1,'肭'=>1,'䏙'=>1,'朗'=>1,'望'=>1,'朡'=>1,'杞'=>1,'杓'=>1,'ð¯£'=>1,'㭉'=>1,'柺'=>1,'枅'=>1,'桒'=>1,'梅'=>1,'𣑭'=>1,'梎'=>1,'栟'=>1,'椔'=>1,'㮝'=>1,'楂'=>1,'榣'=>1,'槪'=>1,'檨'=>1,'𣚣'=>1,'ð¯£'=>1,'㰘'=>1,'次'=>1,'𣢧'=>1,'歔'=>1,'㱎'=>1,'歲'=>1,'殟'=>1,'殺'=>1,'殻'=>1,'𣪍'=>1,'𡴋'=>1,'𣫺'=>1,'汎'=>1,'𣲼'=>1,'沿'=>1,'泍'=>1,'汧'=>1,'洖'=>1,'派'=>1,'ð¯¤'=>1,'流'=>1,'浩'=>1,'浸'=>1,'涅'=>1,'𣴞'=>1,'洴'=>1,'港'=>1,'湮'=>1,'㴳'=>1,'滋'=>1,'滇'=>1,'ð¯¤'=>1,'淹'=>1,'ð¯¤'=>1,'ð¯¤'=>1,'𣾎'=>1,'濆'=>1,'瀹'=>1,'瀞'=>1,'瀛'=>1,'㶖'=>1,'灊'=>1,'災'=>1,'灷'=>1,'炭'=>1,'𠔥'=>1,'煅'=>1,'ð¯¤'=>1,'熜'=>1,'𤎫'=>1,'爨'=>1,'爵'=>1,'牐'=>1,'𤘈'=>1,'犀'=>1,'犕'=>1,'𤜵'=>1,'𤠔'=>1,'獺'=>1,'王'=>1,'㺬'=>1,'玥'=>1,'㺸'=>1,'ð¯¤'=>1,'瑇'=>1,'瑜'=>1,'瑱'=>1,'璅'=>1,'瓊'=>1,'㼛'=>1,'甤'=>1,'𤰶'=>1,'甾'=>1,'𤲒'=>1,'異'=>1,'𢆟'=>1,'瘐'=>1,'𤾡'=>1,'𤾸'=>1,'𥁄'=>1,'㿼'=>1,'䀈'=>1,'直'=>1,'ð¯¥'=>1,'𥃲'=>1,'𥄙'=>1,'𥄳'=>1,'眞'=>1,'真'=>1,'真'=>1,'睊'=>1,'䀹'=>1,'瞋'=>1,'䁆'=>1,'䂖'=>1,'ð¯¥'=>1,'硎'=>1,'ð¯¥'=>1,'ð¯¥'=>1,'䃣'=>1,'𥘦'=>1,'祖'=>1,'𥚚'=>1,'𥛅'=>1,'福'=>1,'秫'=>1,'䄯'=>1,'穀'=>1,'穊'=>1,'穏'=>1,'𥥼'=>1,'ð¯¥'=>1,'𥪧'=>1,'竮'=>1,'䈂'=>1,'𥮫'=>1,'篆'=>1,'築'=>1,'䈧'=>1,'𥲀'=>1,'糒'=>1,'䊠'=>1,'糨'=>1,'糣'=>1,'紀'=>1,'𥾆'=>1,'絣'=>1,'ð¯¥'=>1,'緇'=>1,'縂'=>1,'繅'=>1,'䌴'=>1,'𦈨'=>1,'𦉇'=>1,'䍙'=>1,'𦋙'=>1,'罺'=>1,'𦌾'=>1,'羕'=>1,'翺'=>1,'者'=>1,'𦓚'=>1,'𦔣'=>1,'聠'=>1,'𦖨'=>1,'聰'=>1,'𣍟'=>1,'ð¯¦'=>1,'育'=>1,'脃'=>1,'䐋'=>1,'脾'=>1,'媵'=>1,'𦞧'=>1,'𦞵'=>1,'𣎓'=>1,'𣎜'=>1,'舁'=>1,'舄'=>1,'ð¯¦'=>1,'䑫'=>1,'ð¯¦'=>1,'ð¯¦'=>1,'芝'=>1,'劳'=>1,'花'=>1,'芳'=>1,'芽'=>1,'苦'=>1,'𦬼'=>1,'若'=>1,'茝'=>1,'荣'=>1,'莭'=>1,'茣'=>1,'ð¯¦'=>1,'菧'=>1,'著'=>1,'荓'=>1,'菊'=>1,'菌'=>1,'菜'=>1,'𦰶'=>1,'𦵫'=>1,'𦳕'=>1,'䔫'=>1,'蓱'=>1,'蓳'=>1,'蔖'=>1,'𧏊'=>1,'蕤'=>1,'ð¯¦'=>1,'䕝'=>1,'䕡'=>1,'𦾱'=>1,'𧃒'=>1,'䕫'=>1,'虐'=>1,'虜'=>1,'虧'=>1,'虩'=>1,'蚩'=>1,'蚈'=>1,'蜎'=>1,'蛢'=>1,'蝹'=>1,'蜨'=>1,'蝫'=>1,'螆'=>1,'䗗'=>1,'蟡'=>1,'ð¯§'=>1,'䗹'=>1,'衠'=>1,'衣'=>1,'𧙧'=>1,'裗'=>1,'裞'=>1,'䘵'=>1,'裺'=>1,'㒻'=>1,'𧢮'=>1,'𧥦'=>1,'ð¯§'=>1,'䛇'=>1,'ð¯§'=>1,'ð¯§'=>1,'變'=>1,'豕'=>1,'𧲨'=>1,'貫'=>1,'賁'=>1,'贛'=>1,'起'=>1,'𧼯'=>1,'𠠄'=>1,'跋'=>1,'趼'=>1,'跰'=>1,'ð¯§'=>1,'軔'=>1,'輸'=>1,'𨗒'=>1,'𨗭'=>1,'邔'=>1,'郱'=>1,'鄑'=>1,'𨜮'=>1,'鄛'=>1,'鈸'=>1,'鋗'=>1,'鋘'=>1,'鉼'=>1,'鏹'=>1,'鐕'=>1,'ð¯§'=>1,'開'=>1,'䦕'=>1,'閷'=>1,'𨵷'=>1,'䧦'=>1,'雃'=>1,'嶲'=>1,'霣'=>1,'𩅅'=>1,'𩈚'=>1,'䩮'=>1,'䩶'=>1,'韠'=>1,'𩐊'=>1,'䪲'=>1,'𩒖'=>1,'頋'=>1,'頋'=>1,'頩'=>1,'ð¯¨'=>1,'飢'=>1,'䬳'=>1,'餩'=>1,'馧'=>1,'駂'=>1,'駾'=>1,'䯎'=>1,'𩬰'=>1,'鬒'=>1,'鱀'=>1,'鳽'=>1,'ð¯¨'=>1,'䳭'=>1,'ð¯¨'=>1,'ð¯¨'=>1,'䳸'=>1,'𪄅'=>1,'𪈎'=>1,'𪊑'=>1,'麻'=>1,'䵖'=>1,'黹'=>1,'黾'=>1,'鼅'=>1,'鼏'=>1,'鼖'=>1,'鼻'=>1,'ð¯¨'=>1,'Ì€'=>0,'Ì'=>0,'Ì‚'=>0,'̃'=>0,'Ì„'=>0,'̆'=>0,'̇'=>0,'̈'=>0,'̉'=>0,'ÌŠ'=>0,'Ì‹'=>0,'ÌŒ'=>0,'Ì'=>0,'Ì‘'=>0,'Ì“'=>0,'Ì”'=>0,'Ì›'=>0,'Ì£'=>0,'̤'=>0,'Ì¥'=>0,'̦'=>0,'̧'=>0,'̨'=>0,'Ì'=>0,'Ì®'=>0,'̰'=>0,'̱'=>0,'̸'=>0,'Í‚'=>0,'Í…'=>0,'Ù“'=>0,'Ù”'=>0,'Ù•'=>0,'़'=>0,'া'=>0,'à§—'=>0,'ା'=>0,'à–'=>0,'à—'=>0,'ா'=>0,'ௗ'=>0,'à±–'=>0,'ೂ'=>0,'ೕ'=>0,'à³–'=>0,'à´¾'=>0,'ൗ'=>0,'à·Š'=>0,'à·'=>0,'à·Ÿ'=>0,'ီ'=>0,'á…¡'=>0,'á…¢'=>0,'á…£'=>0,'á…¤'=>0,'á…¥'=>0,'á…¦'=>0,'á…§'=>0,'á…¨'=>0,'á…©'=>0,'á…ª'=>0,'á…«'=>0,'á…¬'=>0,'á…'=>0,'á…®'=>0,'á…¯'=>0,'á…°'=>0,'á…±'=>0,'á…²'=>0,'á…³'=>0,'á…´'=>0,'á…µ'=>0,'ᆨ'=>0,'ᆩ'=>0,'ᆪ'=>0,'ᆫ'=>0,'ᆬ'=>0,'á†'=>0,'ᆮ'=>0,'ᆯ'=>0,'ᆰ'=>0,'ᆱ'=>0,'ᆲ'=>0,'ᆳ'=>0,'ᆴ'=>0,'ᆵ'=>0,'ᆶ'=>0,'ᆷ'=>0,'ᆸ'=>0,'ᆹ'=>0,'ᆺ'=>0,'ᆻ'=>0,'ᆼ'=>0,'ᆽ'=>0,'ᆾ'=>0,'ᆿ'=>0,'ᇀ'=>0,'á‡'=>0,'ᇂ'=>0,'ᬵ'=>0,'ã‚™'=>0,'゚'=>0);
\ No newline at end of file diff --git a/phpBB/includes/utf/data/utf_nfkc_qc.php b/phpBB/includes/utf/data/utf_nfkc_qc.php deleted file mode 100644 index da9a8a0e89..0000000000 --- a/phpBB/includes/utf/data/utf_nfkc_qc.php +++ /dev/null @@ -1,2 +0,0 @@ -<?php -$GLOBALS['utf_nfkc_qc']=array(' '=>1,'¨'=>1,'ª'=>1,'¯'=>1,'²'=>1,'³'=>1,'´'=>1,'µ'=>1,'¸'=>1,'¹'=>1,'º'=>1,'¼'=>1,'½'=>1,'¾'=>1,'IJ'=>1,'ij'=>1,'Ä¿'=>1,'Å€'=>1,'ʼn'=>1,'Å¿'=>1,'Ç„'=>1,'Ç…'=>1,'dž'=>1,'LJ'=>1,'Lj'=>1,'lj'=>1,'ÇŠ'=>1,'Ç‹'=>1,'ÇŒ'=>1,'DZ'=>1,'Dz'=>1,'dz'=>1,'ʰ'=>1,'ʱ'=>1,'ʲ'=>1,'ʳ'=>1,'Ê´'=>1,'ʵ'=>1,'ʶ'=>1,'Ê·'=>1,'ʸ'=>1,'˘'=>1,'Ë™'=>1,'Ëš'=>1,'Ë›'=>1,'Ëœ'=>1,'Ë'=>1,'Ë '=>1,'Ë¡'=>1,'Ë¢'=>1,'Ë£'=>1,'ˤ'=>1,'Í€'=>1,'Í'=>1,'̓'=>1,'Í„'=>1,'Í´'=>1,'ͺ'=>1,';'=>1,'΄'=>1,'Î…'=>1,'·'=>1,'Ï'=>1,'Ï‘'=>1,'Ï’'=>1,'Ï“'=>1,'Ï”'=>1,'Ï•'=>1,'Ï–'=>1,'ϰ'=>1,'ϱ'=>1,'ϲ'=>1,'Ï´'=>1,'ϵ'=>1,'Ϲ'=>1,'Ö‡'=>1,'Ùµ'=>1,'Ù¶'=>1,'Ù·'=>1,'Ù¸'=>1,'क़'=>1,'ख़'=>1,'ग़'=>1,'ज़'=>1,'ड़'=>1,'à¥'=>1,'फ़'=>1,'य़'=>1,'à§œ'=>1,'à§'=>1,'à§Ÿ'=>1,'ਲ਼'=>1,'ਸ਼'=>1,'à©™'=>1,'ਗ਼'=>1,'à©›'=>1,'ਫ਼'=>1,'àœ'=>1,'à'=>1,'ำ'=>1,'ຳ'=>1,'ໜ'=>1,'à»'=>1,'༌'=>1,'གྷ'=>1,'à½'=>1,'དྷ'=>1,'བྷ'=>1,'ཛྷ'=>1,'ཀྵ'=>1,'ཱི'=>1,'ཱུ'=>1,'ྲྀ'=>1,'ཷ'=>1,'ླྀ'=>1,'ཹ'=>1,'à¾'=>1,'ྒྷ'=>1,'à¾'=>1,'ྡྷ'=>1,'ྦྷ'=>1,'ྫྷ'=>1,'ྐྵ'=>1,'ჼ'=>1,'á´¬'=>1,'á´'=>1,'á´®'=>1,'á´°'=>1,'á´±'=>1,'á´²'=>1,'á´³'=>1,'á´´'=>1,'á´µ'=>1,'á´¶'=>1,'á´·'=>1,'á´¸'=>1,'á´¹'=>1,'á´º'=>1,'á´¼'=>1,'á´½'=>1,'á´¾'=>1,'á´¿'=>1,'áµ€'=>1,'áµ'=>1,'ᵂ'=>1,'ᵃ'=>1,'ᵄ'=>1,'áµ…'=>1,'ᵆ'=>1,'ᵇ'=>1,'ᵈ'=>1,'ᵉ'=>1,'ᵊ'=>1,'ᵋ'=>1,'ᵌ'=>1,'áµ'=>1,'áµ'=>1,'áµ'=>1,'ᵑ'=>1,'áµ’'=>1,'ᵓ'=>1,'áµ”'=>1,'ᵕ'=>1,'áµ–'=>1,'áµ—'=>1,'ᵘ'=>1,'áµ™'=>1,'ᵚ'=>1,'áµ›'=>1,'ᵜ'=>1,'áµ'=>1,'ᵞ'=>1,'ᵟ'=>1,'áµ '=>1,'ᵡ'=>1,'áµ¢'=>1,'áµ£'=>1,'ᵤ'=>1,'áµ¥'=>1,'ᵦ'=>1,'áµ§'=>1,'ᵨ'=>1,'ᵩ'=>1,'ᵪ'=>1,'ᵸ'=>1,'á¶›'=>1,'á¶œ'=>1,'á¶'=>1,'á¶ž'=>1,'á¶Ÿ'=>1,'á¶ '=>1,'á¶¡'=>1,'á¶¢'=>1,'á¶£'=>1,'ᶤ'=>1,'á¶¥'=>1,'ᶦ'=>1,'á¶§'=>1,'ᶨ'=>1,'á¶©'=>1,'ᶪ'=>1,'á¶«'=>1,'ᶬ'=>1,'á¶'=>1,'á¶®'=>1,'ᶯ'=>1,'á¶°'=>1,'á¶±'=>1,'á¶²'=>1,'á¶³'=>1,'á¶´'=>1,'á¶µ'=>1,'á¶¶'=>1,'á¶·'=>1,'ᶸ'=>1,'á¶¹'=>1,'ᶺ'=>1,'á¶»'=>1,'á¶¼'=>1,'á¶½'=>1,'á¶¾'=>1,'á¶¿'=>1,'ẚ'=>1,'ẛ'=>1,'á½±'=>1,'á½³'=>1,'á½µ'=>1,'á½·'=>1,'á½¹'=>1,'á½»'=>1,'á½½'=>1,'á¾»'=>1,'á¾½'=>1,'á¾¾'=>1,'᾿'=>1,'á¿€'=>1,'á¿'=>1,'Έ'=>1,'á¿‹'=>1,'á¿'=>1,'῎'=>1,'á¿'=>1,'á¿“'=>1,'á¿›'=>1,'á¿'=>1,'῞'=>1,'῟'=>1,'á¿£'=>1,'á¿«'=>1,'á¿'=>1,'á¿®'=>1,'`'=>1,'Ό'=>1,'á¿»'=>1,'´'=>1,'῾'=>1,' '=>1,'â€'=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,' '=>1,'‑'=>1,'‗'=>1,'․'=>1,'‥'=>1,'…'=>1,' '=>1,'″'=>1,'‴'=>1,'‶'=>1,'‷'=>1,'‼'=>1,'‾'=>1,'â‡'=>1,'âˆ'=>1,'â‰'=>1,'â—'=>1,'âŸ'=>1,'â°'=>1,'â±'=>1,'â´'=>1,'âµ'=>1,'â¶'=>1,'â·'=>1,'â¸'=>1,'â¹'=>1,'âº'=>1,'â»'=>1,'â¼'=>1,'â½'=>1,'â¾'=>1,'â¿'=>1,'â‚€'=>1,'â‚'=>1,'â‚‚'=>1,'₃'=>1,'â‚„'=>1,'â‚…'=>1,'₆'=>1,'₇'=>1,'₈'=>1,'₉'=>1,'₊'=>1,'â‚‹'=>1,'₌'=>1,'â‚'=>1,'₎'=>1,'â‚'=>1,'â‚‘'=>1,'â‚’'=>1,'â‚“'=>1,'â‚”'=>1,'₨'=>1,'â„€'=>1,'â„'=>1,'â„‚'=>1,'℃'=>1,'â„…'=>1,'℆'=>1,'ℇ'=>1,'℉'=>1,'ℊ'=>1,'â„‹'=>1,'ℌ'=>1,'â„'=>1,'ℎ'=>1,'â„'=>1,'â„'=>1,'â„‘'=>1,'â„’'=>1,'â„“'=>1,'â„•'=>1,'â„–'=>1,'â„™'=>1,'ℚ'=>1,'â„›'=>1,'ℜ'=>1,'â„'=>1,'â„ '=>1,'â„¡'=>1,'â„¢'=>1,'ℤ'=>1,'Ω'=>1,'ℨ'=>1,'K'=>1,'â„«'=>1,'ℬ'=>1,'â„'=>1,'ℯ'=>1,'â„°'=>1,'ℱ'=>1,'ℳ'=>1,'â„´'=>1,'ℵ'=>1,'â„¶'=>1,'â„·'=>1,'ℸ'=>1,'ℹ'=>1,'â„»'=>1,'ℼ'=>1,'ℽ'=>1,'ℾ'=>1,'â„¿'=>1,'â…€'=>1,'â……'=>1,'â…†'=>1,'â…‡'=>1,'â…ˆ'=>1,'â…‰'=>1,'â…“'=>1,'â…”'=>1,'â…•'=>1,'â…–'=>1,'â…—'=>1,'â…˜'=>1,'â…™'=>1,'â…š'=>1,'â…›'=>1,'â…œ'=>1,'â…'=>1,'â…ž'=>1,'â…Ÿ'=>1,'â… '=>1,'â…¡'=>1,'â…¢'=>1,'â…£'=>1,'â…¤'=>1,'â…¥'=>1,'â…¦'=>1,'â…§'=>1,'â…¨'=>1,'â…©'=>1,'â…ª'=>1,'â…«'=>1,'â…¬'=>1,'â…'=>1,'â…®'=>1,'â…¯'=>1,'â…°'=>1,'â…±'=>1,'â…²'=>1,'â…³'=>1,'â…´'=>1,'â…µ'=>1,'â…¶'=>1,'â…·'=>1,'â…¸'=>1,'â…¹'=>1,'â…º'=>1,'â…»'=>1,'â…¼'=>1,'â…½'=>1,'â…¾'=>1,'â…¿'=>1,'∬'=>1,'âˆ'=>1,'∯'=>1,'∰'=>1,'〈'=>1,'〉'=>1,'â‘ '=>1,'â‘¡'=>1,'â‘¢'=>1,'â‘£'=>1,'⑤'=>1,'â‘¥'=>1,'⑦'=>1,'â‘§'=>1,'⑨'=>1,'â‘©'=>1,'⑪'=>1,'â‘«'=>1,'⑬'=>1,'â‘'=>1,'â‘®'=>1,'⑯'=>1,'â‘°'=>1,'⑱'=>1,'⑲'=>1,'⑳'=>1,'â‘´'=>1,'⑵'=>1,'â‘¶'=>1,'â‘·'=>1,'⑸'=>1,'⑹'=>1,'⑺'=>1,'â‘»'=>1,'⑼'=>1,'⑽'=>1,'⑾'=>1,'â‘¿'=>1,'â’€'=>1,'â’'=>1,'â’‚'=>1,'â’ƒ'=>1,'â’„'=>1,'â’…'=>1,'â’†'=>1,'â’‡'=>1,'â’ˆ'=>1,'â’‰'=>1,'â’Š'=>1,'â’‹'=>1,'â’Œ'=>1,'â’'=>1,'â’Ž'=>1,'â’'=>1,'â’'=>1,'â’‘'=>1,'â’’'=>1,'â’“'=>1,'â’”'=>1,'â’•'=>1,'â’–'=>1,'â’—'=>1,'â’˜'=>1,'â’™'=>1,'â’š'=>1,'â’›'=>1,'â’œ'=>1,'â’'=>1,'â’ž'=>1,'â’Ÿ'=>1,'â’ '=>1,'â’¡'=>1,'â’¢'=>1,'â’£'=>1,'â’¤'=>1,'â’¥'=>1,'â’¦'=>1,'â’§'=>1,'â’¨'=>1,'â’©'=>1,'â’ª'=>1,'â’«'=>1,'â’¬'=>1,'â’'=>1,'â’®'=>1,'â’¯'=>1,'â’°'=>1,'â’±'=>1,'â’²'=>1,'â’³'=>1,'â’´'=>1,'â’µ'=>1,'â’¶'=>1,'â’·'=>1,'â’¸'=>1,'â’¹'=>1,'â’º'=>1,'â’»'=>1,'â’¼'=>1,'â’½'=>1,'â’¾'=>1,'â’¿'=>1,'â“€'=>1,'â“'=>1,'â“‚'=>1,'Ⓝ'=>1,'â“„'=>1,'â“…'=>1,'Ⓠ'=>1,'Ⓡ'=>1,'Ⓢ'=>1,'Ⓣ'=>1,'Ⓤ'=>1,'â“‹'=>1,'Ⓦ'=>1,'â“'=>1,'Ⓨ'=>1,'â“'=>1,'â“'=>1,'â“‘'=>1,'â“’'=>1,'â““'=>1,'â“”'=>1,'â“•'=>1,'â“–'=>1,'â“—'=>1,'ⓘ'=>1,'â“™'=>1,'ⓚ'=>1,'â“›'=>1,'ⓜ'=>1,'â“'=>1,'ⓞ'=>1,'ⓟ'=>1,'â“ '=>1,'â“¡'=>1,'â“¢'=>1,'â“£'=>1,'ⓤ'=>1,'â“¥'=>1,'ⓦ'=>1,'â“§'=>1,'ⓨ'=>1,'â“©'=>1,'⓪'=>1,'⨌'=>1,'â©´'=>1,'⩵'=>1,'â©¶'=>1,'⫝̸'=>1,'ⵯ'=>1,'⺟'=>1,'⻳'=>1,'â¼€'=>1,'â¼'=>1,'⼂'=>1,'⼃'=>1,'⼄'=>1,'â¼…'=>1,'⼆'=>1,'⼇'=>1,'⼈'=>1,'⼉'=>1,'⼊'=>1,'⼋'=>1,'⼌'=>1,'â¼'=>1,'⼎'=>1,'â¼'=>1,'â¼'=>1,'⼑'=>1,'â¼’'=>1,'⼓'=>1,'â¼”'=>1,'⼕'=>1,'â¼–'=>1,'â¼—'=>1,'⼘'=>1,'â¼™'=>1,'⼚'=>1,'â¼›'=>1,'⼜'=>1,'â¼'=>1,'⼞'=>1,'⼟'=>1,'â¼ '=>1,'⼡'=>1,'â¼¢'=>1,'â¼£'=>1,'⼤'=>1,'â¼¥'=>1,'⼦'=>1,'â¼§'=>1,'⼨'=>1,'⼩'=>1,'⼪'=>1,'⼫'=>1,'⼬'=>1,'â¼'=>1,'â¼®'=>1,'⼯'=>1,'â¼°'=>1,'â¼±'=>1,'â¼²'=>1,'â¼³'=>1,'â¼´'=>1,'â¼µ'=>1,'â¼¶'=>1,'â¼·'=>1,'⼸'=>1,'â¼¹'=>1,'⼺'=>1,'â¼»'=>1,'â¼¼'=>1,'â¼½'=>1,'â¼¾'=>1,'⼿'=>1,'â½€'=>1,'â½'=>1,'⽂'=>1,'⽃'=>1,'⽄'=>1,'â½…'=>1,'⽆'=>1,'⽇'=>1,'⽈'=>1,'⽉'=>1,'⽊'=>1,'⽋'=>1,'⽌'=>1,'â½'=>1,'⽎'=>1,'â½'=>1,'â½'=>1,'⽑'=>1,'â½’'=>1,'⽓'=>1,'â½”'=>1,'⽕'=>1,'â½–'=>1,'â½—'=>1,'⽘'=>1,'â½™'=>1,'⽚'=>1,'â½›'=>1,'⽜'=>1,'â½'=>1,'⽞'=>1,'⽟'=>1,'â½ '=>1,'⽡'=>1,'â½¢'=>1,'â½£'=>1,'⽤'=>1,'â½¥'=>1,'⽦'=>1,'â½§'=>1,'⽨'=>1,'⽩'=>1,'⽪'=>1,'⽫'=>1,'⽬'=>1,'â½'=>1,'â½®'=>1,'⽯'=>1,'â½°'=>1,'â½±'=>1,'â½²'=>1,'â½³'=>1,'â½´'=>1,'â½µ'=>1,'â½¶'=>1,'â½·'=>1,'⽸'=>1,'â½¹'=>1,'⽺'=>1,'â½»'=>1,'â½¼'=>1,'â½½'=>1,'â½¾'=>1,'⽿'=>1,'â¾€'=>1,'â¾'=>1,'⾂'=>1,'⾃'=>1,'⾄'=>1,'â¾…'=>1,'⾆'=>1,'⾇'=>1,'⾈'=>1,'⾉'=>1,'⾊'=>1,'⾋'=>1,'⾌'=>1,'â¾'=>1,'⾎'=>1,'â¾'=>1,'â¾'=>1,'⾑'=>1,'â¾’'=>1,'⾓'=>1,'â¾”'=>1,'⾕'=>1,'â¾–'=>1,'â¾—'=>1,'⾘'=>1,'â¾™'=>1,'⾚'=>1,'â¾›'=>1,'⾜'=>1,'â¾'=>1,'⾞'=>1,'⾟'=>1,'â¾ '=>1,'⾡'=>1,'â¾¢'=>1,'â¾£'=>1,'⾤'=>1,'â¾¥'=>1,'⾦'=>1,'â¾§'=>1,'⾨'=>1,'⾩'=>1,'⾪'=>1,'⾫'=>1,'⾬'=>1,'â¾'=>1,'â¾®'=>1,'⾯'=>1,'â¾°'=>1,'â¾±'=>1,'â¾²'=>1,'â¾³'=>1,'â¾´'=>1,'â¾µ'=>1,'â¾¶'=>1,'â¾·'=>1,'⾸'=>1,'â¾¹'=>1,'⾺'=>1,'â¾»'=>1,'â¾¼'=>1,'â¾½'=>1,'â¾¾'=>1,'⾿'=>1,'â¿€'=>1,'â¿'=>1,'â¿‚'=>1,'⿃'=>1,'â¿„'=>1,'â¿…'=>1,'⿆'=>1,'⿇'=>1,'⿈'=>1,'⿉'=>1,'⿊'=>1,'â¿‹'=>1,'⿌'=>1,'â¿'=>1,'⿎'=>1,'â¿'=>1,'â¿'=>1,'â¿‘'=>1,'â¿’'=>1,'â¿“'=>1,'â¿”'=>1,'â¿•'=>1,' '=>1,'〶'=>1,'〸'=>1,'〹'=>1,'〺'=>1,'ã‚›'=>1,'゜'=>1,'ゟ'=>1,'ヿ'=>1,'ㄱ'=>1,'ㄲ'=>1,'ㄳ'=>1,'ã„´'=>1,'ㄵ'=>1,'ã„¶'=>1,'ã„·'=>1,'ㄸ'=>1,'ㄹ'=>1,'ㄺ'=>1,'ã„»'=>1,'ㄼ'=>1,'ㄽ'=>1,'ㄾ'=>1,'ã„¿'=>1,'ã…€'=>1,'ã…'=>1,'ã…‚'=>1,'ã…ƒ'=>1,'ã…„'=>1,'ã……'=>1,'ã…†'=>1,'ã…‡'=>1,'ã…ˆ'=>1,'ã…‰'=>1,'ã…Š'=>1,'ã…‹'=>1,'ã…Œ'=>1,'ã…'=>1,'ã…Ž'=>1,'ã…'=>1,'ã…'=>1,'ã…‘'=>1,'ã…’'=>1,'ã…“'=>1,'ã…”'=>1,'ã…•'=>1,'ã…–'=>1,'ã…—'=>1,'ã…˜'=>1,'ã…™'=>1,'ã…š'=>1,'ã…›'=>1,'ã…œ'=>1,'ã…'=>1,'ã…ž'=>1,'ã…Ÿ'=>1,'ã… '=>1,'ã…¡'=>1,'ã…¢'=>1,'ã…£'=>1,'ã…¤'=>1,'ã…¥'=>1,'ã…¦'=>1,'ã…§'=>1,'ã…¨'=>1,'ã…©'=>1,'ã…ª'=>1,'ã…«'=>1,'ã…¬'=>1,'ã…'=>1,'ã…®'=>1,'ã…¯'=>1,'ã…°'=>1,'ã…±'=>1,'ã…²'=>1,'ã…³'=>1,'ã…´'=>1,'ã…µ'=>1,'ã…¶'=>1,'ã…·'=>1,'ã…¸'=>1,'ã…¹'=>1,'ã…º'=>1,'ã…»'=>1,'ã…¼'=>1,'ã…½'=>1,'ã…¾'=>1,'ã…¿'=>1,'ㆀ'=>1,'ã†'=>1,'ㆂ'=>1,'ㆃ'=>1,'ㆄ'=>1,'ㆅ'=>1,'ㆆ'=>1,'ㆇ'=>1,'ㆈ'=>1,'ㆉ'=>1,'ㆊ'=>1,'ㆋ'=>1,'ㆌ'=>1,'ã†'=>1,'ㆎ'=>1,'㆒'=>1,'㆓'=>1,'㆔'=>1,'㆕'=>1,'㆖'=>1,'㆗'=>1,'㆘'=>1,'㆙'=>1,'㆚'=>1,'㆛'=>1,'㆜'=>1,'ã†'=>1,'㆞'=>1,'㆟'=>1,'㈀'=>1,'ãˆ'=>1,'㈂'=>1,'㈃'=>1,'㈄'=>1,'㈅'=>1,'㈆'=>1,'㈇'=>1,'㈈'=>1,'㈉'=>1,'㈊'=>1,'㈋'=>1,'㈌'=>1,'ãˆ'=>1,'㈎'=>1,'ãˆ'=>1,'ãˆ'=>1,'㈑'=>1,'㈒'=>1,'㈓'=>1,'㈔'=>1,'㈕'=>1,'㈖'=>1,'㈗'=>1,'㈘'=>1,'㈙'=>1,'㈚'=>1,'㈛'=>1,'㈜'=>1,'ãˆ'=>1,'㈞'=>1,'㈠'=>1,'㈡'=>1,'㈢'=>1,'㈣'=>1,'㈤'=>1,'㈥'=>1,'㈦'=>1,'㈧'=>1,'㈨'=>1,'㈩'=>1,'㈪'=>1,'㈫'=>1,'㈬'=>1,'ãˆ'=>1,'㈮'=>1,'㈯'=>1,'㈰'=>1,'㈱'=>1,'㈲'=>1,'㈳'=>1,'㈴'=>1,'㈵'=>1,'㈶'=>1,'㈷'=>1,'㈸'=>1,'㈹'=>1,'㈺'=>1,'㈻'=>1,'㈼'=>1,'㈽'=>1,'㈾'=>1,'㈿'=>1,'㉀'=>1,'ã‰'=>1,'㉂'=>1,'㉃'=>1,'ã‰'=>1,'㉑'=>1,'㉒'=>1,'㉓'=>1,'㉔'=>1,'㉕'=>1,'㉖'=>1,'㉗'=>1,'㉘'=>1,'㉙'=>1,'㉚'=>1,'㉛'=>1,'㉜'=>1,'ã‰'=>1,'㉞'=>1,'㉟'=>1,'㉠'=>1,'㉡'=>1,'㉢'=>1,'㉣'=>1,'㉤'=>1,'㉥'=>1,'㉦'=>1,'㉧'=>1,'㉨'=>1,'㉩'=>1,'㉪'=>1,'㉫'=>1,'㉬'=>1,'ã‰'=>1,'㉮'=>1,'㉯'=>1,'㉰'=>1,'㉱'=>1,'㉲'=>1,'㉳'=>1,'㉴'=>1,'㉵'=>1,'㉶'=>1,'㉷'=>1,'㉸'=>1,'㉹'=>1,'㉺'=>1,'㉻'=>1,'㉼'=>1,'㉽'=>1,'㉾'=>1,'㊀'=>1,'ãŠ'=>1,'㊂'=>1,'㊃'=>1,'㊄'=>1,'㊅'=>1,'㊆'=>1,'㊇'=>1,'㊈'=>1,'㊉'=>1,'㊊'=>1,'㊋'=>1,'㊌'=>1,'ãŠ'=>1,'㊎'=>1,'ãŠ'=>1,'ãŠ'=>1,'㊑'=>1,'㊒'=>1,'㊓'=>1,'㊔'=>1,'㊕'=>1,'㊖'=>1,'㊗'=>1,'㊘'=>1,'㊙'=>1,'㊚'=>1,'㊛'=>1,'㊜'=>1,'ãŠ'=>1,'㊞'=>1,'㊟'=>1,'㊠'=>1,'㊡'=>1,'㊢'=>1,'㊣'=>1,'㊤'=>1,'㊥'=>1,'㊦'=>1,'㊧'=>1,'㊨'=>1,'㊩'=>1,'㊪'=>1,'㊫'=>1,'㊬'=>1,'ãŠ'=>1,'㊮'=>1,'㊯'=>1,'㊰'=>1,'㊱'=>1,'㊲'=>1,'㊳'=>1,'㊴'=>1,'㊵'=>1,'㊶'=>1,'㊷'=>1,'㊸'=>1,'㊹'=>1,'㊺'=>1,'㊻'=>1,'㊼'=>1,'㊽'=>1,'㊾'=>1,'㊿'=>1,'ã‹€'=>1,'ã‹'=>1,'ã‹‚'=>1,'㋃'=>1,'ã‹„'=>1,'ã‹…'=>1,'㋆'=>1,'㋇'=>1,'㋈'=>1,'㋉'=>1,'㋊'=>1,'ã‹‹'=>1,'㋌'=>1,'ã‹'=>1,'㋎'=>1,'ã‹'=>1,'ã‹'=>1,'ã‹‘'=>1,'ã‹’'=>1,'ã‹“'=>1,'ã‹”'=>1,'ã‹•'=>1,'ã‹–'=>1,'ã‹—'=>1,'㋘'=>1,'ã‹™'=>1,'㋚'=>1,'ã‹›'=>1,'㋜'=>1,'ã‹'=>1,'㋞'=>1,'㋟'=>1,'ã‹ '=>1,'ã‹¡'=>1,'ã‹¢'=>1,'ã‹£'=>1,'㋤'=>1,'ã‹¥'=>1,'㋦'=>1,'ã‹§'=>1,'㋨'=>1,'ã‹©'=>1,'㋪'=>1,'ã‹«'=>1,'㋬'=>1,'ã‹'=>1,'ã‹®'=>1,'㋯'=>1,'ã‹°'=>1,'㋱'=>1,'㋲'=>1,'㋳'=>1,'ã‹´'=>1,'㋵'=>1,'ã‹¶'=>1,'ã‹·'=>1,'㋸'=>1,'㋹'=>1,'㋺'=>1,'ã‹»'=>1,'㋼'=>1,'㋽'=>1,'㋾'=>1,'㌀'=>1,'ãŒ'=>1,'㌂'=>1,'㌃'=>1,'㌄'=>1,'㌅'=>1,'㌆'=>1,'㌇'=>1,'㌈'=>1,'㌉'=>1,'㌊'=>1,'㌋'=>1,'㌌'=>1,'ãŒ'=>1,'㌎'=>1,'ãŒ'=>1,'ãŒ'=>1,'㌑'=>1,'㌒'=>1,'㌓'=>1,'㌔'=>1,'㌕'=>1,'㌖'=>1,'㌗'=>1,'㌘'=>1,'㌙'=>1,'㌚'=>1,'㌛'=>1,'㌜'=>1,'ãŒ'=>1,'㌞'=>1,'㌟'=>1,'㌠'=>1,'㌡'=>1,'㌢'=>1,'㌣'=>1,'㌤'=>1,'㌥'=>1,'㌦'=>1,'㌧'=>1,'㌨'=>1,'㌩'=>1,'㌪'=>1,'㌫'=>1,'㌬'=>1,'ãŒ'=>1,'㌮'=>1,'㌯'=>1,'㌰'=>1,'㌱'=>1,'㌲'=>1,'㌳'=>1,'㌴'=>1,'㌵'=>1,'㌶'=>1,'㌷'=>1,'㌸'=>1,'㌹'=>1,'㌺'=>1,'㌻'=>1,'㌼'=>1,'㌽'=>1,'㌾'=>1,'㌿'=>1,'ã€'=>1,'ã'=>1,'ã‚'=>1,'ãƒ'=>1,'ã„'=>1,'ã…'=>1,'ã†'=>1,'ã‡'=>1,'ãˆ'=>1,'ã‰'=>1,'ãŠ'=>1,'ã‹'=>1,'ãŒ'=>1,'ã'=>1,'ãŽ'=>1,'ã'=>1,'ã'=>1,'ã‘'=>1,'ã’'=>1,'ã“'=>1,'ã”'=>1,'ã•'=>1,'ã–'=>1,'ã—'=>1,'ã˜'=>1,'ã™'=>1,'ãš'=>1,'ã›'=>1,'ãœ'=>1,'ã'=>1,'ãž'=>1,'ãŸ'=>1,'ã '=>1,'ã¡'=>1,'ã¢'=>1,'ã£'=>1,'ã¤'=>1,'ã¥'=>1,'ã¦'=>1,'ã§'=>1,'ã¨'=>1,'ã©'=>1,'ãª'=>1,'ã«'=>1,'ã¬'=>1,'ã'=>1,'ã®'=>1,'ã¯'=>1,'ã°'=>1,'ã±'=>1,'ã²'=>1,'ã³'=>1,'ã´'=>1,'ãµ'=>1,'ã¶'=>1,'ã·'=>1,'ã¸'=>1,'ã¹'=>1,'ãº'=>1,'ã»'=>1,'ã¼'=>1,'ã½'=>1,'ã¾'=>1,'ã¿'=>1,'㎀'=>1,'ãŽ'=>1,'㎂'=>1,'㎃'=>1,'㎄'=>1,'㎅'=>1,'㎆'=>1,'㎇'=>1,'㎈'=>1,'㎉'=>1,'㎊'=>1,'㎋'=>1,'㎌'=>1,'ãŽ'=>1,'㎎'=>1,'ãŽ'=>1,'ãŽ'=>1,'㎑'=>1,'㎒'=>1,'㎓'=>1,'㎔'=>1,'㎕'=>1,'㎖'=>1,'㎗'=>1,'㎘'=>1,'㎙'=>1,'㎚'=>1,'㎛'=>1,'㎜'=>1,'ãŽ'=>1,'㎞'=>1,'㎟'=>1,'㎠'=>1,'㎡'=>1,'㎢'=>1,'㎣'=>1,'㎤'=>1,'㎥'=>1,'㎦'=>1,'㎧'=>1,'㎨'=>1,'㎩'=>1,'㎪'=>1,'㎫'=>1,'㎬'=>1,'ãŽ'=>1,'㎮'=>1,'㎯'=>1,'㎰'=>1,'㎱'=>1,'㎲'=>1,'㎳'=>1,'㎴'=>1,'㎵'=>1,'㎶'=>1,'㎷'=>1,'㎸'=>1,'㎹'=>1,'㎺'=>1,'㎻'=>1,'㎼'=>1,'㎽'=>1,'㎾'=>1,'㎿'=>1,'ã€'=>1,'ã'=>1,'ã‚'=>1,'ãƒ'=>1,'ã„'=>1,'ã…'=>1,'ã†'=>1,'ã‡'=>1,'ãˆ'=>1,'ã‰'=>1,'ãŠ'=>1,'ã‹'=>1,'ãŒ'=>1,'ã'=>1,'ãŽ'=>1,'ã'=>1,'ã'=>1,'ã‘'=>1,'ã’'=>1,'ã“'=>1,'ã”'=>1,'ã•'=>1,'ã–'=>1,'ã—'=>1,'ã˜'=>1,'ã™'=>1,'ãš'=>1,'ã›'=>1,'ãœ'=>1,'ã'=>1,'ãž'=>1,'ãŸ'=>1,'ã '=>1,'ã¡'=>1,'ã¢'=>1,'ã£'=>1,'ã¤'=>1,'ã¥'=>1,'ã¦'=>1,'ã§'=>1,'ã¨'=>1,'ã©'=>1,'ãª'=>1,'ã«'=>1,'ã¬'=>1,'ã'=>1,'ã®'=>1,'ã¯'=>1,'ã°'=>1,'ã±'=>1,'ã²'=>1,'ã³'=>1,'ã´'=>1,'ãµ'=>1,'ã¶'=>1,'ã·'=>1,'ã¸'=>1,'ã¹'=>1,'ãº'=>1,'ã»'=>1,'ã¼'=>1,'ã½'=>1,'ã¾'=>1,'ã¿'=>1,'豈'=>1,'ï¤'=>1,'車'=>1,'賈'=>1,'滑'=>1,'串'=>1,'句'=>1,'龜'=>1,'龜'=>1,'契'=>1,'金'=>1,'喇'=>1,'奈'=>1,'ï¤'=>1,'癩'=>1,'ï¤'=>1,'ï¤'=>1,'螺'=>1,'裸'=>1,'邏'=>1,'樂'=>1,'洛'=>1,'烙'=>1,'珞'=>1,'落'=>1,'酪'=>1,'駱'=>1,'亂'=>1,'卵'=>1,'ï¤'=>1,'爛'=>1,'蘭'=>1,'ï¤ '=>1,'嵐'=>1,'濫'=>1,'藍'=>1,'襤'=>1,'拉'=>1,'臘'=>1,'蠟'=>1,'廊'=>1,'朗'=>1,'浪'=>1,'狼'=>1,'郎'=>1,'ï¤'=>1,'冷'=>1,'勞'=>1,'擄'=>1,'櫓'=>1,'爐'=>1,'盧'=>1,'老'=>1,'蘆'=>1,'虜'=>1,'路'=>1,'露'=>1,'魯'=>1,'鷺'=>1,'碌'=>1,'祿'=>1,'綠'=>1,'菉'=>1,'錄'=>1,'鹿'=>1,'ï¥'=>1,'壟'=>1,'弄'=>1,'籠'=>1,'聾'=>1,'牢'=>1,'磊'=>1,'賂'=>1,'雷'=>1,'壘'=>1,'屢'=>1,'樓'=>1,'ï¥'=>1,'漏'=>1,'ï¥'=>1,'ï¥'=>1,'陋'=>1,'勒'=>1,'肋'=>1,'凜'=>1,'凌'=>1,'稜'=>1,'綾'=>1,'菱'=>1,'陵'=>1,'讀'=>1,'拏'=>1,'樂'=>1,'ï¥'=>1,'丹'=>1,'寧'=>1,'ï¥ '=>1,'率'=>1,'異'=>1,'北'=>1,'磻'=>1,'便'=>1,'復'=>1,'不'=>1,'泌'=>1,'數'=>1,'索'=>1,'參'=>1,'塞'=>1,'ï¥'=>1,'葉'=>1,'說'=>1,'殺'=>1,'辰'=>1,'沈'=>1,'拾'=>1,'若'=>1,'掠'=>1,'略'=>1,'亮'=>1,'兩'=>1,'凉'=>1,'梁'=>1,'糧'=>1,'良'=>1,'諒'=>1,'量'=>1,'勵'=>1,'呂'=>1,'ï¦'=>1,'廬'=>1,'旅'=>1,'濾'=>1,'礪'=>1,'閭'=>1,'驪'=>1,'麗'=>1,'黎'=>1,'力'=>1,'曆'=>1,'歷'=>1,'ï¦'=>1,'年'=>1,'ï¦'=>1,'ï¦'=>1,'撚'=>1,'漣'=>1,'煉'=>1,'璉'=>1,'秊'=>1,'練'=>1,'聯'=>1,'輦'=>1,'蓮'=>1,'連'=>1,'鍊'=>1,'列'=>1,'ï¦'=>1,'咽'=>1,'烈'=>1,'ï¦ '=>1,'說'=>1,'廉'=>1,'念'=>1,'捻'=>1,'殮'=>1,'簾'=>1,'獵'=>1,'令'=>1,'囹'=>1,'寧'=>1,'嶺'=>1,'怜'=>1,'ï¦'=>1,'瑩'=>1,'羚'=>1,'聆'=>1,'鈴'=>1,'零'=>1,'靈'=>1,'領'=>1,'例'=>1,'禮'=>1,'醴'=>1,'隸'=>1,'惡'=>1,'了'=>1,'僚'=>1,'寮'=>1,'尿'=>1,'料'=>1,'樂'=>1,'ï§€'=>1,'ï§'=>1,'ï§‚'=>1,'遼'=>1,'ï§„'=>1,'ï§…'=>1,'阮'=>1,'劉'=>1,'杻'=>1,'柳'=>1,'ï§Š'=>1,'ï§‹'=>1,'ï§Œ'=>1,'ï§'=>1,'ï§Ž'=>1,'ï§'=>1,'ï§'=>1,'ï§‘'=>1,'ï§’'=>1,'ï§“'=>1,'ï§”'=>1,'ï§•'=>1,'ï§–'=>1,'ï§—'=>1,'律'=>1,'ï§™'=>1,'ï§š'=>1,'ï§›'=>1,'ï§œ'=>1,'ï§'=>1,'ï§ž'=>1,'ï§Ÿ'=>1,'ï§ '=>1,'ï§¡'=>1,'ï§¢'=>1,'ï§£'=>1,'理'=>1,'ï§¥'=>1,'罹'=>1,'ï§§'=>1,'裡'=>1,'ï§©'=>1,'離'=>1,'ï§«'=>1,'溺'=>1,'ï§'=>1,'ï§®'=>1,'璘'=>1,'ï§°'=>1,'ï§±'=>1,'ï§²'=>1,'ï§³'=>1,'ï§´'=>1,'ï§µ'=>1,'ï§¶'=>1,'ï§·'=>1,'笠'=>1,'ï§¹'=>1,'狀'=>1,'ï§»'=>1,'ï§¼'=>1,'ï§½'=>1,'ï§¾'=>1,'ï§¿'=>1,'切'=>1,'ï¨'=>1,'拓'=>1,'糖'=>1,'宅'=>1,'洞'=>1,'暴'=>1,'輻'=>1,'行'=>1,'降'=>1,'見'=>1,'廓'=>1,'兀'=>1,'ï¨'=>1,'ï¨'=>1,'晴'=>1,'凞'=>1,'猪'=>1,'益'=>1,'礼'=>1,'神'=>1,'祥'=>1,'福'=>1,'靖'=>1,'ï¨'=>1,'羽'=>1,'ï¨ '=>1,'諸'=>1,'逸'=>1,'都'=>1,'飯'=>1,'飼'=>1,'館'=>1,'ï¨'=>1,'侮'=>1,'僧'=>1,'免'=>1,'勉'=>1,'勤'=>1,'卑'=>1,'喝'=>1,'嘆'=>1,'器'=>1,'塀'=>1,'墨'=>1,'層'=>1,'屮'=>1,'悔'=>1,'慨'=>1,'憎'=>1,'ï©€'=>1,'ï©'=>1,'ï©‚'=>1,'暑'=>1,'ï©„'=>1,'ï©…'=>1,'渚'=>1,'漢'=>1,'煮'=>1,'爫'=>1,'琢'=>1,'ï©‹'=>1,'社'=>1,'ï©'=>1,'祈'=>1,'ï©'=>1,'ï©'=>1,'ï©‘'=>1,'ï©’'=>1,'ï©“'=>1,'ï©”'=>1,'ï©•'=>1,'ï©–'=>1,'ï©—'=>1,'縉'=>1,'ï©™'=>1,'署'=>1,'ï©›'=>1,'臭'=>1,'ï©'=>1,'艹'=>1,'著'=>1,'ï© '=>1,'ï©¡'=>1,'ï©¢'=>1,'ï©£'=>1,'賓'=>1,'ï©¥'=>1,'辶'=>1,'ï©§'=>1,'難'=>1,'ï©©'=>1,'頻'=>1,'ï©°'=>1,'况'=>1,'全'=>1,'侀'=>1,'ï©´'=>1,'冀'=>1,'ï©¶'=>1,'ï©·'=>1,'喝'=>1,'啕'=>1,'喙'=>1,'ï©»'=>1,'塚'=>1,'墳'=>1,'奄'=>1,'ï©¿'=>1,'婢'=>1,'ïª'=>1,'廒'=>1,'廙'=>1,'彩'=>1,'徭'=>1,'惘'=>1,'慎'=>1,'愈'=>1,'憎'=>1,'慠'=>1,'懲'=>1,'戴'=>1,'ïª'=>1,'搜'=>1,'ïª'=>1,'ïª'=>1,'晴'=>1,'朗'=>1,'望'=>1,'杖'=>1,'歹'=>1,'殺'=>1,'流'=>1,'滛'=>1,'滋'=>1,'漢'=>1,'瀞'=>1,'煮'=>1,'ïª'=>1,'爵'=>1,'犯'=>1,'ïª '=>1,'瑱'=>1,'甆'=>1,'画'=>1,'瘝'=>1,'瘟'=>1,'益'=>1,'盛'=>1,'直'=>1,'睊'=>1,'着'=>1,'磌'=>1,'窱'=>1,'ïª'=>1,'类'=>1,'絛'=>1,'練'=>1,'缾'=>1,'者'=>1,'荒'=>1,'華'=>1,'蝹'=>1,'襁'=>1,'覆'=>1,'視'=>1,'調'=>1,'諸'=>1,'請'=>1,'謁'=>1,'諾'=>1,'諭'=>1,'謹'=>1,'ï«€'=>1,'ï«'=>1,'ï«‚'=>1,'遲'=>1,'ï«„'=>1,'ï«…'=>1,'陼'=>1,'難'=>1,'靖'=>1,'韛'=>1,'響'=>1,'ï«‹'=>1,'頻'=>1,'ï«'=>1,'龜'=>1,'ï«'=>1,'ï«'=>1,'ï«‘'=>1,'ï«’'=>1,'ï«“'=>1,'ï«”'=>1,'ï«•'=>1,'ï«–'=>1,'ï«—'=>1,'齃'=>1,'ï«™'=>1,'ff'=>1,'ï¬'=>1,'fl'=>1,'ffi'=>1,'ffl'=>1,'ſt'=>1,'st'=>1,'ﬓ'=>1,'ﬔ'=>1,'ﬕ'=>1,'ﬖ'=>1,'ﬗ'=>1,'ï¬'=>1,'ײַ'=>1,'ï¬ '=>1,'ﬡ'=>1,'ﬢ'=>1,'ﬣ'=>1,'ﬤ'=>1,'ﬥ'=>1,'ﬦ'=>1,'ﬧ'=>1,'ﬨ'=>1,'﬩'=>1,'שׁ'=>1,'שׂ'=>1,'שּׁ'=>1,'ï¬'=>1,'אַ'=>1,'אָ'=>1,'אּ'=>1,'בּ'=>1,'גּ'=>1,'דּ'=>1,'הּ'=>1,'וּ'=>1,'זּ'=>1,'טּ'=>1,'יּ'=>1,'ךּ'=>1,'כּ'=>1,'לּ'=>1,'מּ'=>1,'ï€'=>1,'ï'=>1,'ïƒ'=>1,'ï„'=>1,'ï†'=>1,'ï‡'=>1,'ïˆ'=>1,'ï‰'=>1,'ïŠ'=>1,'ï‹'=>1,'ïŒ'=>1,'ï'=>1,'ïŽ'=>1,'ï'=>1,'ï'=>1,'ï‘'=>1,'ï’'=>1,'ï“'=>1,'ï”'=>1,'ï•'=>1,'ï–'=>1,'ï—'=>1,'ï˜'=>1,'ï™'=>1,'ïš'=>1,'ï›'=>1,'ïœ'=>1,'ï'=>1,'ïž'=>1,'ïŸ'=>1,'ï '=>1,'ï¡'=>1,'ï¢'=>1,'ï£'=>1,'ï¤'=>1,'ï¥'=>1,'ï¦'=>1,'ï§'=>1,'ï¨'=>1,'ï©'=>1,'ïª'=>1,'ï«'=>1,'ï¬'=>1,'ï'=>1,'ï®'=>1,'ï¯'=>1,'ï°'=>1,'ï±'=>1,'ï²'=>1,'ï³'=>1,'ï´'=>1,'ïµ'=>1,'ï¶'=>1,'ï·'=>1,'ï¸'=>1,'ï¹'=>1,'ïº'=>1,'ï»'=>1,'ï¼'=>1,'ï½'=>1,'ï¾'=>1,'ï¿'=>1,'ﮀ'=>1,'ï®'=>1,'ﮂ'=>1,'ﮃ'=>1,'ﮄ'=>1,'ï®…'=>1,'ﮆ'=>1,'ﮇ'=>1,'ﮈ'=>1,'ﮉ'=>1,'ﮊ'=>1,'ﮋ'=>1,'ﮌ'=>1,'ï®'=>1,'ﮎ'=>1,'ï®'=>1,'ï®'=>1,'ﮑ'=>1,'ï®’'=>1,'ﮓ'=>1,'ï®”'=>1,'ﮕ'=>1,'ï®–'=>1,'ï®—'=>1,'ﮘ'=>1,'ï®™'=>1,'ﮚ'=>1,'ï®›'=>1,'ﮜ'=>1,'ï®'=>1,'ﮞ'=>1,'ﮟ'=>1,'ï® '=>1,'ﮡ'=>1,'ﮢ'=>1,'ﮣ'=>1,'ﮤ'=>1,'ﮥ'=>1,'ﮦ'=>1,'ï®§'=>1,'ﮨ'=>1,'ﮩ'=>1,'ﮪ'=>1,'ﮫ'=>1,'ﮬ'=>1,'ï®'=>1,'ï®®'=>1,'ﮯ'=>1,'ï®°'=>1,'ï®±'=>1,'ﯓ'=>1,'ﯔ'=>1,'ﯕ'=>1,'ﯖ'=>1,'ﯗ'=>1,'ﯘ'=>1,'ﯙ'=>1,'ﯚ'=>1,'ﯛ'=>1,'ﯜ'=>1,'ï¯'=>1,'ﯞ'=>1,'ﯟ'=>1,'ï¯ '=>1,'ﯡ'=>1,'ﯢ'=>1,'ﯣ'=>1,'ﯤ'=>1,'ﯥ'=>1,'ﯦ'=>1,'ﯧ'=>1,'ﯨ'=>1,'ﯩ'=>1,'ﯪ'=>1,'ﯫ'=>1,'ﯬ'=>1,'ï¯'=>1,'ﯮ'=>1,'ﯯ'=>1,'ﯰ'=>1,'ﯱ'=>1,'ﯲ'=>1,'ﯳ'=>1,'ﯴ'=>1,'ﯵ'=>1,'ﯶ'=>1,'ﯷ'=>1,'ﯸ'=>1,'ﯹ'=>1,'ﯺ'=>1,'ﯻ'=>1,'ﯼ'=>1,'ﯽ'=>1,'ﯾ'=>1,'ﯿ'=>1,'ï°€'=>1,'ï°'=>1,'ï°‚'=>1,'ï°ƒ'=>1,'ï°„'=>1,'ï°…'=>1,'ï°†'=>1,'ï°‡'=>1,'ï°ˆ'=>1,'ï°‰'=>1,'ï°Š'=>1,'ï°‹'=>1,'ï°Œ'=>1,'ï°'=>1,'ï°Ž'=>1,'ï°'=>1,'ï°'=>1,'ï°‘'=>1,'ï°’'=>1,'ï°“'=>1,'ï°”'=>1,'ï°•'=>1,'ï°–'=>1,'ï°—'=>1,'ï°˜'=>1,'ï°™'=>1,'ï°š'=>1,'ï°›'=>1,'ï°œ'=>1,'ï°'=>1,'ï°ž'=>1,'ï°Ÿ'=>1,'ï° '=>1,'ï°¡'=>1,'ï°¢'=>1,'ï°£'=>1,'ï°¤'=>1,'ï°¥'=>1,'ï°¦'=>1,'ï°§'=>1,'ï°¨'=>1,'ï°©'=>1,'ï°ª'=>1,'ï°«'=>1,'ï°¬'=>1,'ï°'=>1,'ï°®'=>1,'ï°¯'=>1,'ï°°'=>1,'ï°±'=>1,'ï°²'=>1,'ï°³'=>1,'ï°´'=>1,'ï°µ'=>1,'ï°¶'=>1,'ï°·'=>1,'ï°¸'=>1,'ï°¹'=>1,'ï°º'=>1,'ï°»'=>1,'ï°¼'=>1,'ï°½'=>1,'ï°¾'=>1,'ï°¿'=>1,'ï±€'=>1,'ï±'=>1,'ﱂ'=>1,'ﱃ'=>1,'ﱄ'=>1,'ï±…'=>1,'ﱆ'=>1,'ﱇ'=>1,'ﱈ'=>1,'ﱉ'=>1,'ﱊ'=>1,'ﱋ'=>1,'ﱌ'=>1,'ï±'=>1,'ﱎ'=>1,'ï±'=>1,'ï±'=>1,'ﱑ'=>1,'ï±’'=>1,'ﱓ'=>1,'ï±”'=>1,'ﱕ'=>1,'ï±–'=>1,'ï±—'=>1,'ﱘ'=>1,'ï±™'=>1,'ﱚ'=>1,'ï±›'=>1,'ﱜ'=>1,'ï±'=>1,'ﱞ'=>1,'ﱟ'=>1,'ï± '=>1,'ﱡ'=>1,'ï±¢'=>1,'ï±£'=>1,'ﱤ'=>1,'ï±¥'=>1,'ﱦ'=>1,'ï±§'=>1,'ﱨ'=>1,'ﱩ'=>1,'ﱪ'=>1,'ﱫ'=>1,'ﱬ'=>1,'ï±'=>1,'ï±®'=>1,'ﱯ'=>1,'ï±°'=>1,'ï±±'=>1,'ï±²'=>1,'ï±³'=>1,'ï±´'=>1,'ï±µ'=>1,'ï±¶'=>1,'ï±·'=>1,'ﱸ'=>1,'ï±¹'=>1,'ﱺ'=>1,'ï±»'=>1,'ï±¼'=>1,'ï±½'=>1,'ï±¾'=>1,'ﱿ'=>1,'ï²€'=>1,'ï²'=>1,'ﲂ'=>1,'ﲃ'=>1,'ﲄ'=>1,'ï²…'=>1,'ﲆ'=>1,'ﲇ'=>1,'ﲈ'=>1,'ﲉ'=>1,'ﲊ'=>1,'ﲋ'=>1,'ﲌ'=>1,'ï²'=>1,'ﲎ'=>1,'ï²'=>1,'ï²'=>1,'ﲑ'=>1,'ï²’'=>1,'ﲓ'=>1,'ï²”'=>1,'ﲕ'=>1,'ï²–'=>1,'ï²—'=>1,'ﲘ'=>1,'ï²™'=>1,'ﲚ'=>1,'ï²›'=>1,'ﲜ'=>1,'ï²'=>1,'ﲞ'=>1,'ﲟ'=>1,'ï² '=>1,'ﲡ'=>1,'ï²¢'=>1,'ï²£'=>1,'ﲤ'=>1,'ï²¥'=>1,'ﲦ'=>1,'ï²§'=>1,'ﲨ'=>1,'ﲩ'=>1,'ﲪ'=>1,'ﲫ'=>1,'ﲬ'=>1,'ï²'=>1,'ï²®'=>1,'ﲯ'=>1,'ï²°'=>1,'ï²±'=>1,'ï²²'=>1,'ï²³'=>1,'ï²´'=>1,'ï²µ'=>1,'ï²¶'=>1,'ï²·'=>1,'ﲸ'=>1,'ï²¹'=>1,'ﲺ'=>1,'ï²»'=>1,'ï²¼'=>1,'ï²½'=>1,'ï²¾'=>1,'ﲿ'=>1,'ï³€'=>1,'ï³'=>1,'ﳂ'=>1,'ﳃ'=>1,'ﳄ'=>1,'ï³…'=>1,'ﳆ'=>1,'ﳇ'=>1,'ﳈ'=>1,'ﳉ'=>1,'ﳊ'=>1,'ﳋ'=>1,'ﳌ'=>1,'ï³'=>1,'ﳎ'=>1,'ï³'=>1,'ï³'=>1,'ﳑ'=>1,'ï³’'=>1,'ﳓ'=>1,'ï³”'=>1,'ﳕ'=>1,'ï³–'=>1,'ï³—'=>1,'ﳘ'=>1,'ï³™'=>1,'ﳚ'=>1,'ï³›'=>1,'ﳜ'=>1,'ï³'=>1,'ﳞ'=>1,'ﳟ'=>1,'ï³ '=>1,'ﳡ'=>1,'ï³¢'=>1,'ï³£'=>1,'ﳤ'=>1,'ï³¥'=>1,'ﳦ'=>1,'ï³§'=>1,'ﳨ'=>1,'ﳩ'=>1,'ﳪ'=>1,'ﳫ'=>1,'ﳬ'=>1,'ï³'=>1,'ï³®'=>1,'ﳯ'=>1,'ï³°'=>1,'ï³±'=>1,'ï³²'=>1,'ï³³'=>1,'ï³´'=>1,'ï³µ'=>1,'ï³¶'=>1,'ï³·'=>1,'ﳸ'=>1,'ï³¹'=>1,'ﳺ'=>1,'ï³»'=>1,'ï³¼'=>1,'ï³½'=>1,'ï³¾'=>1,'ﳿ'=>1,'ï´€'=>1,'ï´'=>1,'ï´‚'=>1,'ï´ƒ'=>1,'ï´„'=>1,'ï´…'=>1,'ï´†'=>1,'ï´‡'=>1,'ï´ˆ'=>1,'ï´‰'=>1,'ï´Š'=>1,'ï´‹'=>1,'ï´Œ'=>1,'ï´'=>1,'ï´Ž'=>1,'ï´'=>1,'ï´'=>1,'ï´‘'=>1,'ï´’'=>1,'ï´“'=>1,'ï´”'=>1,'ï´•'=>1,'ï´–'=>1,'ï´—'=>1,'ï´˜'=>1,'ï´™'=>1,'ï´š'=>1,'ï´›'=>1,'ï´œ'=>1,'ï´'=>1,'ï´ž'=>1,'ï´Ÿ'=>1,'ï´ '=>1,'ï´¡'=>1,'ï´¢'=>1,'ï´£'=>1,'ï´¤'=>1,'ï´¥'=>1,'ï´¦'=>1,'ï´§'=>1,'ï´¨'=>1,'ï´©'=>1,'ï´ª'=>1,'ï´«'=>1,'ï´¬'=>1,'ï´'=>1,'ï´®'=>1,'ï´¯'=>1,'ï´°'=>1,'ï´±'=>1,'ï´²'=>1,'ï´³'=>1,'ï´´'=>1,'ï´µ'=>1,'ï´¶'=>1,'ï´·'=>1,'ï´¸'=>1,'ï´¹'=>1,'ï´º'=>1,'ï´»'=>1,'ï´¼'=>1,'ï´½'=>1,'ïµ'=>1,'ﵑ'=>1,'ïµ’'=>1,'ﵓ'=>1,'ïµ”'=>1,'ﵕ'=>1,'ïµ–'=>1,'ïµ—'=>1,'ﵘ'=>1,'ïµ™'=>1,'ﵚ'=>1,'ïµ›'=>1,'ﵜ'=>1,'ïµ'=>1,'ﵞ'=>1,'ﵟ'=>1,'ïµ '=>1,'ﵡ'=>1,'ïµ¢'=>1,'ïµ£'=>1,'ﵤ'=>1,'ïµ¥'=>1,'ﵦ'=>1,'ïµ§'=>1,'ﵨ'=>1,'ﵩ'=>1,'ﵪ'=>1,'ﵫ'=>1,'ﵬ'=>1,'ïµ'=>1,'ïµ®'=>1,'ﵯ'=>1,'ïµ°'=>1,'ïµ±'=>1,'ïµ²'=>1,'ïµ³'=>1,'ïµ´'=>1,'ïµµ'=>1,'ïµ¶'=>1,'ïµ·'=>1,'ﵸ'=>1,'ïµ¹'=>1,'ﵺ'=>1,'ïµ»'=>1,'ïµ¼'=>1,'ïµ½'=>1,'ïµ¾'=>1,'ﵿ'=>1,'ï¶€'=>1,'ï¶'=>1,'ï¶‚'=>1,'ﶃ'=>1,'ï¶„'=>1,'ï¶…'=>1,'ﶆ'=>1,'ﶇ'=>1,'ﶈ'=>1,'ﶉ'=>1,'ï¶Š'=>1,'ï¶‹'=>1,'ï¶Œ'=>1,'ï¶'=>1,'ï¶Ž'=>1,'ï¶'=>1,'ï¶’'=>1,'ï¶“'=>1,'ï¶”'=>1,'ï¶•'=>1,'ï¶–'=>1,'ï¶—'=>1,'ﶘ'=>1,'ï¶™'=>1,'ï¶š'=>1,'ï¶›'=>1,'ï¶œ'=>1,'ï¶'=>1,'ï¶ž'=>1,'ï¶Ÿ'=>1,'ï¶ '=>1,'ï¶¡'=>1,'ï¶¢'=>1,'ï¶£'=>1,'ﶤ'=>1,'ï¶¥'=>1,'ﶦ'=>1,'ï¶§'=>1,'ﶨ'=>1,'ï¶©'=>1,'ﶪ'=>1,'ï¶«'=>1,'ﶬ'=>1,'ï¶'=>1,'ï¶®'=>1,'ﶯ'=>1,'ï¶°'=>1,'ï¶±'=>1,'ï¶²'=>1,'ï¶³'=>1,'ï¶´'=>1,'ï¶µ'=>1,'ï¶¶'=>1,'ï¶·'=>1,'ﶸ'=>1,'ï¶¹'=>1,'ﶺ'=>1,'ï¶»'=>1,'ï¶¼'=>1,'ï¶½'=>1,'ï¶¾'=>1,'ï¶¿'=>1,'ï·€'=>1,'ï·'=>1,'ï·‚'=>1,'ï·ƒ'=>1,'ï·„'=>1,'ï·…'=>1,'ï·†'=>1,'ï·‡'=>1,'ï·°'=>1,'ï·±'=>1,'ï·²'=>1,'ï·³'=>1,'ï·´'=>1,'ï·µ'=>1,'ï·¶'=>1,'ï··'=>1,'ï·¸'=>1,'ï·¹'=>1,'ï·º'=>1,'ï·»'=>1,'ï·¼'=>1,'ï¸'=>1,'︑'=>1,'︒'=>1,'︓'=>1,'︔'=>1,'︕'=>1,'︖'=>1,'︗'=>1,'︘'=>1,'︙'=>1,'︰'=>1,'︱'=>1,'︲'=>1,'︳'=>1,'︴'=>1,'︵'=>1,'︶'=>1,'︷'=>1,'︸'=>1,'︹'=>1,'︺'=>1,'︻'=>1,'︼'=>1,'︽'=>1,'︾'=>1,'︿'=>1,'ï¹€'=>1,'ï¹'=>1,'﹂'=>1,'﹃'=>1,'﹄'=>1,'﹇'=>1,'﹈'=>1,'﹉'=>1,'﹊'=>1,'﹋'=>1,'﹌'=>1,'ï¹'=>1,'﹎'=>1,'ï¹'=>1,'ï¹'=>1,'﹑'=>1,'ï¹’'=>1,'ï¹”'=>1,'﹕'=>1,'ï¹–'=>1,'ï¹—'=>1,'﹘'=>1,'ï¹™'=>1,'﹚'=>1,'ï¹›'=>1,'﹜'=>1,'ï¹'=>1,'﹞'=>1,'﹟'=>1,'ï¹ '=>1,'﹡'=>1,'ï¹¢'=>1,'ï¹£'=>1,'﹤'=>1,'ï¹¥'=>1,'﹦'=>1,'﹨'=>1,'﹩'=>1,'﹪'=>1,'﹫'=>1,'ï¹°'=>1,'ï¹±'=>1,'ï¹²'=>1,'ï¹´'=>1,'ï¹¶'=>1,'ï¹·'=>1,'ﹸ'=>1,'ï¹¹'=>1,'ﹺ'=>1,'ï¹»'=>1,'ï¹¼'=>1,'ï¹½'=>1,'ï¹¾'=>1,'ﹿ'=>1,'ﺀ'=>1,'ïº'=>1,'ﺂ'=>1,'ﺃ'=>1,'ﺄ'=>1,'ﺅ'=>1,'ﺆ'=>1,'ﺇ'=>1,'ﺈ'=>1,'ﺉ'=>1,'ﺊ'=>1,'ﺋ'=>1,'ﺌ'=>1,'ïº'=>1,'ﺎ'=>1,'ïº'=>1,'ïº'=>1,'ﺑ'=>1,'ﺒ'=>1,'ﺓ'=>1,'ﺔ'=>1,'ﺕ'=>1,'ﺖ'=>1,'ﺗ'=>1,'ﺘ'=>1,'ﺙ'=>1,'ﺚ'=>1,'ﺛ'=>1,'ﺜ'=>1,'ïº'=>1,'ﺞ'=>1,'ﺟ'=>1,'ïº '=>1,'ﺡ'=>1,'ﺢ'=>1,'ﺣ'=>1,'ﺤ'=>1,'ﺥ'=>1,'ﺦ'=>1,'ﺧ'=>1,'ﺨ'=>1,'ﺩ'=>1,'ﺪ'=>1,'ﺫ'=>1,'ﺬ'=>1,'ïº'=>1,'ﺮ'=>1,'ﺯ'=>1,'ﺰ'=>1,'ﺱ'=>1,'ﺲ'=>1,'ﺳ'=>1,'ﺴ'=>1,'ﺵ'=>1,'ﺶ'=>1,'ﺷ'=>1,'ﺸ'=>1,'ﺹ'=>1,'ﺺ'=>1,'ﺻ'=>1,'ﺼ'=>1,'ﺽ'=>1,'ﺾ'=>1,'ﺿ'=>1,'ﻀ'=>1,'ï»'=>1,'ﻂ'=>1,'ﻃ'=>1,'ﻄ'=>1,'ï»…'=>1,'ﻆ'=>1,'ﻇ'=>1,'ﻈ'=>1,'ﻉ'=>1,'ﻊ'=>1,'ﻋ'=>1,'ﻌ'=>1,'ï»'=>1,'ﻎ'=>1,'ï»'=>1,'ï»'=>1,'ﻑ'=>1,'ï»’'=>1,'ﻓ'=>1,'ï»”'=>1,'ﻕ'=>1,'ï»–'=>1,'ï»—'=>1,'ﻘ'=>1,'ï»™'=>1,'ﻚ'=>1,'ï»›'=>1,'ﻜ'=>1,'ï»'=>1,'ﻞ'=>1,'ﻟ'=>1,'ï» '=>1,'ﻡ'=>1,'ﻢ'=>1,'ﻣ'=>1,'ﻤ'=>1,'ﻥ'=>1,'ﻦ'=>1,'ï»§'=>1,'ﻨ'=>1,'ﻩ'=>1,'ﻪ'=>1,'ﻫ'=>1,'ﻬ'=>1,'ï»'=>1,'ï»®'=>1,'ﻯ'=>1,'ï»°'=>1,'ï»±'=>1,'ﻲ'=>1,'ﻳ'=>1,'ï»´'=>1,'ﻵ'=>1,'ï»¶'=>1,'ï»·'=>1,'ﻸ'=>1,'ﻹ'=>1,'ﻺ'=>1,'ï»»'=>1,'ﻼ'=>1,'ï¼'=>1,'"'=>1,'#'=>1,'$'=>1,'ï¼…'=>1,'&'=>1,'''=>1,'('=>1,')'=>1,'*'=>1,'+'=>1,','=>1,'ï¼'=>1,'.'=>1,'ï¼'=>1,'ï¼'=>1,'1'=>1,'ï¼’'=>1,'3'=>1,'ï¼”'=>1,'5'=>1,'ï¼–'=>1,'ï¼—'=>1,'8'=>1,'ï¼™'=>1,':'=>1,'ï¼›'=>1,'<'=>1,'ï¼'=>1,'>'=>1,'?'=>1,'ï¼ '=>1,'A'=>1,'ï¼¢'=>1,'ï¼£'=>1,'D'=>1,'ï¼¥'=>1,'F'=>1,'ï¼§'=>1,'H'=>1,'I'=>1,'J'=>1,'K'=>1,'L'=>1,'ï¼'=>1,'ï¼®'=>1,'O'=>1,'ï¼°'=>1,'ï¼±'=>1,'ï¼²'=>1,'ï¼³'=>1,'ï¼´'=>1,'ï¼µ'=>1,'ï¼¶'=>1,'ï¼·'=>1,'X'=>1,'ï¼¹'=>1,'Z'=>1,'ï¼»'=>1,'ï¼¼'=>1,'ï¼½'=>1,'ï¼¾'=>1,'_'=>1,'ï½€'=>1,'ï½'=>1,'b'=>1,'c'=>1,'d'=>1,'ï½…'=>1,'f'=>1,'g'=>1,'h'=>1,'i'=>1,'j'=>1,'k'=>1,'l'=>1,'ï½'=>1,'n'=>1,'ï½'=>1,'ï½'=>1,'q'=>1,'ï½’'=>1,'s'=>1,'ï½”'=>1,'u'=>1,'ï½–'=>1,'ï½—'=>1,'x'=>1,'ï½™'=>1,'z'=>1,'ï½›'=>1,'|'=>1,'ï½'=>1,'~'=>1,'⦅'=>1,'ï½ '=>1,'。'=>1,'ï½¢'=>1,'ï½£'=>1,'、'=>1,'ï½¥'=>1,'ヲ'=>1,'ï½§'=>1,'ィ'=>1,'ゥ'=>1,'ェ'=>1,'ォ'=>1,'ャ'=>1,'ï½'=>1,'ï½®'=>1,'ッ'=>1,'ï½°'=>1,'ï½±'=>1,'ï½²'=>1,'ï½³'=>1,'ï½´'=>1,'ï½µ'=>1,'ï½¶'=>1,'ï½·'=>1,'ク'=>1,'ï½¹'=>1,'コ'=>1,'ï½»'=>1,'ï½¼'=>1,'ï½½'=>1,'ï½¾'=>1,'ソ'=>1,'ï¾€'=>1,'ï¾'=>1,'ツ'=>1,'テ'=>1,'ト'=>1,'ï¾…'=>1,'ニ'=>1,'ヌ'=>1,'ネ'=>1,'ノ'=>1,'ハ'=>1,'ヒ'=>1,'フ'=>1,'ï¾'=>1,'ホ'=>1,'ï¾'=>1,'ï¾'=>1,'ム'=>1,'ï¾’'=>1,'モ'=>1,'ï¾”'=>1,'ユ'=>1,'ï¾–'=>1,'ï¾—'=>1,'リ'=>1,'ï¾™'=>1,'レ'=>1,'ï¾›'=>1,'ワ'=>1,'ï¾'=>1,'゙'=>1,'゚'=>1,'ï¾ '=>1,'ᄀ'=>1,'ï¾¢'=>1,'ï¾£'=>1,'ᄂ'=>1,'ï¾¥'=>1,'ᆭ'=>1,'ï¾§'=>1,'ᄄ'=>1,'ᄅ'=>1,'ᆰ'=>1,'ᆱ'=>1,'ᆲ'=>1,'ï¾'=>1,'ï¾®'=>1,'ᆵ'=>1,'ï¾°'=>1,'ï¾±'=>1,'ï¾²'=>1,'ï¾³'=>1,'ï¾´'=>1,'ï¾µ'=>1,'ï¾¶'=>1,'ï¾·'=>1,'ᄌ'=>1,'ï¾¹'=>1,'ᄎ'=>1,'ï¾»'=>1,'ï¾¼'=>1,'ï¾½'=>1,'ï¾¾'=>1,'ï¿‚'=>1,'ᅢ'=>1,'ï¿„'=>1,'ï¿…'=>1,'ᅥ'=>1,'ᅦ'=>1,'ᅧ'=>1,'ï¿‹'=>1,'ᅩ'=>1,'ï¿'=>1,'ᅫ'=>1,'ï¿'=>1,'ï¿’'=>1,'ï¿“'=>1,'ï¿”'=>1,'ï¿•'=>1,'ï¿–'=>1,'ï¿—'=>1,'ᅳ'=>1,'ï¿›'=>1,'ᅵ'=>1,'ï¿ '=>1,'ï¿¡'=>1,'ï¿¢'=>1,'ï¿£'=>1,'¦'=>1,'ï¿¥'=>1,'₩'=>1,'│'=>1,'ï¿©'=>1,'↑'=>1,'ï¿«'=>1,'↓'=>1,'ï¿'=>1,'ï¿®'=>1,'ð…ž'=>1,'ð…Ÿ'=>1,'ð… '=>1,'ð…¡'=>1,'ð…¢'=>1,'ð…£'=>1,'ð…¤'=>1,'ð†»'=>1,'ð†¼'=>1,'ð†½'=>1,'ð†¾'=>1,'ð†¿'=>1,'ð‡€'=>1,'ð€'=>1,'ð'=>1,'ð‚'=>1,'ðƒ'=>1,'ð„'=>1,'ð…'=>1,'ð†'=>1,'ð‡'=>1,'ðˆ'=>1,'ð‰'=>1,'ðŠ'=>1,'ð‹'=>1,'ðŒ'=>1,'ð'=>1,'ðŽ'=>1,'ð'=>1,'ð'=>1,'ð‘'=>1,'ð’'=>1,'ð“'=>1,'ð”'=>1,'ð•'=>1,'ð–'=>1,'ð—'=>1,'ð˜'=>1,'ð™'=>1,'ðš'=>1,'ð›'=>1,'ðœ'=>1,'ð'=>1,'ðž'=>1,'ðŸ'=>1,'ð '=>1,'ð¡'=>1,'ð¢'=>1,'ð£'=>1,'ð¤'=>1,'ð¥'=>1,'ð¦'=>1,'ð§'=>1,'ð¨'=>1,'ð©'=>1,'ðª'=>1,'ð«'=>1,'ð¬'=>1,'ð'=>1,'ð®'=>1,'ð¯'=>1,'ð°'=>1,'ð±'=>1,'ð²'=>1,'ð³'=>1,'ð´'=>1,'ðµ'=>1,'ð¶'=>1,'ð·'=>1,'ð¸'=>1,'ð¹'=>1,'ðº'=>1,'ð»'=>1,'ð¼'=>1,'ð½'=>1,'ð¾'=>1,'ð¿'=>1,'ð‘€'=>1,'ð‘'=>1,'ð‘‚'=>1,'ð‘ƒ'=>1,'ð‘„'=>1,'ð‘…'=>1,'ð‘†'=>1,'ð‘‡'=>1,'ð‘ˆ'=>1,'ð‘‰'=>1,'ð‘Š'=>1,'ð‘‹'=>1,'ð‘Œ'=>1,'ð‘'=>1,'ð‘Ž'=>1,'ð‘'=>1,'ð‘'=>1,'ð‘‘'=>1,'ð‘’'=>1,'ð‘“'=>1,'ð‘”'=>1,'ð‘–'=>1,'ð‘—'=>1,'ð‘˜'=>1,'ð‘™'=>1,'ð‘š'=>1,'ð‘›'=>1,'ð‘œ'=>1,'ð‘'=>1,'ð‘ž'=>1,'ð‘Ÿ'=>1,'ð‘ '=>1,'ð‘¡'=>1,'ð‘¢'=>1,'ð‘£'=>1,'ð‘¤'=>1,'ð‘¥'=>1,'ð‘¦'=>1,'ð‘§'=>1,'ð‘¨'=>1,'ð‘©'=>1,'ð‘ª'=>1,'ð‘«'=>1,'ð‘¬'=>1,'ð‘'=>1,'ð‘®'=>1,'ð‘¯'=>1,'ð‘°'=>1,'ð‘±'=>1,'ð‘²'=>1,'ð‘³'=>1,'ð‘´'=>1,'ð‘µ'=>1,'ð‘¶'=>1,'ð‘·'=>1,'ð‘¸'=>1,'ð‘¹'=>1,'ð‘º'=>1,'ð‘»'=>1,'ð‘¼'=>1,'ð‘½'=>1,'ð‘¾'=>1,'ð‘¿'=>1,'ð’€'=>1,'ð’'=>1,'ð’‚'=>1,'ð’ƒ'=>1,'ð’„'=>1,'ð’…'=>1,'ð’†'=>1,'ð’‡'=>1,'ð’ˆ'=>1,'ð’‰'=>1,'ð’Š'=>1,'ð’‹'=>1,'ð’Œ'=>1,'ð’'=>1,'ð’Ž'=>1,'ð’'=>1,'ð’'=>1,'ð’‘'=>1,'ð’’'=>1,'ð’“'=>1,'ð’”'=>1,'ð’•'=>1,'ð’–'=>1,'ð’—'=>1,'ð’˜'=>1,'ð’™'=>1,'ð’š'=>1,'ð’›'=>1,'ð’œ'=>1,'ð’ž'=>1,'ð’Ÿ'=>1,'ð’¢'=>1,'ð’¥'=>1,'ð’¦'=>1,'ð’©'=>1,'ð’ª'=>1,'ð’«'=>1,'ð’¬'=>1,'ð’®'=>1,'ð’¯'=>1,'ð’°'=>1,'ð’±'=>1,'ð’²'=>1,'ð’³'=>1,'ð’´'=>1,'ð’µ'=>1,'ð’¶'=>1,'ð’·'=>1,'ð’¸'=>1,'ð’¹'=>1,'ð’»'=>1,'ð’½'=>1,'ð’¾'=>1,'ð’¿'=>1,'ð“€'=>1,'ð“'=>1,'ð“‚'=>1,'ð“ƒ'=>1,'ð“…'=>1,'ð“†'=>1,'ð“‡'=>1,'ð“ˆ'=>1,'ð“‰'=>1,'ð“Š'=>1,'ð“‹'=>1,'ð“Œ'=>1,'ð“'=>1,'ð“Ž'=>1,'ð“'=>1,'ð“'=>1,'ð“‘'=>1,'ð“’'=>1,'ð““'=>1,'ð“”'=>1,'ð“•'=>1,'ð“–'=>1,'ð“—'=>1,'ð“˜'=>1,'ð“™'=>1,'ð“š'=>1,'ð“›'=>1,'ð“œ'=>1,'ð“'=>1,'ð“ž'=>1,'ð“Ÿ'=>1,'ð“ '=>1,'ð“¡'=>1,'ð“¢'=>1,'ð“£'=>1,'ð“¤'=>1,'ð“¥'=>1,'ð“¦'=>1,'ð“§'=>1,'ð“¨'=>1,'ð“©'=>1,'ð“ª'=>1,'ð“«'=>1,'ð“¬'=>1,'ð“'=>1,'ð“®'=>1,'ð“¯'=>1,'ð“°'=>1,'ð“±'=>1,'ð“²'=>1,'ð“³'=>1,'ð“´'=>1,'ð“µ'=>1,'ð“¶'=>1,'ð“·'=>1,'ð“¸'=>1,'ð“¹'=>1,'ð“º'=>1,'ð“»'=>1,'ð“¼'=>1,'ð“½'=>1,'ð“¾'=>1,'ð“¿'=>1,'ð”€'=>1,'ð”'=>1,'ð”‚'=>1,'ð”ƒ'=>1,'ð”„'=>1,'ð”…'=>1,'ð”‡'=>1,'ð”ˆ'=>1,'ð”‰'=>1,'ð”Š'=>1,'ð”'=>1,'ð”Ž'=>1,'ð”'=>1,'ð”'=>1,'ð”‘'=>1,'ð”’'=>1,'ð”“'=>1,'ð””'=>1,'ð”–'=>1,'ð”—'=>1,'ð”˜'=>1,'ð”™'=>1,'ð”š'=>1,'ð”›'=>1,'ð”œ'=>1,'ð”ž'=>1,'ð”Ÿ'=>1,'ð” '=>1,'ð”¡'=>1,'ð”¢'=>1,'ð”£'=>1,'ð”¤'=>1,'ð”¥'=>1,'ð”¦'=>1,'ð”§'=>1,'ð”¨'=>1,'ð”©'=>1,'ð”ª'=>1,'ð”«'=>1,'ð”¬'=>1,'ð”'=>1,'ð”®'=>1,'ð”¯'=>1,'ð”°'=>1,'ð”±'=>1,'ð”²'=>1,'ð”³'=>1,'ð”´'=>1,'ð”µ'=>1,'ð”¶'=>1,'ð”·'=>1,'ð”¸'=>1,'ð”¹'=>1,'ð”»'=>1,'ð”¼'=>1,'ð”½'=>1,'ð”¾'=>1,'ð•€'=>1,'ð•'=>1,'ð•‚'=>1,'ð•ƒ'=>1,'ð•„'=>1,'ð•†'=>1,'ð•Š'=>1,'ð•‹'=>1,'ð•Œ'=>1,'ð•'=>1,'ð•Ž'=>1,'ð•'=>1,'ð•'=>1,'ð•’'=>1,'ð•“'=>1,'ð•”'=>1,'ð••'=>1,'ð•–'=>1,'ð•—'=>1,'ð•˜'=>1,'ð•™'=>1,'ð•š'=>1,'ð•›'=>1,'ð•œ'=>1,'ð•'=>1,'ð•ž'=>1,'ð•Ÿ'=>1,'ð• '=>1,'ð•¡'=>1,'ð•¢'=>1,'ð•£'=>1,'ð•¤'=>1,'ð•¥'=>1,'ð•¦'=>1,'ð•§'=>1,'ð•¨'=>1,'ð•©'=>1,'ð•ª'=>1,'ð•«'=>1,'ð•¬'=>1,'ð•'=>1,'ð•®'=>1,'ð•¯'=>1,'ð•°'=>1,'ð•±'=>1,'ð•²'=>1,'ð•³'=>1,'ð•´'=>1,'ð•µ'=>1,'ð•¶'=>1,'ð•·'=>1,'ð•¸'=>1,'ð•¹'=>1,'ð•º'=>1,'ð•»'=>1,'ð•¼'=>1,'ð•½'=>1,'ð•¾'=>1,'ð•¿'=>1,'ð–€'=>1,'ð–'=>1,'ð–‚'=>1,'ð–ƒ'=>1,'ð–„'=>1,'ð–…'=>1,'ð–†'=>1,'ð–‡'=>1,'ð–ˆ'=>1,'ð–‰'=>1,'ð–Š'=>1,'ð–‹'=>1,'ð–Œ'=>1,'ð–'=>1,'ð–Ž'=>1,'ð–'=>1,'ð–'=>1,'ð–‘'=>1,'ð–’'=>1,'ð–“'=>1,'ð–”'=>1,'ð–•'=>1,'ð––'=>1,'ð–—'=>1,'ð–˜'=>1,'ð–™'=>1,'ð–š'=>1,'ð–›'=>1,'ð–œ'=>1,'ð–'=>1,'ð–ž'=>1,'ð–Ÿ'=>1,'ð– '=>1,'ð–¡'=>1,'ð–¢'=>1,'ð–£'=>1,'ð–¤'=>1,'ð–¥'=>1,'ð–¦'=>1,'ð–§'=>1,'ð–¨'=>1,'ð–©'=>1,'ð–ª'=>1,'ð–«'=>1,'ð–¬'=>1,'ð–'=>1,'ð–®'=>1,'ð–¯'=>1,'ð–°'=>1,'ð–±'=>1,'ð–²'=>1,'ð–³'=>1,'ð–´'=>1,'ð–µ'=>1,'ð–¶'=>1,'ð–·'=>1,'ð–¸'=>1,'ð–¹'=>1,'ð–º'=>1,'ð–»'=>1,'ð–¼'=>1,'ð–½'=>1,'ð–¾'=>1,'ð–¿'=>1,'ð—€'=>1,'ð—'=>1,'ð—‚'=>1,'ð—ƒ'=>1,'ð—„'=>1,'ð—…'=>1,'ð—†'=>1,'ð—‡'=>1,'ð—ˆ'=>1,'ð—‰'=>1,'ð—Š'=>1,'ð—‹'=>1,'ð—Œ'=>1,'ð—'=>1,'ð—Ž'=>1,'ð—'=>1,'ð—'=>1,'ð—‘'=>1,'ð—’'=>1,'ð—“'=>1,'ð—”'=>1,'ð—•'=>1,'ð—–'=>1,'ð——'=>1,'ð—˜'=>1,'ð—™'=>1,'ð—š'=>1,'ð—›'=>1,'ð—œ'=>1,'ð—'=>1,'ð—ž'=>1,'ð—Ÿ'=>1,'ð— '=>1,'ð—¡'=>1,'ð—¢'=>1,'ð—£'=>1,'ð—¤'=>1,'ð—¥'=>1,'ð—¦'=>1,'ð—§'=>1,'ð—¨'=>1,'ð—©'=>1,'ð—ª'=>1,'ð—«'=>1,'ð—¬'=>1,'ð—'=>1,'ð—®'=>1,'ð—¯'=>1,'ð—°'=>1,'ð—±'=>1,'ð—²'=>1,'ð—³'=>1,'ð—´'=>1,'ð—µ'=>1,'ð—¶'=>1,'ð—·'=>1,'ð—¸'=>1,'ð—¹'=>1,'ð—º'=>1,'ð—»'=>1,'ð—¼'=>1,'ð—½'=>1,'ð—¾'=>1,'ð—¿'=>1,'ð˜€'=>1,'ð˜'=>1,'ð˜‚'=>1,'ð˜ƒ'=>1,'ð˜„'=>1,'ð˜…'=>1,'ð˜†'=>1,'ð˜‡'=>1,'ð˜ˆ'=>1,'ð˜‰'=>1,'ð˜Š'=>1,'ð˜‹'=>1,'ð˜Œ'=>1,'ð˜'=>1,'ð˜Ž'=>1,'ð˜'=>1,'ð˜'=>1,'ð˜‘'=>1,'ð˜’'=>1,'ð˜“'=>1,'ð˜”'=>1,'ð˜•'=>1,'ð˜–'=>1,'ð˜—'=>1,'ð˜˜'=>1,'ð˜™'=>1,'ð˜š'=>1,'ð˜›'=>1,'ð˜œ'=>1,'ð˜'=>1,'ð˜ž'=>1,'ð˜Ÿ'=>1,'ð˜ '=>1,'ð˜¡'=>1,'ð˜¢'=>1,'ð˜£'=>1,'ð˜¤'=>1,'ð˜¥'=>1,'ð˜¦'=>1,'ð˜§'=>1,'ð˜¨'=>1,'ð˜©'=>1,'ð˜ª'=>1,'ð˜«'=>1,'ð˜¬'=>1,'ð˜'=>1,'ð˜®'=>1,'ð˜¯'=>1,'ð˜°'=>1,'ð˜±'=>1,'ð˜²'=>1,'ð˜³'=>1,'ð˜´'=>1,'ð˜µ'=>1,'ð˜¶'=>1,'ð˜·'=>1,'ð˜¸'=>1,'ð˜¹'=>1,'ð˜º'=>1,'ð˜»'=>1,'ð˜¼'=>1,'ð˜½'=>1,'ð˜¾'=>1,'ð˜¿'=>1,'ð™€'=>1,'ð™'=>1,'ð™‚'=>1,'ð™ƒ'=>1,'ð™„'=>1,'ð™…'=>1,'ð™†'=>1,'ð™‡'=>1,'ð™ˆ'=>1,'ð™‰'=>1,'ð™Š'=>1,'ð™‹'=>1,'ð™Œ'=>1,'ð™'=>1,'ð™Ž'=>1,'ð™'=>1,'ð™'=>1,'ð™‘'=>1,'ð™’'=>1,'ð™“'=>1,'ð™”'=>1,'ð™•'=>1,'ð™–'=>1,'ð™—'=>1,'ð™˜'=>1,'ð™™'=>1,'ð™š'=>1,'ð™›'=>1,'ð™œ'=>1,'ð™'=>1,'ð™ž'=>1,'ð™Ÿ'=>1,'ð™ '=>1,'ð™¡'=>1,'ð™¢'=>1,'ð™£'=>1,'ð™¤'=>1,'ð™¥'=>1,'ð™¦'=>1,'ð™§'=>1,'ð™¨'=>1,'ð™©'=>1,'ð™ª'=>1,'ð™«'=>1,'ð™¬'=>1,'ð™'=>1,'ð™®'=>1,'ð™¯'=>1,'ð™°'=>1,'ð™±'=>1,'ð™²'=>1,'ð™³'=>1,'ð™´'=>1,'ð™µ'=>1,'ð™¶'=>1,'ð™·'=>1,'ð™¸'=>1,'ð™¹'=>1,'ð™º'=>1,'ð™»'=>1,'ð™¼'=>1,'ð™½'=>1,'ð™¾'=>1,'ð™¿'=>1,'ðš€'=>1,'ðš'=>1,'ðš‚'=>1,'ðšƒ'=>1,'ðš„'=>1,'ðš…'=>1,'ðš†'=>1,'ðš‡'=>1,'ðšˆ'=>1,'ðš‰'=>1,'ðšŠ'=>1,'ðš‹'=>1,'ðšŒ'=>1,'ðš'=>1,'ðšŽ'=>1,'ðš'=>1,'ðš'=>1,'ðš‘'=>1,'ðš’'=>1,'ðš“'=>1,'ðš”'=>1,'ðš•'=>1,'ðš–'=>1,'ðš—'=>1,'ðš˜'=>1,'ðš™'=>1,'ðšš'=>1,'ðš›'=>1,'ðšœ'=>1,'ðš'=>1,'ðšž'=>1,'ðšŸ'=>1,'ðš '=>1,'ðš¡'=>1,'ðš¢'=>1,'ðš£'=>1,'ðš¤'=>1,'ðš¥'=>1,'ðš¨'=>1,'ðš©'=>1,'ðšª'=>1,'ðš«'=>1,'ðš¬'=>1,'ðš'=>1,'ðš®'=>1,'ðš¯'=>1,'ðš°'=>1,'ðš±'=>1,'ðš²'=>1,'ðš³'=>1,'ðš´'=>1,'ðšµ'=>1,'ðš¶'=>1,'ðš·'=>1,'ðš¸'=>1,'ðš¹'=>1,'ðšº'=>1,'ðš»'=>1,'ðš¼'=>1,'ðš½'=>1,'ðš¾'=>1,'ðš¿'=>1,'ð›€'=>1,'ð›'=>1,'ð›‚'=>1,'ð›ƒ'=>1,'ð›„'=>1,'ð›…'=>1,'ð›†'=>1,'ð›‡'=>1,'ð›ˆ'=>1,'ð›‰'=>1,'ð›Š'=>1,'ð›‹'=>1,'ð›Œ'=>1,'ð›'=>1,'ð›Ž'=>1,'ð›'=>1,'ð›'=>1,'ð›‘'=>1,'ð›’'=>1,'ð›“'=>1,'ð›”'=>1,'ð›•'=>1,'ð›–'=>1,'ð›—'=>1,'ð›˜'=>1,'ð›™'=>1,'ð›š'=>1,'ð››'=>1,'ð›œ'=>1,'ð›'=>1,'ð›ž'=>1,'ð›Ÿ'=>1,'ð› '=>1,'ð›¡'=>1,'ð›¢'=>1,'ð›£'=>1,'ð›¤'=>1,'ð›¥'=>1,'ð›¦'=>1,'ð›§'=>1,'ð›¨'=>1,'ð›©'=>1,'ð›ª'=>1,'ð›«'=>1,'ð›¬'=>1,'ð›'=>1,'ð›®'=>1,'ð›¯'=>1,'ð›°'=>1,'ð›±'=>1,'ð›²'=>1,'ð›³'=>1,'ð›´'=>1,'ð›µ'=>1,'ð›¶'=>1,'ð›·'=>1,'ð›¸'=>1,'ð›¹'=>1,'ð›º'=>1,'ð›»'=>1,'ð›¼'=>1,'ð›½'=>1,'ð›¾'=>1,'ð›¿'=>1,'ðœ€'=>1,'ðœ'=>1,'ðœ‚'=>1,'ðœƒ'=>1,'ðœ„'=>1,'ðœ…'=>1,'ðœ†'=>1,'ðœ‡'=>1,'ðœˆ'=>1,'ðœ‰'=>1,'ðœŠ'=>1,'ðœ‹'=>1,'ðœŒ'=>1,'ðœ'=>1,'ðœŽ'=>1,'ðœ'=>1,'ðœ'=>1,'ðœ‘'=>1,'ðœ’'=>1,'ðœ“'=>1,'ðœ”'=>1,'ðœ•'=>1,'ðœ–'=>1,'ðœ—'=>1,'ðœ˜'=>1,'ðœ™'=>1,'ðœš'=>1,'ðœ›'=>1,'ðœœ'=>1,'ðœ'=>1,'ðœž'=>1,'ðœŸ'=>1,'ðœ '=>1,'ðœ¡'=>1,'ðœ¢'=>1,'ðœ£'=>1,'ðœ¤'=>1,'ðœ¥'=>1,'ðœ¦'=>1,'ðœ§'=>1,'ðœ¨'=>1,'ðœ©'=>1,'ðœª'=>1,'ðœ«'=>1,'ðœ¬'=>1,'ðœ'=>1,'ðœ®'=>1,'ðœ¯'=>1,'ðœ°'=>1,'ðœ±'=>1,'ðœ²'=>1,'ðœ³'=>1,'ðœ´'=>1,'ðœµ'=>1,'ðœ¶'=>1,'ðœ·'=>1,'ðœ¸'=>1,'ðœ¹'=>1,'ðœº'=>1,'ðœ»'=>1,'ðœ¼'=>1,'ðœ½'=>1,'ðœ¾'=>1,'ðœ¿'=>1,'ð€'=>1,'ð'=>1,'ð‚'=>1,'ðƒ'=>1,'ð„'=>1,'ð…'=>1,'ð†'=>1,'ð‡'=>1,'ðˆ'=>1,'ð‰'=>1,'ðŠ'=>1,'ð‹'=>1,'ðŒ'=>1,'ð'=>1,'ðŽ'=>1,'ð'=>1,'ð'=>1,'ð‘'=>1,'ð’'=>1,'ð“'=>1,'ð”'=>1,'ð•'=>1,'ð–'=>1,'ð—'=>1,'ð˜'=>1,'ð™'=>1,'ðš'=>1,'ð›'=>1,'ðœ'=>1,'ð'=>1,'ðž'=>1,'ðŸ'=>1,'ð '=>1,'ð¡'=>1,'ð¢'=>1,'ð£'=>1,'ð¤'=>1,'ð¥'=>1,'ð¦'=>1,'ð§'=>1,'ð¨'=>1,'ð©'=>1,'ðª'=>1,'ð«'=>1,'ð¬'=>1,'ð'=>1,'ð®'=>1,'ð¯'=>1,'ð°'=>1,'ð±'=>1,'ð²'=>1,'ð³'=>1,'ð´'=>1,'ðµ'=>1,'ð¶'=>1,'ð·'=>1,'ð¸'=>1,'ð¹'=>1,'ðº'=>1,'ð»'=>1,'ð¼'=>1,'ð½'=>1,'ð¾'=>1,'ð¿'=>1,'ðž€'=>1,'ðž'=>1,'ðž‚'=>1,'ðžƒ'=>1,'ðž„'=>1,'ðž…'=>1,'ðž†'=>1,'ðž‡'=>1,'ðžˆ'=>1,'ðž‰'=>1,'ðžŠ'=>1,'ðž‹'=>1,'ðžŒ'=>1,'ðž'=>1,'ðžŽ'=>1,'ðž'=>1,'ðž'=>1,'ðž‘'=>1,'ðž’'=>1,'ðž“'=>1,'ðž”'=>1,'ðž•'=>1,'ðž–'=>1,'ðž—'=>1,'ðž˜'=>1,'ðž™'=>1,'ðžš'=>1,'ðž›'=>1,'ðžœ'=>1,'ðž'=>1,'ðžž'=>1,'ðžŸ'=>1,'ðž '=>1,'ðž¡'=>1,'ðž¢'=>1,'ðž£'=>1,'ðž¤'=>1,'ðž¥'=>1,'ðž¦'=>1,'ðž§'=>1,'ðž¨'=>1,'ðž©'=>1,'ðžª'=>1,'ðž«'=>1,'ðž¬'=>1,'ðž'=>1,'ðž®'=>1,'ðž¯'=>1,'ðž°'=>1,'ðž±'=>1,'ðž²'=>1,'ðž³'=>1,'ðž´'=>1,'ðžµ'=>1,'ðž¶'=>1,'ðž·'=>1,'ðž¸'=>1,'ðž¹'=>1,'ðžº'=>1,'ðž»'=>1,'ðž¼'=>1,'ðž½'=>1,'ðž¾'=>1,'ðž¿'=>1,'ðŸ€'=>1,'ðŸ'=>1,'ðŸ‚'=>1,'ðŸƒ'=>1,'ðŸ„'=>1,'ðŸ…'=>1,'ðŸ†'=>1,'ðŸ‡'=>1,'ðŸˆ'=>1,'ðŸ‰'=>1,'ðŸŠ'=>1,'ðŸ‹'=>1,'ðŸŽ'=>1,'ðŸ'=>1,'ðŸ'=>1,'ðŸ‘'=>1,'ðŸ’'=>1,'ðŸ“'=>1,'ðŸ”'=>1,'ðŸ•'=>1,'ðŸ–'=>1,'ðŸ—'=>1,'ðŸ˜'=>1,'ðŸ™'=>1,'ðŸš'=>1,'ðŸ›'=>1,'ðŸœ'=>1,'ðŸ'=>1,'ðŸž'=>1,'ðŸŸ'=>1,'ðŸ '=>1,'ðŸ¡'=>1,'ðŸ¢'=>1,'ðŸ£'=>1,'ðŸ¤'=>1,'ðŸ¥'=>1,'ðŸ¦'=>1,'ðŸ§'=>1,'ðŸ¨'=>1,'ðŸ©'=>1,'ðŸª'=>1,'ðŸ«'=>1,'ðŸ¬'=>1,'ðŸ'=>1,'ðŸ®'=>1,'ðŸ¯'=>1,'ðŸ°'=>1,'ðŸ±'=>1,'ðŸ²'=>1,'ðŸ³'=>1,'ðŸ´'=>1,'ðŸµ'=>1,'ðŸ¶'=>1,'ðŸ·'=>1,'ðŸ¸'=>1,'ðŸ¹'=>1,'ðŸº'=>1,'ðŸ»'=>1,'ðŸ¼'=>1,'ðŸ½'=>1,'ðŸ¾'=>1,'ðŸ¿'=>1,'丽'=>1,'ð¯ '=>1,'乁'=>1,'𠄢'=>1,'你'=>1,'侮'=>1,'侻'=>1,'倂'=>1,'偺'=>1,'備'=>1,'僧'=>1,'像'=>1,'㒞'=>1,'ð¯ '=>1,'免'=>1,'ð¯ '=>1,'ð¯ '=>1,'具'=>1,'𠔜'=>1,'㒹'=>1,'內'=>1,'再'=>1,'𠕋'=>1,'冗'=>1,'冤'=>1,'仌'=>1,'冬'=>1,'况'=>1,'𩇟'=>1,'ð¯ '=>1,'刃'=>1,'㓟'=>1,'ð¯ '=>1,'剆'=>1,'割'=>1,'剷'=>1,'㔕'=>1,'勇'=>1,'勉'=>1,'勤'=>1,'勺'=>1,'包'=>1,'匆'=>1,'北'=>1,'卉'=>1,'ð¯ '=>1,'博'=>1,'即'=>1,'卽'=>1,'卿'=>1,'卿'=>1,'卿'=>1,'𠨬'=>1,'灰'=>1,'及'=>1,'叟'=>1,'𠭣'=>1,'叫'=>1,'叱'=>1,'吆'=>1,'咞'=>1,'吸'=>1,'呈'=>1,'周'=>1,'咢'=>1,'ð¯¡'=>1,'唐'=>1,'啓'=>1,'啣'=>1,'善'=>1,'善'=>1,'喙'=>1,'喫'=>1,'喳'=>1,'嗂'=>1,'圖'=>1,'嘆'=>1,'ð¯¡'=>1,'噑'=>1,'ð¯¡'=>1,'ð¯¡'=>1,'壮'=>1,'城'=>1,'埴'=>1,'堍'=>1,'型'=>1,'堲'=>1,'報'=>1,'墬'=>1,'𡓤'=>1,'売'=>1,'壷'=>1,'夆'=>1,'ð¯¡'=>1,'夢'=>1,'奢'=>1,'𡚨'=>1,'𡛪'=>1,'姬'=>1,'娛'=>1,'娧'=>1,'姘'=>1,'婦'=>1,'㛮'=>1,'㛼'=>1,'嬈'=>1,'嬾'=>1,'嬾'=>1,'𡧈'=>1,'ð¯¡'=>1,'寘'=>1,'寧'=>1,'寳'=>1,'𡬘'=>1,'寿'=>1,'将'=>1,'当'=>1,'尢'=>1,'㞁'=>1,'屠'=>1,'屮'=>1,'峀'=>1,'岍'=>1,'𡷤'=>1,'嵃'=>1,'𡷦'=>1,'嵮'=>1,'嵫'=>1,'嵼'=>1,'ð¯¢'=>1,'巢'=>1,'㠯'=>1,'巽'=>1,'帨'=>1,'帽'=>1,'幩'=>1,'㡢'=>1,'𢆃'=>1,'㡼'=>1,'庰'=>1,'庳'=>1,'ð¯¢'=>1,'廊'=>1,'ð¯¢'=>1,'ð¯¢'=>1,'𢌱'=>1,'𢌱'=>1,'舁'=>1,'弢'=>1,'弢'=>1,'㣇'=>1,'𣊸'=>1,'𦇚'=>1,'形'=>1,'彫'=>1,'㣣'=>1,'徚'=>1,'ð¯¢'=>1,'志'=>1,'忹'=>1,'悁'=>1,'㤺'=>1,'㤜'=>1,'悔'=>1,'𢛔'=>1,'惇'=>1,'慈'=>1,'慌'=>1,'慎'=>1,'慌'=>1,'慺'=>1,'憎'=>1,'憲'=>1,'ð¯¢'=>1,'憯'=>1,'懞'=>1,'懲'=>1,'懶'=>1,'成'=>1,'戛'=>1,'扝'=>1,'抱'=>1,'拔'=>1,'捐'=>1,'𢬌'=>1,'挽'=>1,'拼'=>1,'捨'=>1,'掃'=>1,'揤'=>1,'𢯱'=>1,'搢'=>1,'揅'=>1,'ð¯£'=>1,'㨮'=>1,'摩'=>1,'摾'=>1,'撝'=>1,'摷'=>1,'㩬'=>1,'敏'=>1,'敬'=>1,'𣀊'=>1,'旣'=>1,'書'=>1,'ð¯£'=>1,'㬙'=>1,'ð¯£'=>1,'ð¯£'=>1,'㫤'=>1,'冒'=>1,'冕'=>1,'最'=>1,'暜'=>1,'肭'=>1,'䏙'=>1,'朗'=>1,'望'=>1,'朡'=>1,'杞'=>1,'杓'=>1,'ð¯£'=>1,'㭉'=>1,'柺'=>1,'枅'=>1,'桒'=>1,'梅'=>1,'𣑭'=>1,'梎'=>1,'栟'=>1,'椔'=>1,'㮝'=>1,'楂'=>1,'榣'=>1,'槪'=>1,'檨'=>1,'𣚣'=>1,'ð¯£'=>1,'㰘'=>1,'次'=>1,'𣢧'=>1,'歔'=>1,'㱎'=>1,'歲'=>1,'殟'=>1,'殺'=>1,'殻'=>1,'𣪍'=>1,'𡴋'=>1,'𣫺'=>1,'汎'=>1,'𣲼'=>1,'沿'=>1,'泍'=>1,'汧'=>1,'洖'=>1,'派'=>1,'ð¯¤'=>1,'流'=>1,'浩'=>1,'浸'=>1,'涅'=>1,'𣴞'=>1,'洴'=>1,'港'=>1,'湮'=>1,'㴳'=>1,'滋'=>1,'滇'=>1,'ð¯¤'=>1,'淹'=>1,'ð¯¤'=>1,'ð¯¤'=>1,'𣾎'=>1,'濆'=>1,'瀹'=>1,'瀞'=>1,'瀛'=>1,'㶖'=>1,'灊'=>1,'災'=>1,'灷'=>1,'炭'=>1,'𠔥'=>1,'煅'=>1,'ð¯¤'=>1,'熜'=>1,'𤎫'=>1,'爨'=>1,'爵'=>1,'牐'=>1,'𤘈'=>1,'犀'=>1,'犕'=>1,'𤜵'=>1,'𤠔'=>1,'獺'=>1,'王'=>1,'㺬'=>1,'玥'=>1,'㺸'=>1,'ð¯¤'=>1,'瑇'=>1,'瑜'=>1,'瑱'=>1,'璅'=>1,'瓊'=>1,'㼛'=>1,'甤'=>1,'𤰶'=>1,'甾'=>1,'𤲒'=>1,'異'=>1,'𢆟'=>1,'瘐'=>1,'𤾡'=>1,'𤾸'=>1,'𥁄'=>1,'㿼'=>1,'䀈'=>1,'直'=>1,'ð¯¥'=>1,'𥃲'=>1,'𥄙'=>1,'𥄳'=>1,'眞'=>1,'真'=>1,'真'=>1,'睊'=>1,'䀹'=>1,'瞋'=>1,'䁆'=>1,'䂖'=>1,'ð¯¥'=>1,'硎'=>1,'ð¯¥'=>1,'ð¯¥'=>1,'䃣'=>1,'𥘦'=>1,'祖'=>1,'𥚚'=>1,'𥛅'=>1,'福'=>1,'秫'=>1,'䄯'=>1,'穀'=>1,'穊'=>1,'穏'=>1,'𥥼'=>1,'ð¯¥'=>1,'𥪧'=>1,'竮'=>1,'䈂'=>1,'𥮫'=>1,'篆'=>1,'築'=>1,'䈧'=>1,'𥲀'=>1,'糒'=>1,'䊠'=>1,'糨'=>1,'糣'=>1,'紀'=>1,'𥾆'=>1,'絣'=>1,'ð¯¥'=>1,'緇'=>1,'縂'=>1,'繅'=>1,'䌴'=>1,'𦈨'=>1,'𦉇'=>1,'䍙'=>1,'𦋙'=>1,'罺'=>1,'𦌾'=>1,'羕'=>1,'翺'=>1,'者'=>1,'𦓚'=>1,'𦔣'=>1,'聠'=>1,'𦖨'=>1,'聰'=>1,'𣍟'=>1,'ð¯¦'=>1,'育'=>1,'脃'=>1,'䐋'=>1,'脾'=>1,'媵'=>1,'𦞧'=>1,'𦞵'=>1,'𣎓'=>1,'𣎜'=>1,'舁'=>1,'舄'=>1,'ð¯¦'=>1,'䑫'=>1,'ð¯¦'=>1,'ð¯¦'=>1,'芝'=>1,'劳'=>1,'花'=>1,'芳'=>1,'芽'=>1,'苦'=>1,'𦬼'=>1,'若'=>1,'茝'=>1,'荣'=>1,'莭'=>1,'茣'=>1,'ð¯¦'=>1,'菧'=>1,'著'=>1,'荓'=>1,'菊'=>1,'菌'=>1,'菜'=>1,'𦰶'=>1,'𦵫'=>1,'𦳕'=>1,'䔫'=>1,'蓱'=>1,'蓳'=>1,'蔖'=>1,'𧏊'=>1,'蕤'=>1,'ð¯¦'=>1,'䕝'=>1,'䕡'=>1,'𦾱'=>1,'𧃒'=>1,'䕫'=>1,'虐'=>1,'虜'=>1,'虧'=>1,'虩'=>1,'蚩'=>1,'蚈'=>1,'蜎'=>1,'蛢'=>1,'蝹'=>1,'蜨'=>1,'蝫'=>1,'螆'=>1,'䗗'=>1,'蟡'=>1,'ð¯§'=>1,'䗹'=>1,'衠'=>1,'衣'=>1,'𧙧'=>1,'裗'=>1,'裞'=>1,'䘵'=>1,'裺'=>1,'㒻'=>1,'𧢮'=>1,'𧥦'=>1,'ð¯§'=>1,'䛇'=>1,'ð¯§'=>1,'ð¯§'=>1,'變'=>1,'豕'=>1,'𧲨'=>1,'貫'=>1,'賁'=>1,'贛'=>1,'起'=>1,'𧼯'=>1,'𠠄'=>1,'跋'=>1,'趼'=>1,'跰'=>1,'ð¯§'=>1,'軔'=>1,'輸'=>1,'𨗒'=>1,'𨗭'=>1,'邔'=>1,'郱'=>1,'鄑'=>1,'𨜮'=>1,'鄛'=>1,'鈸'=>1,'鋗'=>1,'鋘'=>1,'鉼'=>1,'鏹'=>1,'鐕'=>1,'ð¯§'=>1,'開'=>1,'䦕'=>1,'閷'=>1,'𨵷'=>1,'䧦'=>1,'雃'=>1,'嶲'=>1,'霣'=>1,'𩅅'=>1,'𩈚'=>1,'䩮'=>1,'䩶'=>1,'韠'=>1,'𩐊'=>1,'䪲'=>1,'𩒖'=>1,'頋'=>1,'頋'=>1,'頩'=>1,'ð¯¨'=>1,'飢'=>1,'䬳'=>1,'餩'=>1,'馧'=>1,'駂'=>1,'駾'=>1,'䯎'=>1,'𩬰'=>1,'鬒'=>1,'鱀'=>1,'鳽'=>1,'ð¯¨'=>1,'䳭'=>1,'ð¯¨'=>1,'ð¯¨'=>1,'䳸'=>1,'𪄅'=>1,'𪈎'=>1,'𪊑'=>1,'麻'=>1,'䵖'=>1,'黹'=>1,'黾'=>1,'鼅'=>1,'鼏'=>1,'鼖'=>1,'鼻'=>1,'ð¯¨'=>1,'Ì€'=>0,'Ì'=>0,'Ì‚'=>0,'̃'=>0,'Ì„'=>0,'̆'=>0,'̇'=>0,'̈'=>0,'̉'=>0,'ÌŠ'=>0,'Ì‹'=>0,'ÌŒ'=>0,'Ì'=>0,'Ì‘'=>0,'Ì“'=>0,'Ì”'=>0,'Ì›'=>0,'Ì£'=>0,'̤'=>0,'Ì¥'=>0,'̦'=>0,'̧'=>0,'̨'=>0,'Ì'=>0,'Ì®'=>0,'̰'=>0,'̱'=>0,'̸'=>0,'Í‚'=>0,'Í…'=>0,'Ù“'=>0,'Ù”'=>0,'Ù•'=>0,'़'=>0,'া'=>0,'à§—'=>0,'ା'=>0,'à–'=>0,'à—'=>0,'ா'=>0,'ௗ'=>0,'à±–'=>0,'ೂ'=>0,'ೕ'=>0,'à³–'=>0,'à´¾'=>0,'ൗ'=>0,'à·Š'=>0,'à·'=>0,'à·Ÿ'=>0,'ီ'=>0,'á…¡'=>0,'á…¢'=>0,'á…£'=>0,'á…¤'=>0,'á…¥'=>0,'á…¦'=>0,'á…§'=>0,'á…¨'=>0,'á…©'=>0,'á…ª'=>0,'á…«'=>0,'á…¬'=>0,'á…'=>0,'á…®'=>0,'á…¯'=>0,'á…°'=>0,'á…±'=>0,'á…²'=>0,'á…³'=>0,'á…´'=>0,'á…µ'=>0,'ᆨ'=>0,'ᆩ'=>0,'ᆪ'=>0,'ᆫ'=>0,'ᆬ'=>0,'á†'=>0,'ᆮ'=>0,'ᆯ'=>0,'ᆰ'=>0,'ᆱ'=>0,'ᆲ'=>0,'ᆳ'=>0,'ᆴ'=>0,'ᆵ'=>0,'ᆶ'=>0,'ᆷ'=>0,'ᆸ'=>0,'ᆹ'=>0,'ᆺ'=>0,'ᆻ'=>0,'ᆼ'=>0,'ᆽ'=>0,'ᆾ'=>0,'ᆿ'=>0,'ᇀ'=>0,'á‡'=>0,'ᇂ'=>0,'ᬵ'=>0,'ã‚™'=>0,'゚'=>0);
\ No newline at end of file diff --git a/phpBB/includes/utf/data/utf_normalizer_common.php b/phpBB/includes/utf/data/utf_normalizer_common.php deleted file mode 100644 index befc17d410..0000000000 --- a/phpBB/includes/utf/data/utf_normalizer_common.php +++ /dev/null @@ -1,4 +0,0 @@ -<?php -$GLOBALS['utf_jamo_index']=array('á„€'=>44032,'á„'=>44620,'á„‚'=>45208,'ᄃ'=>45796,'á„„'=>46384,'á„…'=>46972,'ᄆ'=>47560,'ᄇ'=>48148,'ᄈ'=>48736,'ᄉ'=>49324,'ᄊ'=>49912,'á„‹'=>50500,'ᄌ'=>51088,'á„'=>51676,'ᄎ'=>52264,'á„'=>52852,'á„'=>53440,'á„‘'=>54028,'á„’'=>54616,'á…¡'=>0,'á…¢'=>28,'á…£'=>56,'á…¤'=>84,'á…¥'=>112,'á…¦'=>140,'á…§'=>168,'á…¨'=>196,'á…©'=>224,'á…ª'=>252,'á…«'=>280,'á…¬'=>308,'á…'=>336,'á…®'=>364,'á…¯'=>392,'á…°'=>420,'á…±'=>448,'á…²'=>476,'á…³'=>504,'á…´'=>532,'á…µ'=>560,'ᆧ'=>0,'ᆨ'=>1,'ᆩ'=>2,'ᆪ'=>3,'ᆫ'=>4,'ᆬ'=>5,'á†'=>6,'ᆮ'=>7,'ᆯ'=>8,'ᆰ'=>9,'ᆱ'=>10,'ᆲ'=>11,'ᆳ'=>12,'ᆴ'=>13,'ᆵ'=>14,'ᆶ'=>15,'ᆷ'=>16,'ᆸ'=>17,'ᆹ'=>18,'ᆺ'=>19,'ᆻ'=>20,'ᆼ'=>21,'ᆽ'=>22,'ᆾ'=>23,'ᆿ'=>24,'ᇀ'=>25,'á‡'=>26,'ᇂ'=>27); -$GLOBALS['utf_jamo_type']=array('á„€'=>0,'á„'=>0,'á„‚'=>0,'ᄃ'=>0,'á„„'=>0,'á„…'=>0,'ᄆ'=>0,'ᄇ'=>0,'ᄈ'=>0,'ᄉ'=>0,'ᄊ'=>0,'á„‹'=>0,'ᄌ'=>0,'á„'=>0,'ᄎ'=>0,'á„'=>0,'á„'=>0,'á„‘'=>0,'á„’'=>0,'á…¡'=>1,'á…¢'=>1,'á…£'=>1,'á…¤'=>1,'á…¥'=>1,'á…¦'=>1,'á…§'=>1,'á…¨'=>1,'á…©'=>1,'á…ª'=>1,'á…«'=>1,'á…¬'=>1,'á…'=>1,'á…®'=>1,'á…¯'=>1,'á…°'=>1,'á…±'=>1,'á…²'=>1,'á…³'=>1,'á…´'=>1,'á…µ'=>1,'ᆧ'=>2,'ᆨ'=>2,'ᆩ'=>2,'ᆪ'=>2,'ᆫ'=>2,'ᆬ'=>2,'á†'=>2,'ᆮ'=>2,'ᆯ'=>2,'ᆰ'=>2,'ᆱ'=>2,'ᆲ'=>2,'ᆳ'=>2,'ᆴ'=>2,'ᆵ'=>2,'ᆶ'=>2,'ᆷ'=>2,'ᆸ'=>2,'ᆹ'=>2,'ᆺ'=>2,'ᆻ'=>2,'ᆼ'=>2,'ᆽ'=>2,'ᆾ'=>2,'ᆿ'=>2,'ᇀ'=>2,'á‡'=>2,'ᇂ'=>2); -$GLOBALS['utf_combining_class']=array('Ì€'=>230,'Ì'=>230,'Ì‚'=>230,'̃'=>230,'Ì„'=>230,'Ì…'=>230,'̆'=>230,'̇'=>230,'̈'=>230,'̉'=>230,'ÌŠ'=>230,'Ì‹'=>230,'ÌŒ'=>230,'Ì'=>230,'ÌŽ'=>230,'Ì'=>230,'Ì'=>230,'Ì‘'=>230,'Ì’'=>230,'Ì“'=>230,'Ì”'=>230,'Ì•'=>232,'Ì–'=>220,'Ì—'=>220,'̘'=>220,'Ì™'=>220,'Ìš'=>232,'Ì›'=>216,'Ìœ'=>220,'Ì'=>220,'Ìž'=>220,'ÌŸ'=>220,'Ì '=>220,'Ì¡'=>202,'Ì¢'=>202,'Ì£'=>220,'̤'=>220,'Ì¥'=>220,'̦'=>220,'̧'=>202,'̨'=>202,'Ì©'=>220,'̪'=>220,'Ì«'=>220,'̬'=>220,'Ì'=>220,'Ì®'=>220,'̯'=>220,'̰'=>220,'̱'=>220,'̲'=>220,'̳'=>220,'Ì´'=>1,'̵'=>1,'̶'=>1,'Ì·'=>1,'̸'=>1,'̹'=>220,'̺'=>220,'Ì»'=>220,'̼'=>220,'̽'=>230,'̾'=>230,'Ì¿'=>230,'Í€'=>230,'Í'=>230,'Í‚'=>230,'̓'=>230,'Í„'=>230,'Í…'=>240,'͆'=>230,'͇'=>220,'͈'=>220,'͉'=>220,'ÍŠ'=>230,'Í‹'=>230,'ÍŒ'=>230,'Í'=>220,'ÍŽ'=>220,'Í'=>230,'Í‘'=>230,'Í’'=>230,'Í“'=>220,'Í”'=>220,'Í•'=>220,'Í–'=>220,'Í—'=>230,'͘'=>232,'Í™'=>220,'Íš'=>220,'Í›'=>230,'Íœ'=>233,'Í'=>234,'Íž'=>234,'ÍŸ'=>233,'Í '=>234,'Í¡'=>234,'Í¢'=>233,'Í£'=>230,'ͤ'=>230,'Í¥'=>230,'ͦ'=>230,'ͧ'=>230,'ͨ'=>230,'Í©'=>230,'ͪ'=>230,'Í«'=>230,'ͬ'=>230,'Í'=>230,'Í®'=>230,'ͯ'=>230,'Òƒ'=>230,'Ò„'=>230,'Ò…'=>230,'Ò†'=>230,'Ö‘'=>220,'Ö’'=>230,'Ö“'=>230,'Ö”'=>230,'Ö•'=>230,'Ö–'=>220,'Ö—'=>230,'Ö˜'=>230,'Ö™'=>230,'Öš'=>222,'Ö›'=>220,'Öœ'=>230,'Ö'=>230,'Öž'=>230,'ÖŸ'=>230,'Ö '=>230,'Ö¡'=>230,'Ö¢'=>220,'Ö£'=>220,'Ö¤'=>220,'Ö¥'=>220,'Ö¦'=>220,'Ö§'=>220,'Ö¨'=>230,'Ö©'=>230,'Öª'=>220,'Ö«'=>230,'Ö¬'=>230,'Ö'=>222,'Ö®'=>228,'Ö¯'=>230,'Ö°'=>10,'Ö±'=>11,'Ö²'=>12,'Ö³'=>13,'Ö´'=>14,'Öµ'=>15,'Ö¶'=>16,'Ö·'=>17,'Ö¸'=>18,'Ö¹'=>19,'Öº'=>19,'Ö»'=>20,'Ö¼'=>21,'Ö½'=>22,'Ö¿'=>23,'×'=>24,'ׂ'=>25,'ׄ'=>230,'×…'=>220,'ׇ'=>18,'Ø'=>230,'Ø‘'=>230,'Ø’'=>230,'Ø“'=>230,'Ø”'=>230,'Ø•'=>230,'Ù‹'=>27,'ÙŒ'=>28,'Ù'=>29,'ÙŽ'=>30,'Ù'=>31,'Ù'=>32,'Ù‘'=>33,'Ù’'=>34,'Ù“'=>230,'Ù”'=>230,'Ù•'=>220,'Ù–'=>220,'Ù—'=>230,'Ù˜'=>230,'Ù™'=>230,'Ùš'=>230,'Ù›'=>230,'Ùœ'=>220,'Ù'=>230,'Ùž'=>230,'Ù°'=>35,'Û–'=>230,'Û—'=>230,'Û˜'=>230,'Û™'=>230,'Ûš'=>230,'Û›'=>230,'Ûœ'=>230,'ÛŸ'=>230,'Û '=>230,'Û¡'=>230,'Û¢'=>230,'Û£'=>220,'Û¤'=>230,'Û§'=>230,'Û¨'=>230,'Ûª'=>220,'Û«'=>230,'Û¬'=>230,'Û'=>220,'Ü‘'=>36,'ܰ'=>230,'ܱ'=>220,'ܲ'=>230,'ܳ'=>230,'Ü´'=>220,'ܵ'=>230,'ܶ'=>230,'Ü·'=>220,'ܸ'=>220,'ܹ'=>220,'ܺ'=>230,'Ü»'=>220,'ܼ'=>220,'ܽ'=>230,'ܾ'=>220,'Ü¿'=>230,'Ý€'=>230,'Ý'=>230,'Ý‚'=>220,'݃'=>230,'Ý„'=>220,'Ý…'=>230,'݆'=>220,'݇'=>230,'݈'=>220,'݉'=>230,'ÝŠ'=>230,'ß«'=>230,'߬'=>230,'ß'=>230,'ß®'=>230,'߯'=>230,'ß°'=>230,'ß±'=>230,'ß²'=>220,'ß³'=>230,'़'=>7,'à¥'=>9,'॑'=>230,'॒'=>220,'॓'=>230,'॔'=>230,'়'=>7,'à§'=>9,'਼'=>7,'à©'=>9,'઼'=>7,'à«'=>9,'଼'=>7,'à'=>9,'à¯'=>9,'à±'=>9,'ౕ'=>84,'à±–'=>91,'಼'=>7,'à³'=>9,'àµ'=>9,'à·Š'=>9,'ุ'=>103,'ู'=>103,'ฺ'=>9,'่'=>107,'้'=>107,'๊'=>107,'๋'=>107,'ຸ'=>118,'ູ'=>118,'່'=>122,'້'=>122,'໊'=>122,'໋'=>122,'༘'=>220,'༙'=>220,'༵'=>220,'༷'=>220,'༹'=>216,'ཱ'=>129,'ི'=>130,'ུ'=>132,'ེ'=>130,'ཻ'=>130,'ོ'=>130,'ཽ'=>130,'ྀ'=>130,'ྂ'=>230,'ྃ'=>230,'྄'=>9,'྆'=>230,'྇'=>230,'࿆'=>220,'့'=>7,'္'=>9,'áŸ'=>230,'᜔'=>9,'᜴'=>9,'្'=>9,'áŸ'=>230,'ᢩ'=>228,'᤹'=>222,'᤺'=>230,'᤻'=>220,'ᨗ'=>230,'ᨘ'=>220,'᬴'=>7,'á„'=>9,'á«'=>230,'á¬'=>220,'á'=>230,'á®'=>230,'á¯'=>230,'á°'=>230,'á±'=>230,'á²'=>230,'á³'=>230,'á·€'=>230,'á·'=>230,'á·‚'=>220,'á·ƒ'=>230,'á·„'=>230,'á·…'=>230,'á·†'=>230,'á·‡'=>230,'á·ˆ'=>230,'á·‰'=>230,'á·Š'=>220,'á·¾'=>230,'á·¿'=>220,'âƒ'=>230,'⃑'=>230,'⃒'=>1,'⃓'=>1,'⃔'=>230,'⃕'=>230,'⃖'=>230,'⃗'=>230,'⃘'=>1,'⃙'=>1,'⃚'=>1,'⃛'=>230,'⃜'=>230,'⃡'=>230,'⃥'=>1,'⃦'=>1,'⃧'=>230,'⃨'=>220,'⃩'=>230,'⃪'=>1,'⃫'=>1,'⃬'=>220,'âƒ'=>220,'⃮'=>220,'⃯'=>220,'〪'=>218,'〫'=>228,'〬'=>232,'ã€'=>222,'〮'=>224,'〯'=>224,'ã‚™'=>8,'゚'=>8,'ê †'=>9,'ﬞ'=>26,'ï¸ '=>230,'︡'=>230,'︢'=>230,'︣'=>230,'ð¨'=>220,'ð¨'=>230,'ð¨¸'=>230,'ð¨¹'=>1,'ð¨º'=>220,'ð¨¿'=>9,'ð…¥'=>216,'ð…¦'=>216,'ð…§'=>1,'ð…¨'=>1,'ð…©'=>1,'ð…'=>226,'ð…®'=>216,'ð…¯'=>216,'ð…°'=>216,'ð…±'=>216,'ð…²'=>216,'ð…»'=>220,'ð…¼'=>220,'ð…½'=>220,'ð…¾'=>220,'ð…¿'=>220,'ð†€'=>220,'ð†'=>220,'ð†‚'=>220,'ð†…'=>230,'ð††'=>230,'ð†‡'=>230,'ð†ˆ'=>230,'ð†‰'=>230,'ð†Š'=>220,'ð†‹'=>220,'ð†ª'=>230,'ð†«'=>230,'ð†¬'=>230,'ð†'=>230,'ð‰‚'=>230,'ð‰ƒ'=>230,'ð‰„'=>230);
\ No newline at end of file diff --git a/phpBB/includes/utf/utf_normalizer.php b/phpBB/includes/utf/utf_normalizer.php deleted file mode 100644 index 5f88adaa4c..0000000000 --- a/phpBB/includes/utf/utf_normalizer.php +++ /dev/null @@ -1,1505 +0,0 @@ -<?php -/** -* -* @package utf -* @version $Id$ -* @copyright (c) 2005 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -// Unset global variables -unset($GLOBALS['utf_jamo_index'], $GLOBALS['utf_jamo_type'], $GLOBALS['utf_nfc_qc'], $GLOBALS['utf_combining_class'], $GLOBALS['utf_canonical_comp'], $GLOBALS['utf_canonical_decomp'], $GLOBALS['utf_nfkc_qc'], $GLOBALS['utf_compatibility_decomp']); - -/** -* Unicode normalization routines -* -* @package utf -*/ -class utf_normalizer -{ - /** - * Some Unicode characters encoded in UTF-8 - * - * Preserved for compatibility - */ - - const UTF8_REPLACEMENT = "\xEF\xBF\xBD"; - const UTF8_MAX = "\xF4\x8F\xBF\xBF"; - const UTF8_FFFE = "\xEF\xBF\xBE"; - const UTF8_FFFF = "\xEF\xBF\xBF"; - const UTF8_SURROGATE_FIRST = "\xED\xA0\x80"; - const UTF8_SURROGATE_LAST = "\xED\xBF\xBF"; - const UTF8_HANGUL_FIRST = "\xEA\xB0\x80"; - const UTF8_HANGUL_LAST = "\xED\x9E\xA3"; - - const UTF8_CJK_FIRST = "\xE4\xB8\x80"; - const UTF8_CJK_LAST = "\xE9\xBE\xBB"; - const UTF8_CJK_B_FIRST = "\xF0\xA0\x80\x80"; - const UTF8_CJK_B_LAST = "\xF0\xAA\x9B\x96"; - - // NFC_QC and NFKC_QC values - const UNICODE_QC_MAYBE = 0; - const UNICODE_QC_NO = 1; - - // Contains all the ASCII characters appearing in UTF-8, sorted by frequency - const UTF8_ASCII_RANGE = "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0D\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F"; - - // Contains all the tail bytes that can appear in the composition of a UTF-8 char - const UTF8_TRAILING_BYTES = "\xA9\xA0\xA8\x80\xAA\x99\xA7\xBB\xAB\x89\x94\x82\xB4\xA2\xAE\x83\xB0\xB9\xB8\x93\xAF\xBC\xB3\x81\xA4\xB2\x9C\xA1\xB5\xBE\xBD\xBA\x98\xAD\xB1\x84\x95\xA6\xB6\x88\x8D\x90\xB7\xBF\x92\x85\xA5\x97\x8C\x86\xA3\x8E\x9F\x8F\x87\x91\x9D\xAC\x9E\x8B\x96\x9B\x8A\x9A"; - - // Constants used by the Hangul [de]composition algorithms - const UNICODE_HANGUL_SBASE = 0xAC00; - const UNICODE_HANGUL_LBASE = 0x1100; - const UNICODE_HANGUL_VBASE = 0x1161; - const UNICODE_HANGUL_TBASE = 0x11A7; - const UNICODE_HANGUL_SCOUNT = 11172; - const UNICODE_HANGUL_LCOUNT = 19; - const UNICODE_HANGUL_VCOUNT = 21; - const UNICODE_HANGUL_TCOUNT = 28; - const UNICODE_HANGUL_NCOUNT = 588; - const UNICODE_JAMO_L = 0; - const UNICODE_JAMO_V = 1; - const UNICODE_JAMO_T = 2; - - /** - * Validate, cleanup and normalize a string - * - * The ultimate convenience function! Clean up invalid UTF-8 sequences, - * and convert to Normal Form C, canonical composition. - * - * @param string &$str The dirty string - * @return string The same string, all shiny and cleaned-up - */ - public static function cleanup(&$str) - { - // The string below is the list of all authorized characters, sorted by frequency in latin text - $pos = strspn($str, "\x20\x65\x69\x61\x73\x6E\x74\x72\x6F\x6C\x75\x64\x5D\x5B\x63\x6D\x70\x27\x0A\x67\x7C\x68\x76\x2E\x66\x62\x2C\x3A\x3D\x2D\x71\x31\x30\x43\x32\x2A\x79\x78\x29\x28\x4C\x39\x41\x53\x2F\x50\x22\x45\x6A\x4D\x49\x6B\x33\x3E\x35\x54\x3C\x44\x34\x7D\x42\x7B\x38\x46\x77\x52\x36\x37\x55\x47\x4E\x3B\x4A\x7A\x56\x23\x48\x4F\x57\x5F\x26\x21\x4B\x3F\x58\x51\x25\x59\x5C\x09\x5A\x2B\x7E\x5E\x24\x40\x60\x7F\x0D"); - $len = strlen($str); - - if ($pos == $len) - { - // ASCII strings with no special chars return immediately - return; - } - - // Note: we do not check for $GLOBALS['utf_canonical_decomp']. It is assumed they are always loaded together - if (!isset($GLOBALS['utf_nfc_qc'])) - { - include(PHPBB_ROOT_PATH . 'includes/utf/data/utf_nfc_qc.' . PHP_EXT); - } - - if (!isset($GLOBALS['utf_canonical_decomp'])) - { - include(PHPBB_ROOT_PATH . 'includes/utf/data/utf_canonical_decomp.' . PHP_EXT); - } - - // Replace any byte in the range 0x00..0x1F, except for \r, \n and \t - // We replace those characters with a 0xFF byte, which is illegal in UTF-8 and will in turn be replaced with a UTF replacement char - $str = strtr( - $str, - "\x00\x01\x02\x03\x04\x05\x06\x07\x08\x0B\x0C\x0E\x0F\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1A\x1B\x1C\x1D\x1E\x1F", - "\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF\xFF" - ); - - $str = self::recompose($str, $pos, $len, $GLOBALS['utf_nfc_qc'], $GLOBALS['utf_canonical_decomp']); - } - - /** - * Validate and normalize a UTF string to NFC - * - * @param string &$str Unchecked UTF string - * @return string The string, validated and in normal form - */ - public static function nfc(&$str) - { - $pos = strspn($str, self::UTF8_ASCII_RANGE); - $len = strlen($str); - - if ($pos == $len) - { - // ASCII strings return immediately - return; - } - - if (!isset($GLOBALS['utf_nfc_qc'])) - { - include(PHPBB_ROOT_PATH . 'includes/utf/data/utf_nfc_qc.' . PHP_EXT); - } - - if (!isset($GLOBALS['utf_canonical_decomp'])) - { - include(PHPBB_ROOT_PATH . 'includes/utf/data/utf_canonical_decomp.' . PHP_EXT); - } - - $str = self::recompose($str, $pos, $len, $GLOBALS['utf_nfc_qc'], $GLOBALS['utf_canonical_decomp']); - } - - /** - * Validate and normalize a UTF string to NFKC - * - * @param string &$str Unchecked UTF string - * @return string The string, validated and in normal form - */ - public static function nfkc(&$str) - { - $pos = strspn($str, self::UTF8_ASCII_RANGE); - $len = strlen($str); - - if ($pos == $len) - { - // ASCII strings return immediately - return; - } - - if (!isset($GLOBALS['utf_nfkc_qc'])) - { - include(PHPBB_ROOT_PATH . 'includes/utf/data/utf_nfkc_qc.' . PHP_EXT); - } - - if (!isset($GLOBALS['utf_compatibility_decomp'])) - { - include(PHPBB_ROOT_PATH . 'includes/utf/data/utf_compatibility_decomp.' . PHP_EXT); - } - - $str = self::recompose($str, $pos, $len, $GLOBALS['utf_nfkc_qc'], $GLOBALS['utf_compatibility_decomp']); - } - - /** - * Validate and normalize a UTF string to NFD - * - * @param string &$str Unchecked UTF string - * @return string The string, validated and in normal form - */ - public static function nfd(&$str) - { - $pos = strspn($str, self::UTF8_ASCII_RANGE); - $len = strlen($str); - - if ($pos == $len) - { - // ASCII strings return immediately - return; - } - - if (!isset($GLOBALS['utf_canonical_decomp'])) - { - include(PHPBB_ROOT_PATH . 'includes/utf/data/utf_canonical_decomp.' . PHP_EXT); - } - - $str = self::decompose($str, $pos, $len, $GLOBALS['utf_canonical_decomp']); - } - - /** - * Validate and normalize a UTF string to NFKD - * - * @param string &$str Unchecked UTF string - * @return string The string, validated and in normal form - */ - public static function nfkd(&$str) - { - $pos = strspn($str, self::UTF8_ASCII_RANGE); - $len = strlen($str); - - if ($pos == $len) - { - // ASCII strings return immediately - return; - } - - if (!isset($GLOBALS['utf_compatibility_decomp'])) - { - include(PHPBB_ROOT_PATH . 'includes/utf/data/utf_compatibility_decomp.' . PHP_EXT); - } - - $str = self::decompose($str, $pos, $len, $GLOBALS['utf_compatibility_decomp']); - } - - - /** - * Recompose a UTF string - * - * @param string $str Unchecked UTF string - * @param integer $pos Position of the first UTF char (in bytes) - * @param integer $len Length of the string (in bytes) - * @param array &$qc Quick-check array, passed by reference but never modified - * @param array &$decomp_map Decomposition mapping, passed by reference but never modified - * @return string The string, validated and recomposed - * - * @access private - */ - private static function recompose($str, $pos, $len, &$qc, &$decomp_map) - { - global $utf_combining_class, $utf_canonical_comp, $utf_jamo_type, $utf_jamo_index; - - // Load some commonly-used tables - if (!isset($utf_jamo_index, $utf_jamo_type, $utf_combining_class)) - { - include(PHPBB_ROOT_PATH . 'includes/utf/data/utf_normalizer_common.' . PHP_EXT); - } - - // Load the canonical composition table - if (!isset($utf_canonical_comp)) - { - include(PHPBB_ROOT_PATH . 'includes/utf/data/utf_canonical_comp.' . PHP_EXT); - } - - // Buffer the last ASCII char before the UTF-8 stuff if applicable - $tmp = ''; - $i = $tmp_pos = $last_cc = 0; - - $buffer = ($pos) ? array(++$i => $str[$pos - 1]) : array(); - - // UTF char length array - // This array is used to determine the length of a UTF character. - // Be $c the result of ($str[$pos] & "\xF0") --where $str is the string we're operating on and $pos - // the position of the cursor--, if $utf_len_mask[$c] does not exist, the byte is an ASCII char. - // Otherwise, if $utf_len_mask[$c] is greater than 0, we have a the leading byte of a multibyte character - // whose length is $utf_len_mask[$c] and if it is equal to 0, the byte is a trailing byte. - $utf_len_mask = array( - // Leading bytes masks - "\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4, - // Trailing bytes masks - "\x80" => 0, "\x90" => 0, "\xA0" => 0, "\xB0" => 0 - ); - - $extra_check = array( - "\xED" => 1, "\xEF" => 1, "\xC0" => 1, "\xC1" => 1, "\xE0" => 1, "\xF0" => 1, - "\xF4" => 1, "\xF5" => 1, "\xF6" => 1, "\xF7" => 1, "\xF8" => 1, "\xF9" => 1, - "\xFA" => 1, "\xFB" => 1, "\xFC" => 1, "\xFD" => 1, "\xFE" => 1, "\xFF" => 1 - ); - - $utf_validation_mask = array( - 2 => "\xE0\xC0", - 3 => "\xF0\xC0\xC0", - 4 => "\xF8\xC0\xC0\xC0" - ); - - $utf_validation_check = array( - 2 => "\xC0\x80", - 3 => "\xE0\x80\x80", - 4 => "\xF0\x80\x80\x80" - ); - - // Main loop - do - { - // STEP 0: Capture the current char and buffer it - $c = $str[$pos]; - $c_mask = $c & "\xF0"; - - if (isset($utf_len_mask[$c_mask])) - { - // Byte at $pos is either a leading byte or a missplaced trailing byte - if ($utf_len = $utf_len_mask[$c_mask]) - { - // Capture the char - $buffer[++$i & 7] = $utf_char = substr($str, $pos, $utf_len); - - // Let's find out if a thorough check is needed - if (isset($qc[$utf_char])) - { - // If the UTF char is in the qc array then it may not be in normal form. We do nothing here, the actual processing is below this "if" block - } - else if (isset($utf_combining_class[$utf_char])) - { - if ($utf_combining_class[$utf_char] < $last_cc) - { - // A combining character that is NOT canonically ordered - } - else - { - // A combining character that IS canonically ordered, skip to the next char - $last_cc = $utf_combining_class[$utf_char]; - - $pos += $utf_len; - continue; - } - } - else - { - // At this point, $utf_char holds a UTF char that we know is not a NF[K]C_QC and is not a combining character. - // It can be a singleton, a canonical composite, a replacement char or an even an ill-formed bunch of bytes. Let's find out - $last_cc = 0; - - // Check that we have the correct number of trailing bytes - if (($utf_char & $utf_validation_mask[$utf_len]) != $utf_validation_check[$utf_len]) - { - // Current char isn't well-formed or legal: either one or several trailing bytes are missing, or the Unicode char - // has been encoded in a five- or six- byte sequence - if ($utf_char[0] >= "\xF8") - { - if ($utf_char[0] < "\xFC") - { - $trailing_bytes = 4; - } - else if ($utf_char[0] > "\xFD") - { - $trailing_bytes = 0; - } - else - { - $trailing_bytes = 5; - } - } - else - { - $trailing_bytes = $utf_len - 1; - } - - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . self::UTF8_REPLACEMENT; - $pos += strspn($str, self::UTF8_TRAILING_BYTES, ++$pos, $trailing_bytes); - $tmp_pos = $pos; - - continue; - } - - if (isset($extra_check[$c])) - { - switch ($c) - { - // Note: 0xED is quite common in Korean - case "\xED": - if ($utf_char >= "\xED\xA0\x80") - { - // Surrogates (U+D800..U+DFFF) are not allowed in UTF-8 (UTF sequence 0xEDA080..0xEDBFBF) - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . self::UTF8_REPLACEMENT; - $pos += $utf_len; - $tmp_pos = $pos; - continue 2; - } - break; - - // Note: 0xEF is quite common in Japanese - case "\xEF": - if ($utf_char == "\xEF\xBF\xBE" || $utf_char == "\xEF\xBF\xBF") - { - // U+FFFE and U+FFFF are explicitly disallowed (UTF sequence 0xEFBFBE..0xEFBFBF) - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . self::UTF8_REPLACEMENT; - $pos += $utf_len; - $tmp_pos = $pos; - continue 2; - } - break; - - case "\xC0": - case "\xC1": - if ($utf_char <= "\xC1\xBF") - { - // Overlong sequence: Unicode char U+0000..U+007F encoded as a double-byte UTF char - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . self::UTF8_REPLACEMENT; - $pos += $utf_len; - $tmp_pos = $pos; - continue 2; - } - break; - - case "\xE0": - if ($utf_char <= "\xE0\x9F\xBF") - { - // Unicode char U+0000..U+07FF encoded in 3 bytes - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . self::UTF8_REPLACEMENT; - $pos += $utf_len; - $tmp_pos = $pos; - continue 2; - } - break; - - case "\xF0": - if ($utf_char <= "\xF0\x8F\xBF\xBF") - { - // Unicode char U+0000..U+FFFF encoded in 4 bytes - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . self::UTF8_REPLACEMENT; - $pos += $utf_len; - $tmp_pos = $pos; - continue 2; - } - break; - - default: - // Five- and six- byte sequences do not need being checked for here anymore - if ($utf_char > self::UTF8_MAX) - { - // Out of the Unicode range - if ($utf_char[0] < "\xF8") - { - $trailing_bytes = 3; - } - else if ($utf_char[0] < "\xFC") - { - $trailing_bytes = 4; - } - else if ($utf_char[0] > "\xFD") - { - $trailing_bytes = 0; - } - else - { - $trailing_bytes = 5; - } - - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . self::UTF8_REPLACEMENT; - $pos += strspn($str, self::UTF8_TRAILING_BYTES, ++$pos, $trailing_bytes); - $tmp_pos = $pos; - continue 2; - } - break; - } - } - - // The char is a valid starter, move the cursor and go on - $pos += $utf_len; - continue; - } - } - else - { - // A trailing byte came out of nowhere, we will advance the cursor and treat the this byte and all following trailing bytes as if - // each of them was a Unicode replacement char - $spn = strspn($str, self::UTF8_TRAILING_BYTES, $pos); - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . str_repeat(self::UTF8_REPLACEMENT, $spn); - - $pos += $spn; - $tmp_pos = $pos; - continue; - } - - - // STEP 1: Decompose current char - - // We have found a character that is either: - // - in the NFC_QC/NFKC_QC list - // - a non-starter char that is not canonically ordered - // - // We are going to capture the shortest UTF sequence that satisfies these two conditions: - // - // 1 - If the sequence does not start at the begginning of the string, it must begin with a starter, - // and that starter must not have the NF[K]C_QC property equal to "MAYBE" - // - // 2 - If the sequence does not end at the end of the string, it must end with a non-starter and be - // immediately followed by a starter that is not on the QC list - // - $utf_seq = array(); - $last_cc = 0; - $lpos = $pos; - $pos += $utf_len; - - if (isset($decomp_map[$utf_char])) - { - $_pos = 0; - $_len = strlen($decomp_map[$utf_char]); - - do - { - $_utf_len =& $utf_len_mask[$decomp_map[$utf_char][$_pos] & "\xF0"]; - - if (isset($_utf_len)) - { - $utf_seq[] = substr($decomp_map[$utf_char], $_pos, $_utf_len); - $_pos += $_utf_len; - } - else - { - $utf_seq[] = $decomp_map[$utf_char][$_pos]; - ++$_pos; - } - } - while ($_pos < $_len); - } - else - { - // The char is not decomposable - $utf_seq = array($utf_char); - } - - - // STEP 2: Capture the starter - - // Check out the combining class of the first character of the UTF sequence - $k = 0; - if (isset($utf_combining_class[$utf_seq[0]]) || $qc[$utf_char] == self::UNICODE_QC_MAYBE) - { - // Not a starter, inspect previous characters - // The last 8 characters are kept in a buffer so that we don't have to capture them everytime. - // This is enough for all real-life strings but even if it wasn't, we can capture characters in backward mode, - // although it is slower than this method. - // - // In the following loop, $j starts at the previous buffered character ($i - 1, because current character is - // at offset $i) and process them in backward mode until we find a starter. - // - // $k is the index on each UTF character inside of our UTF sequence. At this time, $utf_seq contains one or more - // characters numbered 0 to n. $k starts at 0 and for each char we prepend we pre-decrement it and for numbering - $starter_found = 0; - $j_min = max(1, $i - 7); - - for ($j = $i - 1; $j >= $j_min && $lpos > $tmp_pos; --$j) - { - $utf_char = $buffer[$j & 7]; - $lpos -= strlen($utf_char); - - if (isset($decomp_map[$utf_char])) - { - // The char is a composite, decompose for storage - $decomp_seq = array(); - $_pos = 0; - $_len = strlen($decomp_map[$utf_char]); - - do - { - $c = $decomp_map[$utf_char][$_pos]; - $_utf_len =& $utf_len_mask[$c & "\xF0"]; - - if (isset($_utf_len)) - { - $decomp_seq[] = substr($decomp_map[$utf_char], $_pos, $_utf_len); - $_pos += $_utf_len; - } - else - { - $decomp_seq[] = $c; - ++$_pos; - } - } - while ($_pos < $_len); - - // Prepend the UTF sequence with our decomposed sequence - if (isset($decomp_seq[1])) - { - // The char expanded into several chars - $decomp_cnt = sizeof($decomp_seq); - - foreach ($decomp_seq as $decomp_i => $decomp_char) - { - $utf_seq[$k + $decomp_i - $decomp_cnt] = $decomp_char; - } - $k -= $decomp_cnt; - } - else - { - // Decomposed to a single char, easier to prepend - $utf_seq[--$k] = $decomp_seq[0]; - } - } - else - { - $utf_seq[--$k] = $utf_char; - } - - if (!isset($utf_combining_class[$utf_seq[$k]])) - { - // We have found our starter - $starter_found = 1; - break; - } - } - - if (!$starter_found && $lpos > $tmp_pos) - { - // The starter was not found in the buffer, let's rewind some more - do - { - // $utf_len_mask contains the masks of both leading bytes and trailing bytes. If $utf_en > 0 then it's a leading byte, otherwise it's a trailing byte. - $c = $str[--$lpos]; - $c_mask = $c & "\xF0"; - - if (isset($utf_len_mask[$c_mask])) - { - // UTF byte - if ($utf_len = $utf_len_mask[$c_mask]) - { - // UTF *leading* byte - $utf_char = substr($str, $lpos, $utf_len); - - if (isset($decomp_map[$utf_char])) - { - // Decompose the character - $decomp_seq = array(); - $_pos = 0; - $_len = strlen($decomp_map[$utf_char]); - - do - { - $c = $decomp_map[$utf_char][$_pos]; - $_utf_len =& $utf_len_mask[$c & "\xF0"]; - - if (isset($_utf_len)) - { - $decomp_seq[] = substr($decomp_map[$utf_char], $_pos, $_utf_len); - $_pos += $_utf_len; - } - else - { - $decomp_seq[] = $c; - ++$_pos; - } - } - while ($_pos < $_len); - - // Prepend the UTF sequence with our decomposed sequence - if (isset($decomp_seq[1])) - { - // The char expanded into several chars - $decomp_cnt = sizeof($decomp_seq); - foreach ($decomp_seq as $decomp_i => $utf_char) - { - $utf_seq[$k + $decomp_i - $decomp_cnt] = $utf_char; - } - $k -= $decomp_cnt; - } - else - { - // Decomposed to a single char, easier to prepend - $utf_seq[--$k] = $decomp_seq[0]; - } - } - else - { - $utf_seq[--$k] = $utf_char; - } - } - } - else - { - // ASCII char - $utf_seq[--$k] = $c; - } - } - while ($lpos > $tmp_pos); - } - } - - - // STEP 3: Capture following combining modifiers - - while ($pos < $len) - { - $c_mask = $str[$pos] & "\xF0"; - - if (isset($utf_len_mask[$c_mask])) - { - if ($utf_len = $utf_len_mask[$c_mask]) - { - $utf_char = substr($str, $pos, $utf_len); - } - else - { - // A trailing byte came out of nowhere - // Trailing bytes are replaced with Unicode replacement chars, we will just ignore it for now, break out of the loop - // as if it was a starter (replacement chars ARE starters) and let the next loop replace it - break; - } - - if (isset($utf_combining_class[$utf_char]) || isset($qc[$utf_char])) - { - // Combining character, add it to the sequence and move the cursor - if (isset($decomp_map[$utf_char])) - { - // Decompose the character - $_pos = 0; - $_len = strlen($decomp_map[$utf_char]); - - do - { - $c = $decomp_map[$utf_char][$_pos]; - $_utf_len =& $utf_len_mask[$c & "\xF0"]; - - if (isset($_utf_len)) - { - $utf_seq[] = substr($decomp_map[$utf_char], $_pos, $_utf_len); - $_pos += $_utf_len; - } - else - { - $utf_seq[] = $c; - ++$_pos; - } - } - while ($_pos < $_len); - } - else - { - $utf_seq[] = $utf_char; - } - - $pos += $utf_len; - } - else - { - // Combining class 0 and no QC, break out of the loop - // Note: we do not know if that character is valid. If it's not, the next iteration will replace it - break; - } - } - else - { - // ASCII chars are starters - break; - } - } - - - // STEP 4: Sort and combine - - // Here we sort... - $k_max = $k + sizeof($utf_seq); - - if (!$k && $k_max == 1) - { - // There is only one char in the UTF sequence, add it then jump to the next iteration of main loop - if (substr_compare($str, $utf_seq[0], $lpos, $pos - $lpos)) - { - $tmp .= substr($str, $tmp_pos, $lpos - $tmp_pos) . $utf_seq[0]; - $tmp_pos = $pos; - } - - continue; - } - - // ...there we combine - if (isset($utf_combining_class[$utf_seq[$k]])) - { - $starter = $nf_seq = ''; - } - else - { - $starter = $utf_seq[$k++]; - $nf_seq = ''; - } - $utf_sort = array(); - - // We add an empty char at the end of the UTF char sequence. It will act as a starter and trigger the sort/combine routine - // at the end of the string without altering it - $utf_seq[] = ''; - - do - { - $utf_char = $utf_seq[$k++]; - - if (isset($utf_combining_class[$utf_char])) - { - $utf_sort[$utf_combining_class[$utf_char]][] = $utf_char; - } - else - { - if (empty($utf_sort)) - { - // No combining characters... check for a composite of the two starters - if (isset($utf_canonical_comp[$starter . $utf_char])) - { - // Good ol' composite character - $starter = $utf_canonical_comp[$starter . $utf_char]; - } - else if (isset($utf_jamo_type[$utf_char])) - { - // Current char is a composable jamo - if (isset($utf_jamo_type[$starter]) && $utf_jamo_type[$starter] == self::UNICODE_JAMO_L && $utf_jamo_type[$utf_char] == self::UNICODE_JAMO_V) - { - // We have a L jamo followed by a V jamo, we are going to prefetch the next char to see if it's a T jamo - if (isset($utf_jamo_type[$utf_seq[$k]]) && $utf_jamo_type[$utf_seq[$k]] == self::UNICODE_JAMO_T) - { - // L+V+T jamos, combine to a LVT Hangul syllable ($k is incremented) - $cp = $utf_jamo_index[$starter] + $utf_jamo_index[$utf_char] + $utf_jamo_index[$utf_seq[$k]]; - ++$k; - } - else - { - // L+V jamos, combine to a LV Hangul syllable - $cp = $utf_jamo_index[$starter] + $utf_jamo_index[$utf_char]; - } - - $starter = chr(0xE0 | ($cp >> 12)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F)); - } - else - { - // Non-composable jamo, just add it to the sequence - $nf_seq .= $starter; - $starter = $utf_char; - } - } - else - { - // No composite, just add the first starter to the sequence then continue with the other one - $nf_seq .= $starter; - $starter = $utf_char; - } - } - else - { - ksort($utf_sort); - - // For each class of combining characters - foreach ($utf_sort as $cc => $utf_chars) - { - $j = 0; - - do - { - // Look for a composite - if (isset($utf_canonical_comp[$starter . $utf_chars[$j]])) - { - // Found a composite, replace the starter - $starter = $utf_canonical_comp[$starter . $utf_chars[$j]]; - unset($utf_sort[$cc][$j]); - } - else - { - // No composite, all following characters in that class are blocked - break; - } - } - while (isset($utf_sort[$cc][++$j])); - } - - // Add the starter to the normalized sequence, followed by non-starters in canonical order - $nf_seq .= $starter; - - foreach ($utf_sort as $utf_chars) - { - if (!empty($utf_chars)) - { - $nf_seq .= implode('', $utf_chars); - } - } - - // Reset the array and go on - $utf_sort = array(); - $starter = $utf_char; - } - } - } - while ($k <= $k_max); - - $tmp .= substr($str, $tmp_pos, $lpos - $tmp_pos) . $nf_seq; - $tmp_pos = $pos; - } - else - { - // Only a ASCII char can make the program get here - // - // First we skip the current byte with ++$pos, then we quickly skip following ASCII chars with strspn(). - // - // The first two "if"'s here can be removed, with the consequences of being faster on latin text (lots of ASCII) and slower on - // multi-byte text (where the only ASCII chars are spaces and punctuation) - if (++$pos != $len) - { - if ($str[$pos] < "\x80") - { - $pos += strspn($str, self::UTF8_ASCII_RANGE, ++$pos); - $buffer[++$i & 7] = $str[$pos - 1]; - } - else - { - $buffer[++$i & 7] = $c; - } - } - } - } - while ($pos < $len); - - // Now is time to return the string - if ($tmp_pos) - { - // If the $tmp_pos cursor is not at the beggining of the string then at least one character was not in normal form. Replace $str with the fixed version - if ($tmp_pos == $len) - { - // The $tmp_pos cursor is at the end of $str, therefore $tmp holds the whole $str - return $tmp; - } - else - { - // The rightmost chunk of $str has not been appended to $tmp yet - return $tmp . substr($str, $tmp_pos); - } - } - - // The string was already in normal form - return $str; - } - - /** - * Decompose a UTF string - * - * @param string $str UTF string - * @param integer $pos Position of the first UTF char (in bytes) - * @param integer $len Length of the string (in bytes) - * @param array &$decomp_map Decomposition mapping, passed by reference but never modified - * @return string The string, decomposed and sorted canonically - * - * @access private - */ - private static function decompose($str, $pos, $len, &$decomp_map) - { - global $utf_combining_class; - - // Load some commonly-used tables - if (!isset($utf_combining_class)) - { - include(PHPBB_ROOT_PATH . 'includes/utf/data/utf_normalizer_common.' . PHP_EXT); - } - - // UTF char length array - $utf_len_mask = array( - // Leading bytes masks - "\xC0" => 2, "\xD0" => 2, "\xE0" => 3, "\xF0" => 4, - // Trailing bytes masks - "\x80" => 0, "\x90" => 0, "\xA0" => 0, "\xB0" => 0 - ); - - // Some extra checks are triggered on the first byte of a UTF sequence - $extra_check = array( - "\xED" => 1, "\xEF" => 1, "\xC0" => 1, "\xC1" => 1, "\xE0" => 1, "\xF0" => 1, - "\xF4" => 1, "\xF5" => 1, "\xF6" => 1, "\xF7" => 1, "\xF8" => 1, "\xF9" => 1, - "\xFA" => 1, "\xFB" => 1, "\xFC" => 1, "\xFD" => 1, "\xFE" => 1, "\xFF" => 1 - ); - - // These masks are used to check if a UTF sequence is well formed. Here are the only 3 lengths we acknowledge: - // - 2-byte: 110? ???? 10?? ???? - // - 3-byte: 1110 ???? 10?? ???? 10?? ???? - // - 4-byte: 1111 0??? 10?? ???? 10?? ???? 10?? ???? - // Note that 5- and 6- byte sequences are automatically discarded - $utf_validation_mask = array( - 2 => "\xE0\xC0", - 3 => "\xF0\xC0\xC0", - 4 => "\xF8\xC0\xC0\xC0" - ); - - $utf_validation_check = array( - 2 => "\xC0\x80", - 3 => "\xE0\x80\x80", - 4 => "\xF0\x80\x80\x80" - ); - - $tmp = ''; - $starter_pos = $pos; - $tmp_pos = $last_cc = $sort = $dump = 0; - $utf_sort = array(); - - - // Main loop - do - { - // STEP 0: Capture the current char - - $cur_mask = $str[$pos] & "\xF0"; - if (isset($utf_len_mask[$cur_mask])) - { - if ($utf_len = $utf_len_mask[$cur_mask]) - { - // Multibyte char - $utf_char = substr($str, $pos, $utf_len); - $pos += $utf_len; - } - else - { - // A trailing byte came out of nowhere, we will treat it and all following trailing bytes as if each of them was a Unicode - // replacement char and we will advance the cursor - $spn = strspn($str, self::UTF8_TRAILING_BYTES, $pos); - - if ($dump) - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - // Dump combiners - if (!empty($utf_sort)) - { - if ($sort) - { - ksort($utf_sort); - } - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - } - - $tmp .= str_repeat(self::UTF8_REPLACEMENT, $spn); - $dump = $sort = 0; - } - else - { - $tmp .= substr($str, $tmp_pos, $pos - $tmp_pos) . str_repeat(self::UTF8_REPLACEMENT, $spn); - } - - $pos += $spn; - $tmp_pos = $starter_pos = $pos; - - $utf_sort = array(); - $last_cc = 0; - - continue; - } - - - // STEP 1: Decide what to do with current char - - // Now, in that order: - // - check if that character is decomposable - // - check if that character is a non-starter - // - check if that character requires extra checks to be performed - if (isset($decomp_map[$utf_char])) - { - // Decompose the char - $_pos = 0; - $_len = strlen($decomp_map[$utf_char]); - - do - { - $c = $decomp_map[$utf_char][$_pos]; - $_utf_len =& $utf_len_mask[$c & "\xF0"]; - - if (isset($_utf_len)) - { - $_utf_char = substr($decomp_map[$utf_char], $_pos, $_utf_len); - $_pos += $_utf_len; - - if (isset($utf_combining_class[$_utf_char])) - { - // The character decomposed to a non-starter, buffer it for sorting - $utf_sort[$utf_combining_class[$_utf_char]][] = $_utf_char; - - if ($utf_combining_class[$_utf_char] < $last_cc) - { - // Not canonically ordered, will require sorting - $sort = $dump = 1; - } - else - { - $dump = 1; - $last_cc = $utf_combining_class[$_utf_char]; - } - } - else - { - // This character decomposition contains a starter, dump the buffer and continue - if ($dump) - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - // Dump combiners - if (!empty($utf_sort)) - { - if ($sort) - { - ksort($utf_sort); - } - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - } - - $tmp .= $_utf_char; - $dump = $sort = 0; - } - else - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos) . $_utf_char; - } - - $tmp_pos = $starter_pos = $pos; - $utf_sort = array(); - $last_cc = 0; - } - } - else - { - // This character decomposition contains an ASCII char, which is a starter. Dump the buffer and continue - ++$_pos; - - if ($dump) - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - // Dump combiners - if (!empty($utf_sort)) - { - if ($sort) - { - ksort($utf_sort); - } - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - } - - $tmp .= $c; - $dump = $sort = 0; - } - else - { - $tmp .= substr($str, $tmp_pos, $pos - $utf_len - $tmp_pos) . $c; - } - - $tmp_pos = $starter_pos = $pos; - $utf_sort = array(); - $last_cc = 0; - } - } - while ($_pos < $_len); - } - else if (isset($utf_combining_class[$utf_char])) - { - // Combining character - if ($utf_combining_class[$utf_char] < $last_cc) - { - // Not in canonical order - $sort = $dump = 1; - } - else - { - $last_cc = $utf_combining_class[$utf_char]; - } - - $utf_sort[$utf_combining_class[$utf_char]][] = $utf_char; - } - else - { - // Non-decomposable starter, check out if it's a Hangul syllable - if ($utf_char < self::UTF8_HANGUL_FIRST || $utf_char > self::UTF8_HANGUL_LAST) - { - // Nope, regular UTF char, check that we have the correct number of trailing bytes - if (($utf_char & $utf_validation_mask[$utf_len]) != $utf_validation_check[$utf_len]) - { - // Current char isn't well-formed or legal: either one or several trailing bytes are missing, or the Unicode char - // has been encoded in a five- or six- byte sequence. - // Move the cursor back to its original position then advance it to the position it should really be at - $pos -= $utf_len; - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - // Add a replacement char then another replacement char for every trailing byte. - // - // @todo I'm not entirely sure that's how we're supposed to mark invalidated byte sequences, check this - $spn = strspn($str, self::UTF8_TRAILING_BYTES, ++$pos); - $tmp .= str_repeat(self::UTF8_REPLACEMENT, $spn + 1); - - $dump = $sort = 0; - - $pos += $spn; - $tmp_pos = $pos; - continue; - } - - if (isset($extra_check[$utf_char[0]])) - { - switch ($utf_char[0]) - { - // Note: 0xED is quite common in Korean - case "\xED": - if ($utf_char >= "\xED\xA0\x80") - { - // Surrogates (U+D800..U+DFFF) are not allowed in UTF-8 (UTF sequence 0xEDA080..0xEDBFBF) - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - $tmp .= self::UTF8_REPLACEMENT; - $dump = $sort = 0; - - $tmp_pos = $starter_pos = $pos; - continue 2; - } - break; - - // Note: 0xEF is quite common in Japanese - case "\xEF": - if ($utf_char == "\xEF\xBF\xBE" || $utf_char == "\xEF\xBF\xBF") - { - // U+FFFE and U+FFFF are explicitly disallowed (UTF sequence 0xEFBFBE..0xEFBFBF) - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - $tmp .= self::UTF8_REPLACEMENT; - $dump = $sort = 0; - - $tmp_pos = $starter_pos = $pos; - continue 2; - } - break; - - case "\xC0": - case "\xC1": - if ($utf_char <= "\xC1\xBF") - { - // Overlong sequence: Unicode char U+0000..U+007F encoded as a double-byte UTF char - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - $tmp .= self::UTF8_REPLACEMENT; - $dump = $sort = 0; - - $tmp_pos = $starter_pos = $pos; - continue 2; - } - break; - - case "\xE0": - if ($utf_char <= "\xE0\x9F\xBF") - { - // Unicode char U+0000..U+07FF encoded in 3 bytes - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - $tmp .= self::UTF8_REPLACEMENT; - $dump = $sort = 0; - - $tmp_pos = $starter_pos = $pos; - continue 2; - } - break; - - case "\xF0": - if ($utf_char <= "\xF0\x8F\xBF\xBF") - { - // Unicode char U+0000..U+FFFF encoded in 4 bytes - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - $tmp .= self::UTF8_REPLACEMENT; - $dump = $sort = 0; - - $tmp_pos = $starter_pos = $pos; - continue 2; - } - break; - - default: - if ($utf_char > self::UTF8_MAX) - { - // Out of the Unicode range - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - if (!empty($utf_sort)) - { - ksort($utf_sort); - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - $utf_sort = array(); - } - - $tmp .= self::UTF8_REPLACEMENT; - $dump = $sort = 0; - - $tmp_pos = $starter_pos = $pos; - continue 2; - } - break; - } - } - } - else - { - // Hangul syllable - $idx = (((ord($utf_char[0]) & 0x0F) << 12) | ((ord($utf_char[1]) & 0x3F) << 6) | (ord($utf_char[2]) & 0x3F)) - self::UNICODE_HANGUL_SBASE; - - // LIndex can only range from 0 to 18, therefore it cannot influence the first two bytes of the L Jamo, which allows us to hardcode them (based on LBase). - // - // The same goes for VIndex, but for TIndex there's a catch: the value of the third byte could exceed 0xBF and we would have to increment the second byte - if ($t_index = $idx % self::UNICODE_HANGUL_TCOUNT) - { - if ($t_index < 25) - { - $utf_char = "\xE1\x84\x00\xE1\x85\x00\xE1\x86\x00"; - $utf_char[8] = chr(0xA7 + $t_index); - } - else - { - $utf_char = "\xE1\x84\x00\xE1\x85\x00\xE1\x87\x00"; - $utf_char[8] = chr(0x67 + $t_index); - } - } - else - { - $utf_char = "\xE1\x84\x00\xE1\x85\x00"; - } - - $utf_char[2] = chr(0x80 + (int) ($idx / self::UNICODE_HANGUL_NCOUNT)); - $utf_char[5] = chr(0xA1 + (int) (($idx % self::UNICODE_HANGUL_NCOUNT) / self::UNICODE_HANGUL_TCOUNT)); - - // Just like other decompositions, the resulting Jamos must be dumped to the tmp string - $dump = 1; - } - - // Do we need to dump stuff to the tmp string? - if ($dump) - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - // Dump combiners - if (!empty($utf_sort)) - { - if ($sort) - { - ksort($utf_sort); - } - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - } - - $tmp .= $utf_char; - $dump = $sort = 0; - $tmp_pos = $pos; - } - - $last_cc = 0; - $utf_sort = array(); - $starter_pos = $pos; - } - } - else - { - // ASCII char, which happens to be a starter (as any other ASCII char) - if ($dump) - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - // Dump combiners - if (!empty($utf_sort)) - { - if ($sort) - { - ksort($utf_sort); - } - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - } - - $tmp .= $str[$pos]; - $dump = $sort = 0; - $tmp_pos = ++$pos; - - $pos += strspn($str, self::UTF8_ASCII_RANGE, $pos); - } - else - { - $pos += strspn($str, self::UTF8_ASCII_RANGE, ++$pos); - } - - $last_cc = 0; - $utf_sort = array(); - $starter_pos = $pos; - } - } - while ($pos < $len); - - // Now is time to return the string - if ($dump) - { - $tmp .= substr($str, $tmp_pos, $starter_pos - $tmp_pos); - - // Dump combiners - if (!empty($utf_sort)) - { - if ($sort) - { - ksort($utf_sort); - } - - foreach ($utf_sort as $utf_chars) - { - $tmp .= implode('', $utf_chars); - } - } - - return $tmp; - } - else if ($tmp_pos) - { - // If the $tmp_pos cursor was moved then at least one character was not in normal form. Replace $str with the fixed version - if ($tmp_pos == $len) - { - // The $tmp_pos cursor is at the end of $str, therefore $tmp holds the whole $str - return $tmp; - } - else - { - // The rightmost chunk of $str has not been appended to $tmp yet - return $tmp . substr($str, $tmp_pos); - } - } - - // The string was already in normal form - return $str; - } -} - -?>
\ No newline at end of file diff --git a/phpBB/includes/utf/utf_tools.php b/phpBB/includes/utf/utf_tools.php deleted file mode 100644 index b946f16466..0000000000 --- a/phpBB/includes/utf/utf_tools.php +++ /dev/null @@ -1,1516 +0,0 @@ -<?php -/** -* -* @package utf -* @version $Id$ -* @copyright (c) 2006 phpBB Group -* @license http://opensource.org/licenses/gpl-license.php GNU Public License -* -*/ - -/** -*/ -if (!defined('IN_PHPBB')) -{ - exit; -} - -// Enforce ASCII only string handling -setlocale(LC_CTYPE, 'C'); - -/** -* UTF-8 tools -* -* Whenever possible, these functions will try to use PHP's built-in functions or -* extensions, otherwise they will default to custom routines. -* -* @package utf -*/ - -if (!extension_loaded('xml')) -{ - /** - * Implementation of PHP's native utf8_encode for people without XML support - * This function exploits some nice things that ISO-8859-1 and UTF-8 have in common - * - * @param string $str ISO-8859-1 encoded data - * @return string UTF-8 encoded data - */ - function utf8_encode($str) - { - $out = ''; - for ($i = 0, $len = strlen($str); $i < $len; $i++) - { - $letter = $str[$i]; - $num = ord($letter); - if ($num < 0x80) - { - $out .= $letter; - } - else if ($num < 0xC0) - { - $out .= "\xC2" . $letter; - } - else - { - $out .= "\xC3" . chr($num - 64); - } - } - return $out; - } - - /** - * Implementation of PHP's native utf8_decode for people without XML support - * - * @param string $str UTF-8 encoded data - * @return string ISO-8859-1 encoded data - */ - function utf8_decode($str) - { - $pos = 0; - $len = strlen($str); - $ret = ''; - - while ($pos < $len) - { - $ord = ord($str[$pos]) & 0xF0; - if ($ord === 0xC0 || $ord === 0xD0) - { - $charval = ((ord($str[$pos]) & 0x1F) << 6) | (ord($str[$pos + 1]) & 0x3F); - $pos += 2; - $ret .= (($charval < 256) ? chr($charval) : '?'); - } - else if ($ord === 0xE0) - { - $ret .= '?'; - $pos += 3; - } - else if ($ord === 0xF0) - { - $ret .= '?'; - $pos += 4; - } - else - { - $ret .= $str[$pos]; - ++$pos; - } - } - return $ret; - } -} - -// mbstring is old and has it's functions around for older versions of PHP. -// if mbstring is not loaded, we go into native mode. -if (extension_loaded('mbstring')) -{ - mb_internal_encoding('UTF-8'); - - /** - * UTF-8 aware alternative to strrpos - * Find position of last occurrence of a char in a string - * - * Notes: - * - offset for mb_strrpos was added in 5.2.0, we emulate if it is lower - */ - if (version_compare(PHP_VERSION, '5.2.0', '>=')) - { - /** - * UTF-8 aware alternative to strrpos - * @ignore - */ - function utf8_strrpos($str, $needle, $offset = null) - { - // Emulate behaviour of strrpos rather than raising warning - if (empty($str)) - { - return false; - } - - if (is_null($offset)) - { - return mb_strrpos($str, $needle); - } - else - { - return mb_strrpos($str, $needle, $offset); - } - } - } - else - { - /** - * UTF-8 aware alternative to strrpos - * @ignore - */ - function utf8_strrpos($str, $needle, $offset = null) - { - // offset for mb_strrpos was added in 5.2.0 - if (is_null($offset)) - { - // Emulate behaviour of strrpos rather than raising warning - if (empty($str)) - { - return false; - } - - return mb_strrpos($str, $needle); - } - else - { - if (!is_int($offset)) - { - trigger_error('utf8_strrpos expects parameter 3 to be long', E_USER_ERROR); - return false; - } - - $str = mb_substr($str, $offset); - - if (false !== ($pos = mb_strrpos($str, $needle))) - { - return $pos + $offset; - } - - return false; - } - } - } - - /** - * UTF-8 aware alternative to strpos - * @ignore - */ - function utf8_strpos($str, $needle, $offset = null) - { - if (is_null($offset)) - { - return mb_strpos($str, $needle); - } - else - { - return mb_strpos($str, $needle, $offset); - } - } - - /** - * UTF-8 aware alternative to substr - * @ignore - */ - function utf8_substr($str, $offset, $length = null) - { - if (is_null($length)) - { - return mb_substr($str, $offset); - } - else - { - return mb_substr($str, $offset, $length); - } - } - - /** - * Return the length (in characters) of a UTF-8 string - * @ignore - */ - function utf8_strlen($text) - { - return mb_strlen($text, 'utf-8'); - } -} -else -{ - /** - * UTF-8 aware alternative to strrpos - * Find position of last occurrence of a char in a string - * - * @author Harry Fuecks - * @param string $str haystack - * @param string $needle needle - * @param integer $offset (optional) offset (from left) - * @return mixed integer position or FALSE on failure - */ - function utf8_strrpos($str, $needle, $offset = null) - { - if (is_null($offset)) - { - $ar = explode($needle, $str); - - if (sizeof($ar) > 1) - { - // Pop off the end of the string where the last match was made - array_pop($ar); - $str = join($needle, $ar); - - return utf8_strlen($str); - } - return false; - } - else - { - if (!is_int($offset)) - { - trigger_error('utf8_strrpos expects parameter 3 to be long', E_USER_ERROR); - return false; - } - - $str = utf8_substr($str, $offset); - - if (false !== ($pos = utf8_strrpos($str, $needle))) - { - return $pos + $offset; - } - - return false; - } - } - - /** - * UTF-8 aware alternative to strpos - * Find position of first occurrence of a string - * - * @author Harry Fuecks - * @param string $str haystack - * @param string $needle needle - * @param integer $offset offset in characters (from left) - * @return mixed integer position or FALSE on failure - */ - function utf8_strpos($str, $needle, $offset = null) - { - if (is_null($offset)) - { - $ar = explode($needle, $str); - if (sizeof($ar) > 1) - { - return utf8_strlen($ar[0]); - } - return false; - } - else - { - if (!is_int($offset)) - { - trigger_error('utf8_strpos: Offset must be an integer', E_USER_ERROR); - return false; - } - - $str = utf8_substr($str, $offset); - - if (false !== ($pos = utf8_strpos($str, $needle))) - { - return $pos + $offset; - } - - return false; - } - } - - /** - * UTF-8 aware alternative to substr - * Return part of a string given character offset (and optionally length) - * - * Note arguments: comparied to substr - if offset or length are - * not integers, this version will not complain but rather massages them - * into an integer. - * - * Note on returned values: substr documentation states false can be - * returned in some cases (e.g. offset > string length) - * mb_substr never returns false, it will return an empty string instead. - * This adopts the mb_substr approach - * - * Note on implementation: PCRE only supports repetitions of less than - * 65536, in order to accept up to MAXINT values for offset and length, - * we'll repeat a group of 65535 characters when needed. - * - * Note on implementation: calculating the number of characters in the - * string is a relatively expensive operation, so we only carry it out when - * necessary. It isn't necessary for +ve offsets and no specified length - * - * @author Chris Smith<chris@jalakai.co.uk> - * @param string $str - * @param integer $offset number of UTF-8 characters offset (from left) - * @param integer $length (optional) length in UTF-8 characters from offset - * @return mixed string or FALSE if failure - */ - function utf8_substr($str, $offset, $length = NULL) - { - // generates E_NOTICE - // for PHP4 objects, but not PHP5 objects - $str = (string) $str; - $offset = (int) $offset; - if (!is_null($length)) - { - $length = (int) $length; - } - - // handle trivial cases - if ($length === 0 || ($offset < 0 && $length < 0 && $length < $offset)) - { - return ''; - } - - // normalise negative offsets (we could use a tail - // anchored pattern, but they are horribly slow!) - if ($offset < 0) - { - // see notes - $strlen = utf8_strlen($str); - $offset = $strlen + $offset; - if ($offset < 0) - { - $offset = 0; - } - } - - $op = ''; - $lp = ''; - - // establish a pattern for offset, a - // non-captured group equal in length to offset - if ($offset > 0) - { - $ox = (int) ($offset / 65535); - $oy = $offset % 65535; - - if ($ox) - { - $op = '(?:.{65535}){' . $ox . '}'; - } - - $op = '^(?:' . $op . '.{' . $oy . '})'; - } - else - { - // offset == 0; just anchor the pattern - $op = '^'; - } - - // establish a pattern for length - if (is_null($length)) - { - // the rest of the string - $lp = '(.*)$'; - } - else - { - if (!isset($strlen)) - { - // see notes - $strlen = utf8_strlen($str); - } - - // another trivial case - if ($offset > $strlen) - { - return ''; - } - - if ($length > 0) - { - // reduce any length that would - // go passed the end of the string - $length = min($strlen - $offset, $length); - - $lx = (int) ($length / 65535); - $ly = $length % 65535; - - // negative length requires a captured group - // of length characters - if ($lx) - { - $lp = '(?:.{65535}){' . $lx . '}'; - } - $lp = '(' . $lp . '.{'. $ly . '})'; - } - else if ($length < 0) - { - if ($length < ($offset - $strlen)) - { - return ''; - } - - $lx = (int)((-$length) / 65535); - $ly = (-$length) % 65535; - - // negative length requires ... capture everything - // except a group of -length characters - // anchored at the tail-end of the string - if ($lx) - { - $lp = '(?:.{65535}){' . $lx . '}'; - } - $lp = '(.*)(?:' . $lp . '.{' . $ly . '})$'; - } - } - - if (!preg_match('#' . $op . $lp . '#us', $str, $match)) - { - return ''; - } - - return $match[1]; - } - - /** - * Return the length (in characters) of a UTF-8 string - * - * @param string $text UTF-8 string - * @return integer Length (in chars) of given string - */ - function utf8_strlen($text) - { - // Since utf8_decode is replacing multibyte characters to ? strlen works fine - return strlen(utf8_decode($text)); - } -} - -/** -* UTF-8 aware alternative to str_split -* Convert a string to an array -* -* @author Harry Fuecks -* @param string $str UTF-8 encoded -* @param int $split_len number to characters to split string by -* @return array characters in string reverses -*/ -function utf8_str_split($str, $split_len = 1) -{ - if (!is_int($split_len) || $split_len < 1) - { - return false; - } - - $len = utf8_strlen($str); - if ($len <= $split_len) - { - return array($str); - } - - preg_match_all('/.{' . $split_len . '}|[^\x00]{1,' . $split_len . '}$/us', $str, $ar); - return $ar[0]; -} - -/** -* UTF-8 aware alternative to strspn -* Find length of initial segment matching the mask -* -* @author Harry Fuecks -*/ -function utf8_strspn($str, $mask, $start = null, $length = null) -{ - if ($start !== null || $length !== null) - { - $str = utf8_substr($str, $start, $length); - } - - preg_match('/^[' . $mask . ']+/u', $str, $matches); - - if (isset($matches[0])) - { - return utf8_strlen($matches[0]); - } - - return 0; -} - -/** -* Replace all UTF-8 chars that are not in ASCII with their NCR -* -* @param string $text UTF-8 string in NFC -* @return string ASCII string using NCRs for non-ASCII chars -*/ -function utf8_encode_ncr($text) -{ - return preg_replace_callback('#[\\xC2-\\xF4][\\x80-\\xBF]{1,3}#', 'utf8_encode_ncr_callback', $text); -} - -/** -* Callback used in encode_ncr() -* -* Takes a UTF-8 char and replaces it with its NCR. Attention, $m is an array -* -* @param array $m 0-based numerically indexed array passed by preg_replace_callback() -* @return string A HTML NCR if the character is valid, or the original string otherwise -*/ -function utf8_encode_ncr_callback($m) -{ - return '&#' . utf8_ord($m[0]) . ';'; -} - -/** -* Converts a UTF-8 char to an NCR -* -* @param string $chr UTF-8 char -* @return integer UNICODE code point -*/ -function utf8_ord($chr) -{ - switch (strlen($chr)) - { - case 1: - return ord($chr); - break; - - case 2: - return ((ord($chr[0]) & 0x1F) << 6) | (ord($chr[1]) & 0x3F); - break; - - case 3: - return ((ord($chr[0]) & 0x0F) << 12) | ((ord($chr[1]) & 0x3F) << 6) | (ord($chr[2]) & 0x3F); - break; - - case 4: - return ((ord($chr[0]) & 0x07) << 18) | ((ord($chr[1]) & 0x3F) << 12) | ((ord($chr[2]) & 0x3F) << 6) | (ord($chr[3]) & 0x3F); - break; - - default: - return $chr; - } -} - -/** -* Converts an NCR to a UTF-8 char -* -* @param int $cp UNICODE code point -* @return string UTF-8 char -*/ -function utf8_chr($cp) -{ - if ($cp > 0xFFFF) - { - return chr(0xF0 | ($cp >> 18)) . chr(0x80 | (($cp >> 12) & 0x3F)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F)); - } - else if ($cp > 0x7FF) - { - return chr(0xE0 | ($cp >> 12)) . chr(0x80 | (($cp >> 6) & 0x3F)) . chr(0x80 | ($cp & 0x3F)); - } - else if ($cp > 0x7F) - { - return chr(0xC0 | ($cp >> 6)) . chr(0x80 | ($cp & 0x3F)); - } - else - { - return chr($cp); - } -} - -/** -* Convert Numeric Character References to UTF-8 chars -* -* Notes: -* - we do not convert NCRs recursively, if you pass &#38; it will return & -* - we DO NOT check for the existence of the Unicode characters, therefore an entity may be converted to an inexistent codepoint -* -* @param string $text String to convert, encoded in UTF-8 (no normal form required) -* @return string UTF-8 string where NCRs have been replaced with the actual chars -*/ -function utf8_decode_ncr($text) -{ - return preg_replace_callback('/&#([0-9]{1,6}|x[0-9A-F]{1,5});/i', 'utf8_decode_ncr_callback', $text); -} - -/** -* Callback used in decode_ncr() -* -* Takes a NCR (in decimal or hexadecimal) and returns a UTF-8 char. Attention, $m is an array. -* It will ignore most of invalid NCRs, but not all! -* -* @param array $m 0-based numerically indexed array passed by preg_replace_callback() -* @return string UTF-8 char -*/ -function utf8_decode_ncr_callback($m) -{ - $cp = (strncasecmp($m[1], 'x', 1)) ? $m[1] : hexdec(substr($m[1], 1)); - - return utf8_chr($cp); -} - -/** -* Case folds a unicode string as per Unicode 5.0, section 3.13 -* -* @param string $text text to be case folded -* @param string $option determines how we will fold the cases -* @return string case folded text -*/ -function utf8_case_fold($text, $option = 'full') -{ - static $uniarray = array(); - - // common is always set - if (!isset($uniarray['c'])) - { - $uniarray['c'] = include(PHPBB_ROOT_PATH . 'includes/utf/data/case_fold_c.' . PHP_EXT); - } - - // only set full if we need to - if ($option === 'full' && !isset($uniarray['f'])) - { - $uniarray['f'] = include(PHPBB_ROOT_PATH . 'includes/utf/data/case_fold_f.' . PHP_EXT); - } - - // only set simple if we need to - if ($option !== 'full' && !isset($uniarray['s'])) - { - $uniarray['s'] = include(PHPBB_ROOT_PATH . 'includes/utf/data/case_fold_s.' . PHP_EXT); - } - - // common is always replaced - $text = strtr($text, $uniarray['c']); - - if ($option === 'full') - { - // full replaces a character with multiple characters - $text = strtr($text, $uniarray['f']); - } - else - { - // simple replaces a character with another character - $text = strtr($text, $uniarray['s']); - } - - return $text; -} - -/** -* Takes the input and does a "special" case fold. It does minor normalization -* and returns NFKC compatable text -* -* @param string $text text to be case folded -* @param string $option determines how we will fold the cases -* @return string case folded text -*/ -function utf8_case_fold_nfkc($text, $option = 'full') -{ - static $fc_nfkc_closure = array( - "\xCD\xBA" => "\x20\xCE\xB9", - "\xCF\x92" => "\xCF\x85", - "\xCF\x93" => "\xCF\x8D", - "\xCF\x94" => "\xCF\x8B", - "\xCF\xB2" => "\xCF\x83", - "\xCF\xB9" => "\xCF\x83", - "\xE1\xB4\xAC" => "\x61", - "\xE1\xB4\xAD" => "\xC3\xA6", - "\xE1\xB4\xAE" => "\x62", - "\xE1\xB4\xB0" => "\x64", - "\xE1\xB4\xB1" => "\x65", - "\xE1\xB4\xB2" => "\xC7\x9D", - "\xE1\xB4\xB3" => "\x67", - "\xE1\xB4\xB4" => "\x68", - "\xE1\xB4\xB5" => "\x69", - "\xE1\xB4\xB6" => "\x6A", - "\xE1\xB4\xB7" => "\x6B", - "\xE1\xB4\xB8" => "\x6C", - "\xE1\xB4\xB9" => "\x6D", - "\xE1\xB4\xBA" => "\x6E", - "\xE1\xB4\xBC" => "\x6F", - "\xE1\xB4\xBD" => "\xC8\xA3", - "\xE1\xB4\xBE" => "\x70", - "\xE1\xB4\xBF" => "\x72", - "\xE1\xB5\x80" => "\x74", - "\xE1\xB5\x81" => "\x75", - "\xE1\xB5\x82" => "\x77", - "\xE2\x82\xA8" => "\x72\x73", - "\xE2\x84\x82" => "\x63", - "\xE2\x84\x83" => "\xC2\xB0\x63", - "\xE2\x84\x87" => "\xC9\x9B", - "\xE2\x84\x89" => "\xC2\xB0\x66", - "\xE2\x84\x8B" => "\x68", - "\xE2\x84\x8C" => "\x68", - "\xE2\x84\x8D" => "\x68", - "\xE2\x84\x90" => "\x69", - "\xE2\x84\x91" => "\x69", - "\xE2\x84\x92" => "\x6C", - "\xE2\x84\x95" => "\x6E", - "\xE2\x84\x96" => "\x6E\x6F", - "\xE2\x84\x99" => "\x70", - "\xE2\x84\x9A" => "\x71", - "\xE2\x84\x9B" => "\x72", - "\xE2\x84\x9C" => "\x72", - "\xE2\x84\x9D" => "\x72", - "\xE2\x84\xA0" => "\x73\x6D", - "\xE2\x84\xA1" => "\x74\x65\x6C", - "\xE2\x84\xA2" => "\x74\x6D", - "\xE2\x84\xA4" => "\x7A", - "\xE2\x84\xA8" => "\x7A", - "\xE2\x84\xAC" => "\x62", - "\xE2\x84\xAD" => "\x63", - "\xE2\x84\xB0" => "\x65", - "\xE2\x84\xB1" => "\x66", - "\xE2\x84\xB3" => "\x6D", - "\xE2\x84\xBB" => "\x66\x61\x78", - "\xE2\x84\xBE" => "\xCE\xB3", - "\xE2\x84\xBF" => "\xCF\x80", - "\xE2\x85\x85" => "\x64", - "\xE3\x89\x90" => "\x70\x74\x65", - "\xE3\x8B\x8C" => "\x68\x67", - "\xE3\x8B\x8E" => "\x65\x76", - "\xE3\x8B\x8F" => "\x6C\x74\x64", - "\xE3\x8D\xB1" => "\x68\x70\x61", - "\xE3\x8D\xB3" => "\x61\x75", - "\xE3\x8D\xB5" => "\x6F\x76", - "\xE3\x8D\xBA" => "\x69\x75", - "\xE3\x8E\x80" => "\x70\x61", - "\xE3\x8E\x81" => "\x6E\x61", - "\xE3\x8E\x82" => "\xCE\xBC\x61", - "\xE3\x8E\x83" => "\x6D\x61", - "\xE3\x8E\x84" => "\x6B\x61", - "\xE3\x8E\x85" => "\x6B\x62", - "\xE3\x8E\x86" => "\x6D\x62", - "\xE3\x8E\x87" => "\x67\x62", - "\xE3\x8E\x8A" => "\x70\x66", - "\xE3\x8E\x8B" => "\x6E\x66", - "\xE3\x8E\x8C" => "\xCE\xBC\x66", - "\xE3\x8E\x90" => "\x68\x7A", - "\xE3\x8E\x91" => "\x6B\x68\x7A", - "\xE3\x8E\x92" => "\x6D\x68\x7A", - "\xE3\x8E\x93" => "\x67\x68\x7A", - "\xE3\x8E\x94" => "\x74\x68\x7A", - "\xE3\x8E\xA9" => "\x70\x61", - "\xE3\x8E\xAA" => "\x6B\x70\x61", - "\xE3\x8E\xAB" => "\x6D\x70\x61", - "\xE3\x8E\xAC" => "\x67\x70\x61", - "\xE3\x8E\xB4" => "\x70\x76", - "\xE3\x8E\xB5" => "\x6E\x76", - "\xE3\x8E\xB6" => "\xCE\xBC\x76", - "\xE3\x8E\xB7" => "\x6D\x76", - "\xE3\x8E\xB8" => "\x6B\x76", - "\xE3\x8E\xB9" => "\x6D\x76", - "\xE3\x8E\xBA" => "\x70\x77", - "\xE3\x8E\xBB" => "\x6E\x77", - "\xE3\x8E\xBC" => "\xCE\xBC\x77", - "\xE3\x8E\xBD" => "\x6D\x77", - "\xE3\x8E\xBE" => "\x6B\x77", - "\xE3\x8E\xBF" => "\x6D\x77", - "\xE3\x8F\x80" => "\x6B\xCF\x89", - "\xE3\x8F\x81" => "\x6D\xCF\x89", - "\xE3\x8F\x83" => "\x62\x71", - "\xE3\x8F\x86" => "\x63\xE2\x88\x95\x6B\x67", - "\xE3\x8F\x87" => "\x63\x6F\x2E", - "\xE3\x8F\x88" => "\x64\x62", - "\xE3\x8F\x89" => "\x67\x79", - "\xE3\x8F\x8B" => "\x68\x70", - "\xE3\x8F\x8D" => "\x6B\x6B", - "\xE3\x8F\x8E" => "\x6B\x6D", - "\xE3\x8F\x97" => "\x70\x68", - "\xE3\x8F\x99" => "\x70\x70\x6D", - "\xE3\x8F\x9A" => "\x70\x72", - "\xE3\x8F\x9C" => "\x73\x76", - "\xE3\x8F\x9D" => "\x77\x62", - "\xE3\x8F\x9E" => "\x76\xE2\x88\x95\x6D", - "\xE3\x8F\x9F" => "\x61\xE2\x88\x95\x6D", - "\xF0\x9D\x90\x80" => "\x61", - "\xF0\x9D\x90\x81" => "\x62", - "\xF0\x9D\x90\x82" => "\x63", - "\xF0\x9D\x90\x83" => "\x64", - "\xF0\x9D\x90\x84" => "\x65", - "\xF0\x9D\x90\x85" => "\x66", - "\xF0\x9D\x90\x86" => "\x67", - "\xF0\x9D\x90\x87" => "\x68", - "\xF0\x9D\x90\x88" => "\x69", - "\xF0\x9D\x90\x89" => "\x6A", - "\xF0\x9D\x90\x8A" => "\x6B", - "\xF0\x9D\x90\x8B" => "\x6C", - "\xF0\x9D\x90\x8C" => "\x6D", - "\xF0\x9D\x90\x8D" => "\x6E", - "\xF0\x9D\x90\x8E" => "\x6F", - "\xF0\x9D\x90\x8F" => "\x70", - "\xF0\x9D\x90\x90" => "\x71", - "\xF0\x9D\x90\x91" => "\x72", - "\xF0\x9D\x90\x92" => "\x73", - "\xF0\x9D\x90\x93" => "\x74", - "\xF0\x9D\x90\x94" => "\x75", - "\xF0\x9D\x90\x95" => "\x76", - "\xF0\x9D\x90\x96" => "\x77", - "\xF0\x9D\x90\x97" => "\x78", - "\xF0\x9D\x90\x98" => "\x79", - "\xF0\x9D\x90\x99" => "\x7A", - "\xF0\x9D\x90\xB4" => "\x61", - "\xF0\x9D\x90\xB5" => "\x62", - "\xF0\x9D\x90\xB6" => "\x63", - "\xF0\x9D\x90\xB7" => "\x64", - "\xF0\x9D\x90\xB8" => "\x65", - "\xF0\x9D\x90\xB9" => "\x66", - "\xF0\x9D\x90\xBA" => "\x67", - "\xF0\x9D\x90\xBB" => "\x68", - "\xF0\x9D\x90\xBC" => "\x69", - "\xF0\x9D\x90\xBD" => "\x6A", - "\xF0\x9D\x90\xBE" => "\x6B", - "\xF0\x9D\x90\xBF" => "\x6C", - "\xF0\x9D\x91\x80" => "\x6D", - "\xF0\x9D\x91\x81" => "\x6E", - "\xF0\x9D\x91\x82" => "\x6F", - "\xF0\x9D\x91\x83" => "\x70", - "\xF0\x9D\x91\x84" => "\x71", - "\xF0\x9D\x91\x85" => "\x72", - "\xF0\x9D\x91\x86" => "\x73", - "\xF0\x9D\x91\x87" => "\x74", - "\xF0\x9D\x91\x88" => "\x75", - "\xF0\x9D\x91\x89" => "\x76", - "\xF0\x9D\x91\x8A" => "\x77", - "\xF0\x9D\x91\x8B" => "\x78", - "\xF0\x9D\x91\x8C" => "\x79", - "\xF0\x9D\x91\x8D" => "\x7A", - "\xF0\x9D\x91\xA8" => "\x61", - "\xF0\x9D\x91\xA9" => "\x62", - "\xF0\x9D\x91\xAA" => "\x63", - "\xF0\x9D\x91\xAB" => "\x64", - "\xF0\x9D\x91\xAC" => "\x65", - "\xF0\x9D\x91\xAD" => "\x66", - "\xF0\x9D\x91\xAE" => "\x67", - "\xF0\x9D\x91\xAF" => "\x68", - "\xF0\x9D\x91\xB0" => "\x69", - "\xF0\x9D\x91\xB1" => "\x6A", - "\xF0\x9D\x91\xB2" => "\x6B", - "\xF0\x9D\x91\xB3" => "\x6C", - "\xF0\x9D\x91\xB4" => "\x6D", - "\xF0\x9D\x91\xB5" => "\x6E", - "\xF0\x9D\x91\xB6" => "\x6F", - "\xF0\x9D\x91\xB7" => "\x70", - "\xF0\x9D\x91\xB8" => "\x71", - "\xF0\x9D\x91\xB9" => "\x72", - "\xF0\x9D\x91\xBA" => "\x73", - "\xF0\x9D\x91\xBB" => "\x74", - "\xF0\x9D\x91\xBC" => "\x75", - "\xF0\x9D\x91\xBD" => "\x76", - "\xF0\x9D\x91\xBE" => "\x77", - "\xF0\x9D\x91\xBF" => "\x78", - "\xF0\x9D\x92\x80" => "\x79", - "\xF0\x9D\x92\x81" => "\x7A", - "\xF0\x9D\x92\x9C" => "\x61", - "\xF0\x9D\x92\x9E" => "\x63", - "\xF0\x9D\x92\x9F" => "\x64", - "\xF0\x9D\x92\xA2" => "\x67", - "\xF0\x9D\x92\xA5" => "\x6A", - "\xF0\x9D\x92\xA6" => "\x6B", - "\xF0\x9D\x92\xA9" => "\x6E", - "\xF0\x9D\x92\xAA" => "\x6F", - "\xF0\x9D\x92\xAB" => "\x70", - "\xF0\x9D\x92\xAC" => "\x71", - "\xF0\x9D\x92\xAE" => "\x73", - "\xF0\x9D\x92\xAF" => "\x74", - "\xF0\x9D\x92\xB0" => "\x75", - "\xF0\x9D\x92\xB1" => "\x76", - "\xF0\x9D\x92\xB2" => "\x77", - "\xF0\x9D\x92\xB3" => "\x78", - "\xF0\x9D\x92\xB4" => "\x79", - "\xF0\x9D\x92\xB5" => "\x7A", - "\xF0\x9D\x93\x90" => "\x61", - "\xF0\x9D\x93\x91" => "\x62", - "\xF0\x9D\x93\x92" => "\x63", - "\xF0\x9D\x93\x93" => "\x64", - "\xF0\x9D\x93\x94" => "\x65", - "\xF0\x9D\x93\x95" => "\x66", - "\xF0\x9D\x93\x96" => "\x67", - "\xF0\x9D\x93\x97" => "\x68", - "\xF0\x9D\x93\x98" => "\x69", - "\xF0\x9D\x93\x99" => "\x6A", - "\xF0\x9D\x93\x9A" => "\x6B", - "\xF0\x9D\x93\x9B" => "\x6C", - "\xF0\x9D\x93\x9C" => "\x6D", - "\xF0\x9D\x93\x9D" => "\x6E", - "\xF0\x9D\x93\x9E" => "\x6F", - "\xF0\x9D\x93\x9F" => "\x70", - "\xF0\x9D\x93\xA0" => "\x71", - "\xF0\x9D\x93\xA1" => "\x72", - "\xF0\x9D\x93\xA2" => "\x73", - "\xF0\x9D\x93\xA3" => "\x74", - "\xF0\x9D\x93\xA4" => "\x75", - "\xF0\x9D\x93\xA5" => "\x76", - "\xF0\x9D\x93\xA6" => "\x77", - "\xF0\x9D\x93\xA7" => "\x78", - "\xF0\x9D\x93\xA8" => "\x79", - "\xF0\x9D\x93\xA9" => "\x7A", - "\xF0\x9D\x94\x84" => "\x61", - "\xF0\x9D\x94\x85" => "\x62", - "\xF0\x9D\x94\x87" => "\x64", - "\xF0\x9D\x94\x88" => "\x65", - "\xF0\x9D\x94\x89" => "\x66", - "\xF0\x9D\x94\x8A" => "\x67", - "\xF0\x9D\x94\x8D" => "\x6A", - "\xF0\x9D\x94\x8E" => "\x6B", - "\xF0\x9D\x94\x8F" => "\x6C", - "\xF0\x9D\x94\x90" => "\x6D", - "\xF0\x9D\x94\x91" => "\x6E", - "\xF0\x9D\x94\x92" => "\x6F", - "\xF0\x9D\x94\x93" => "\x70", - "\xF0\x9D\x94\x94" => "\x71", - "\xF0\x9D\x94\x96" => "\x73", - "\xF0\x9D\x94\x97" => "\x74", - "\xF0\x9D\x94\x98" => "\x75", - "\xF0\x9D\x94\x99" => "\x76", - "\xF0\x9D\x94\x9A" => "\x77", - "\xF0\x9D\x94\x9B" => "\x78", - "\xF0\x9D\x94\x9C" => "\x79", - "\xF0\x9D\x94\xB8" => "\x61", - "\xF0\x9D\x94\xB9" => "\x62", - "\xF0\x9D\x94\xBB" => "\x64", - "\xF0\x9D\x94\xBC" => "\x65", - "\xF0\x9D\x94\xBD" => "\x66", - "\xF0\x9D\x94\xBE" => "\x67", - "\xF0\x9D\x95\x80" => "\x69", - "\xF0\x9D\x95\x81" => "\x6A", - "\xF0\x9D\x95\x82" => "\x6B", - "\xF0\x9D\x95\x83" => "\x6C", - "\xF0\x9D\x95\x84" => "\x6D", - "\xF0\x9D\x95\x86" => "\x6F", - "\xF0\x9D\x95\x8A" => "\x73", - "\xF0\x9D\x95\x8B" => "\x74", - "\xF0\x9D\x95\x8C" => "\x75", - "\xF0\x9D\x95\x8D" => "\x76", - "\xF0\x9D\x95\x8E" => "\x77", - "\xF0\x9D\x95\x8F" => "\x78", - "\xF0\x9D\x95\x90" => "\x79", - "\xF0\x9D\x95\xAC" => "\x61", - "\xF0\x9D\x95\xAD" => "\x62", - "\xF0\x9D\x95\xAE" => "\x63", - "\xF0\x9D\x95\xAF" => "\x64", - "\xF0\x9D\x95\xB0" => "\x65", - "\xF0\x9D\x95\xB1" => "\x66", - "\xF0\x9D\x95\xB2" => "\x67", - "\xF0\x9D\x95\xB3" => "\x68", - "\xF0\x9D\x95\xB4" => "\x69", - "\xF0\x9D\x95\xB5" => "\x6A", - "\xF0\x9D\x95\xB6" => "\x6B", - "\xF0\x9D\x95\xB7" => "\x6C", - "\xF0\x9D\x95\xB8" => "\x6D", - "\xF0\x9D\x95\xB9" => "\x6E", - "\xF0\x9D\x95\xBA" => "\x6F", - "\xF0\x9D\x95\xBB" => "\x70", - "\xF0\x9D\x95\xBC" => "\x71", - "\xF0\x9D\x95\xBD" => "\x72", - "\xF0\x9D\x95\xBE" => "\x73", - "\xF0\x9D\x95\xBF" => "\x74", - "\xF0\x9D\x96\x80" => "\x75", - "\xF0\x9D\x96\x81" => "\x76", - "\xF0\x9D\x96\x82" => "\x77", - "\xF0\x9D\x96\x83" => "\x78", - "\xF0\x9D\x96\x84" => "\x79", - "\xF0\x9D\x96\x85" => "\x7A", - "\xF0\x9D\x96\xA0" => "\x61", - "\xF0\x9D\x96\xA1" => "\x62", - "\xF0\x9D\x96\xA2" => "\x63", - "\xF0\x9D\x96\xA3" => "\x64", - "\xF0\x9D\x96\xA4" => "\x65", - "\xF0\x9D\x96\xA5" => "\x66", - "\xF0\x9D\x96\xA6" => "\x67", - "\xF0\x9D\x96\xA7" => "\x68", - "\xF0\x9D\x96\xA8" => "\x69", - "\xF0\x9D\x96\xA9" => "\x6A", - "\xF0\x9D\x96\xAA" => "\x6B", - "\xF0\x9D\x96\xAB" => "\x6C", - "\xF0\x9D\x96\xAC" => "\x6D", - "\xF0\x9D\x96\xAD" => "\x6E", - "\xF0\x9D\x96\xAE" => "\x6F", - "\xF0\x9D\x96\xAF" => "\x70", - "\xF0\x9D\x96\xB0" => "\x71", - "\xF0\x9D\x96\xB1" => "\x72", - "\xF0\x9D\x96\xB2" => "\x73", - "\xF0\x9D\x96\xB3" => "\x74", - "\xF0\x9D\x96\xB4" => "\x75", - "\xF0\x9D\x96\xB5" => "\x76", - "\xF0\x9D\x96\xB6" => "\x77", - "\xF0\x9D\x96\xB7" => "\x78", - "\xF0\x9D\x96\xB8" => "\x79", - "\xF0\x9D\x96\xB9" => "\x7A", - "\xF0\x9D\x97\x94" => "\x61", - "\xF0\x9D\x97\x95" => "\x62", - "\xF0\x9D\x97\x96" => "\x63", - "\xF0\x9D\x97\x97" => "\x64", - "\xF0\x9D\x97\x98" => "\x65", - "\xF0\x9D\x97\x99" => "\x66", - "\xF0\x9D\x97\x9A" => "\x67", - "\xF0\x9D\x97\x9B" => "\x68", - "\xF0\x9D\x97\x9C" => "\x69", - "\xF0\x9D\x97\x9D" => "\x6A", - "\xF0\x9D\x97\x9E" => "\x6B", - "\xF0\x9D\x97\x9F" => "\x6C", - "\xF0\x9D\x97\xA0" => "\x6D", - "\xF0\x9D\x97\xA1" => "\x6E", - "\xF0\x9D\x97\xA2" => "\x6F", - "\xF0\x9D\x97\xA3" => "\x70", - "\xF0\x9D\x97\xA4" => "\x71", - "\xF0\x9D\x97\xA5" => "\x72", - "\xF0\x9D\x97\xA6" => "\x73", - "\xF0\x9D\x97\xA7" => "\x74", - "\xF0\x9D\x97\xA8" => "\x75", - "\xF0\x9D\x97\xA9" => "\x76", - "\xF0\x9D\x97\xAA" => "\x77", - "\xF0\x9D\x97\xAB" => "\x78", - "\xF0\x9D\x97\xAC" => "\x79", - "\xF0\x9D\x97\xAD" => "\x7A", - "\xF0\x9D\x98\x88" => "\x61", - "\xF0\x9D\x98\x89" => "\x62", - "\xF0\x9D\x98\x8A" => "\x63", - "\xF0\x9D\x98\x8B" => "\x64", - "\xF0\x9D\x98\x8C" => "\x65", - "\xF0\x9D\x98\x8D" => "\x66", - "\xF0\x9D\x98\x8E" => "\x67", - "\xF0\x9D\x98\x8F" => "\x68", - "\xF0\x9D\x98\x90" => "\x69", - "\xF0\x9D\x98\x91" => "\x6A", - "\xF0\x9D\x98\x92" => "\x6B", - "\xF0\x9D\x98\x93" => "\x6C", - "\xF0\x9D\x98\x94" => "\x6D", - "\xF0\x9D\x98\x95" => "\x6E", - "\xF0\x9D\x98\x96" => "\x6F", - "\xF0\x9D\x98\x97" => "\x70", - "\xF0\x9D\x98\x98" => "\x71", - "\xF0\x9D\x98\x99" => "\x72", - "\xF0\x9D\x98\x9A" => "\x73", - "\xF0\x9D\x98\x9B" => "\x74", - "\xF0\x9D\x98\x9C" => "\x75", - "\xF0\x9D\x98\x9D" => "\x76", - "\xF0\x9D\x98\x9E" => "\x77", - "\xF0\x9D\x98\x9F" => "\x78", - "\xF0\x9D\x98\xA0" => "\x79", - "\xF0\x9D\x98\xA1" => "\x7A", - "\xF0\x9D\x98\xBC" => "\x61", - "\xF0\x9D\x98\xBD" => "\x62", - "\xF0\x9D\x98\xBE" => "\x63", - "\xF0\x9D\x98\xBF" => "\x64", - "\xF0\x9D\x99\x80" => "\x65", - "\xF0\x9D\x99\x81" => "\x66", - "\xF0\x9D\x99\x82" => "\x67", - "\xF0\x9D\x99\x83" => "\x68", - "\xF0\x9D\x99\x84" => "\x69", - "\xF0\x9D\x99\x85" => "\x6A", - "\xF0\x9D\x99\x86" => "\x6B", - "\xF0\x9D\x99\x87" => "\x6C", - "\xF0\x9D\x99\x88" => "\x6D", - "\xF0\x9D\x99\x89" => "\x6E", - "\xF0\x9D\x99\x8A" => "\x6F", - "\xF0\x9D\x99\x8B" => "\x70", - "\xF0\x9D\x99\x8C" => "\x71", - "\xF0\x9D\x99\x8D" => "\x72", - "\xF0\x9D\x99\x8E" => "\x73", - "\xF0\x9D\x99\x8F" => "\x74", - "\xF0\x9D\x99\x90" => "\x75", - "\xF0\x9D\x99\x91" => "\x76", - "\xF0\x9D\x99\x92" => "\x77", - "\xF0\x9D\x99\x93" => "\x78", - "\xF0\x9D\x99\x94" => "\x79", - "\xF0\x9D\x99\x95" => "\x7A", - "\xF0\x9D\x99\xB0" => "\x61", - "\xF0\x9D\x99\xB1" => "\x62", - "\xF0\x9D\x99\xB2" => "\x63", - "\xF0\x9D\x99\xB3" => "\x64", - "\xF0\x9D\x99\xB4" => "\x65", - "\xF0\x9D\x99\xB5" => "\x66", - "\xF0\x9D\x99\xB6" => "\x67", - "\xF0\x9D\x99\xB7" => "\x68", - "\xF0\x9D\x99\xB8" => "\x69", - "\xF0\x9D\x99\xB9" => "\x6A", - "\xF0\x9D\x99\xBA" => "\x6B", - "\xF0\x9D\x99\xBB" => "\x6C", - "\xF0\x9D\x99\xBC" => "\x6D", - "\xF0\x9D\x99\xBD" => "\x6E", - "\xF0\x9D\x99\xBE" => "\x6F", - "\xF0\x9D\x99\xBF" => "\x70", - "\xF0\x9D\x9A\x80" => "\x71", - "\xF0\x9D\x9A\x81" => "\x72", - "\xF0\x9D\x9A\x82" => "\x73", - "\xF0\x9D\x9A\x83" => "\x74", - "\xF0\x9D\x9A\x84" => "\x75", - "\xF0\x9D\x9A\x85" => "\x76", - "\xF0\x9D\x9A\x86" => "\x77", - "\xF0\x9D\x9A\x87" => "\x78", - "\xF0\x9D\x9A\x88" => "\x79", - "\xF0\x9D\x9A\x89" => "\x7A", - "\xF0\x9D\x9A\xA8" => "\xCE\xB1", - "\xF0\x9D\x9A\xA9" => "\xCE\xB2", - "\xF0\x9D\x9A\xAA" => "\xCE\xB3", - "\xF0\x9D\x9A\xAB" => "\xCE\xB4", - "\xF0\x9D\x9A\xAC" => "\xCE\xB5", - "\xF0\x9D\x9A\xAD" => "\xCE\xB6", - "\xF0\x9D\x9A\xAE" => "\xCE\xB7", - "\xF0\x9D\x9A\xAF" => "\xCE\xB8", - "\xF0\x9D\x9A\xB0" => "\xCE\xB9", - "\xF0\x9D\x9A\xB1" => "\xCE\xBA", - "\xF0\x9D\x9A\xB2" => "\xCE\xBB", - "\xF0\x9D\x9A\xB3" => "\xCE\xBC", - "\xF0\x9D\x9A\xB4" => "\xCE\xBD", - "\xF0\x9D\x9A\xB5" => "\xCE\xBE", - "\xF0\x9D\x9A\xB6" => "\xCE\xBF", - "\xF0\x9D\x9A\xB7" => "\xCF\x80", - "\xF0\x9D\x9A\xB8" => "\xCF\x81", - "\xF0\x9D\x9A\xB9" => "\xCE\xB8", - "\xF0\x9D\x9A\xBA" => "\xCF\x83", - "\xF0\x9D\x9A\xBB" => "\xCF\x84", - "\xF0\x9D\x9A\xBC" => "\xCF\x85", - "\xF0\x9D\x9A\xBD" => "\xCF\x86", - "\xF0\x9D\x9A\xBE" => "\xCF\x87", - "\xF0\x9D\x9A\xBF" => "\xCF\x88", - "\xF0\x9D\x9B\x80" => "\xCF\x89", - "\xF0\x9D\x9B\x93" => "\xCF\x83", - "\xF0\x9D\x9B\xA2" => "\xCE\xB1", - "\xF0\x9D\x9B\xA3" => "\xCE\xB2", - "\xF0\x9D\x9B\xA4" => "\xCE\xB3", - "\xF0\x9D\x9B\xA5" => "\xCE\xB4", - "\xF0\x9D\x9B\xA6" => "\xCE\xB5", - "\xF0\x9D\x9B\xA7" => "\xCE\xB6", - "\xF0\x9D\x9B\xA8" => "\xCE\xB7", - "\xF0\x9D\x9B\xA9" => "\xCE\xB8", - "\xF0\x9D\x9B\xAA" => "\xCE\xB9", - "\xF0\x9D\x9B\xAB" => "\xCE\xBA", - "\xF0\x9D\x9B\xAC" => "\xCE\xBB", - "\xF0\x9D\x9B\xAD" => "\xCE\xBC", - "\xF0\x9D\x9B\xAE" => "\xCE\xBD", - "\xF0\x9D\x9B\xAF" => "\xCE\xBE", - "\xF0\x9D\x9B\xB0" => "\xCE\xBF", - "\xF0\x9D\x9B\xB1" => "\xCF\x80", - "\xF0\x9D\x9B\xB2" => "\xCF\x81", - "\xF0\x9D\x9B\xB3" => "\xCE\xB8", - "\xF0\x9D\x9B\xB4" => "\xCF\x83", - "\xF0\x9D\x9B\xB5" => "\xCF\x84", - "\xF0\x9D\x9B\xB6" => "\xCF\x85", - "\xF0\x9D\x9B\xB7" => "\xCF\x86", - "\xF0\x9D\x9B\xB8" => "\xCF\x87", - "\xF0\x9D\x9B\xB9" => "\xCF\x88", - "\xF0\x9D\x9B\xBA" => "\xCF\x89", - "\xF0\x9D\x9C\x8D" => "\xCF\x83", - "\xF0\x9D\x9C\x9C" => "\xCE\xB1", - "\xF0\x9D\x9C\x9D" => "\xCE\xB2", - "\xF0\x9D\x9C\x9E" => "\xCE\xB3", - "\xF0\x9D\x9C\x9F" => "\xCE\xB4", - "\xF0\x9D\x9C\xA0" => "\xCE\xB5", - "\xF0\x9D\x9C\xA1" => "\xCE\xB6", - "\xF0\x9D\x9C\xA2" => "\xCE\xB7", - "\xF0\x9D\x9C\xA3" => "\xCE\xB8", - "\xF0\x9D\x9C\xA4" => "\xCE\xB9", - "\xF0\x9D\x9C\xA5" => "\xCE\xBA", - "\xF0\x9D\x9C\xA6" => "\xCE\xBB", - "\xF0\x9D\x9C\xA7" => "\xCE\xBC", - "\xF0\x9D\x9C\xA8" => "\xCE\xBD", - "\xF0\x9D\x9C\xA9" => "\xCE\xBE", - "\xF0\x9D\x9C\xAA" => "\xCE\xBF", - "\xF0\x9D\x9C\xAB" => "\xCF\x80", - "\xF0\x9D\x9C\xAC" => "\xCF\x81", - "\xF0\x9D\x9C\xAD" => "\xCE\xB8", - "\xF0\x9D\x9C\xAE" => "\xCF\x83", - "\xF0\x9D\x9C\xAF" => "\xCF\x84", - "\xF0\x9D\x9C\xB0" => "\xCF\x85", - "\xF0\x9D\x9C\xB1" => "\xCF\x86", - "\xF0\x9D\x9C\xB2" => "\xCF\x87", - "\xF0\x9D\x9C\xB3" => "\xCF\x88", - "\xF0\x9D\x9C\xB4" => "\xCF\x89", - "\xF0\x9D\x9D\x87" => "\xCF\x83", - "\xF0\x9D\x9D\x96" => "\xCE\xB1", - "\xF0\x9D\x9D\x97" => "\xCE\xB2", - "\xF0\x9D\x9D\x98" => "\xCE\xB3", - "\xF0\x9D\x9D\x99" => "\xCE\xB4", - "\xF0\x9D\x9D\x9A" => "\xCE\xB5", - "\xF0\x9D\x9D\x9B" => "\xCE\xB6", - "\xF0\x9D\x9D\x9C" => "\xCE\xB7", - "\xF0\x9D\x9D\x9D" => "\xCE\xB8", - "\xF0\x9D\x9D\x9E" => "\xCE\xB9", - "\xF0\x9D\x9D\x9F" => "\xCE\xBA", - "\xF0\x9D\x9D\xA0" => "\xCE\xBB", - "\xF0\x9D\x9D\xA1" => "\xCE\xBC", - "\xF0\x9D\x9D\xA2" => "\xCE\xBD", - "\xF0\x9D\x9D\xA3" => "\xCE\xBE", - "\xF0\x9D\x9D\xA4" => "\xCE\xBF", - "\xF0\x9D\x9D\xA5" => "\xCF\x80", - "\xF0\x9D\x9D\xA6" => "\xCF\x81", - "\xF0\x9D\x9D\xA7" => "\xCE\xB8", - "\xF0\x9D\x9D\xA8" => "\xCF\x83", - "\xF0\x9D\x9D\xA9" => "\xCF\x84", - "\xF0\x9D\x9D\xAA" => "\xCF\x85", - "\xF0\x9D\x9D\xAB" => "\xCF\x86", - "\xF0\x9D\x9D\xAC" => "\xCF\x87", - "\xF0\x9D\x9D\xAD" => "\xCF\x88", - "\xF0\x9D\x9D\xAE" => "\xCF\x89", - "\xF0\x9D\x9E\x81" => "\xCF\x83", - "\xF0\x9D\x9E\x90" => "\xCE\xB1", - "\xF0\x9D\x9E\x91" => "\xCE\xB2", - "\xF0\x9D\x9E\x92" => "\xCE\xB3", - "\xF0\x9D\x9E\x93" => "\xCE\xB4", - "\xF0\x9D\x9E\x94" => "\xCE\xB5", - "\xF0\x9D\x9E\x95" => "\xCE\xB6", - "\xF0\x9D\x9E\x96" => "\xCE\xB7", - "\xF0\x9D\x9E\x97" => "\xCE\xB8", - "\xF0\x9D\x9E\x98" => "\xCE\xB9", - "\xF0\x9D\x9E\x99" => "\xCE\xBA", - "\xF0\x9D\x9E\x9A" => "\xCE\xBB", - "\xF0\x9D\x9E\x9B" => "\xCE\xBC", - "\xF0\x9D\x9E\x9C" => "\xCE\xBD", - "\xF0\x9D\x9E\x9D" => "\xCE\xBE", - "\xF0\x9D\x9E\x9E" => "\xCE\xBF", - "\xF0\x9D\x9E\x9F" => "\xCF\x80", - "\xF0\x9D\x9E\xA0" => "\xCF\x81", - "\xF0\x9D\x9E\xA1" => "\xCE\xB8", - "\xF0\x9D\x9E\xA2" => "\xCF\x83", - "\xF0\x9D\x9E\xA3" => "\xCF\x84", - "\xF0\x9D\x9E\xA4" => "\xCF\x85", - "\xF0\x9D\x9E\xA5" => "\xCF\x86", - "\xF0\x9D\x9E\xA6" => "\xCF\x87", - "\xF0\x9D\x9E\xA7" => "\xCF\x88", - "\xF0\x9D\x9E\xA8" => "\xCF\x89", - "\xF0\x9D\x9E\xBB" => "\xCF\x83", - "\xF0\x9D\x9F\x8A" => "\xCF\x9D", - ); - - // do the case fold - $text = utf8_case_fold($text, $option); - - if (!class_exists('utf_normalizer')) - { - include(PHPBB_ROOT_PATH . 'includes/utf/utf_normalizer.' . PHP_EXT); - } - - // convert to NFKC - utf_normalizer::nfkc($text); - - // FC_NFKC_Closure, http://www.unicode.org/Public/5.0.0/ucd/DerivedNormalizationProps.txt - $text = strtr($text, $fc_nfkc_closure); - - return $text; -} - -/** -* Assume the input is NFC: -* Takes the input and does a "special" case fold. It does minor normalization as well. -* -* @param string $text text to be case folded -* @param string $option determines how we will fold the cases -* @return string case folded text -*/ -function utf8_case_fold_nfc($text, $option = 'full') -{ - static $uniarray = array(); - static $ypogegrammeni = array( - "\xCD\xBA" => "\x20\xCD\x85", - "\xE1\xBE\x80" => "\xE1\xBC\x80\xCD\x85", - "\xE1\xBE\x81" => "\xE1\xBC\x81\xCD\x85", - "\xE1\xBE\x82" => "\xE1\xBC\x82\xCD\x85", - "\xE1\xBE\x83" => "\xE1\xBC\x83\xCD\x85", - "\xE1\xBE\x84" => "\xE1\xBC\x84\xCD\x85", - "\xE1\xBE\x85" => "\xE1\xBC\x85\xCD\x85", - "\xE1\xBE\x86" => "\xE1\xBC\x86\xCD\x85", - "\xE1\xBE\x87" => "\xE1\xBC\x87\xCD\x85", - "\xE1\xBE\x88" => "\xE1\xBC\x88\xCD\x85", - "\xE1\xBE\x89" => "\xE1\xBC\x89\xCD\x85", - "\xE1\xBE\x8A" => "\xE1\xBC\x8A\xCD\x85", - "\xE1\xBE\x8B" => "\xE1\xBC\x8B\xCD\x85", - "\xE1\xBE\x8C" => "\xE1\xBC\x8C\xCD\x85", - "\xE1\xBE\x8D" => "\xE1\xBC\x8D\xCD\x85", - "\xE1\xBE\x8E" => "\xE1\xBC\x8E\xCD\x85", - "\xE1\xBE\x8F" => "\xE1\xBC\x8F\xCD\x85", - "\xE1\xBE\x90" => "\xE1\xBC\xA0\xCD\x85", - "\xE1\xBE\x91" => "\xE1\xBC\xA1\xCD\x85", - "\xE1\xBE\x92" => "\xE1\xBC\xA2\xCD\x85", - "\xE1\xBE\x93" => "\xE1\xBC\xA3\xCD\x85", - "\xE1\xBE\x94" => "\xE1\xBC\xA4\xCD\x85", - "\xE1\xBE\x95" => "\xE1\xBC\xA5\xCD\x85", - "\xE1\xBE\x96" => "\xE1\xBC\xA6\xCD\x85", - "\xE1\xBE\x97" => "\xE1\xBC\xA7\xCD\x85", - "\xE1\xBE\x98" => "\xE1\xBC\xA8\xCD\x85", - "\xE1\xBE\x99" => "\xE1\xBC\xA9\xCD\x85", - "\xE1\xBE\x9A" => "\xE1\xBC\xAA\xCD\x85", - "\xE1\xBE\x9B" => "\xE1\xBC\xAB\xCD\x85", - "\xE1\xBE\x9C" => "\xE1\xBC\xAC\xCD\x85", - "\xE1\xBE\x9D" => "\xE1\xBC\xAD\xCD\x85", - "\xE1\xBE\x9E" => "\xE1\xBC\xAE\xCD\x85", - "\xE1\xBE\x9F" => "\xE1\xBC\xAF\xCD\x85", - "\xE1\xBE\xA0" => "\xE1\xBD\xA0\xCD\x85", - "\xE1\xBE\xA1" => "\xE1\xBD\xA1\xCD\x85", - "\xE1\xBE\xA2" => "\xE1\xBD\xA2\xCD\x85", - "\xE1\xBE\xA3" => "\xE1\xBD\xA3\xCD\x85", - "\xE1\xBE\xA4" => "\xE1\xBD\xA4\xCD\x85", - "\xE1\xBE\xA5" => "\xE1\xBD\xA5\xCD\x85", - "\xE1\xBE\xA6" => "\xE1\xBD\xA6\xCD\x85", - "\xE1\xBE\xA7" => "\xE1\xBD\xA7\xCD\x85", - "\xE1\xBE\xA8" => "\xE1\xBD\xA8\xCD\x85", - "\xE1\xBE\xA9" => "\xE1\xBD\xA9\xCD\x85", - "\xE1\xBE\xAA" => "\xE1\xBD\xAA\xCD\x85", - "\xE1\xBE\xAB" => "\xE1\xBD\xAB\xCD\x85", - "\xE1\xBE\xAC" => "\xE1\xBD\xAC\xCD\x85", - "\xE1\xBE\xAD" => "\xE1\xBD\xAD\xCD\x85", - "\xE1\xBE\xAE" => "\xE1\xBD\xAE\xCD\x85", - "\xE1\xBE\xAF" => "\xE1\xBD\xAF\xCD\x85", - "\xE1\xBE\xB2" => "\xE1\xBD\xB0\xCD\x85", - "\xE1\xBE\xB3" => "\xCE\xB1\xCD\x85", - "\xE1\xBE\xB4" => "\xCE\xAC\xCD\x85", - "\xE1\xBE\xB7" => "\xE1\xBE\xB6\xCD\x85", - "\xE1\xBE\xBC" => "\xCE\x91\xCD\x85", - "\xE1\xBF\x82" => "\xE1\xBD\xB4\xCD\x85", - "\xE1\xBF\x83" => "\xCE\xB7\xCD\x85", - "\xE1\xBF\x84" => "\xCE\xAE\xCD\x85", - "\xE1\xBF\x87" => "\xE1\xBF\x86\xCD\x85", - "\xE1\xBF\x8C" => "\xCE\x97\xCD\x85", - "\xE1\xBF\xB2" => "\xE1\xBD\xBC\xCD\x85", - "\xE1\xBF\xB3" => "\xCF\x89\xCD\x85", - "\xE1\xBF\xB4" => "\xCF\x8E\xCD\x85", - "\xE1\xBF\xB7" => "\xE1\xBF\xB6\xCD\x85", - "\xE1\xBF\xBC" => "\xCE\xA9\xCD\x85", - ); - - // perform a small trick, avoid further normalization on composed points that contain U+0345 in their decomposition - $text = strtr($text, $ypogegrammeni); - - // do the case fold - $text = utf8_case_fold($text, $option); - - return $text; -} - -/** -* A wrapper function for the normalizer which takes care of including the class if required and modifies the passed strings -* to be in NFC (Normalization Form Composition). -* -* @todo allow arbitrary array depth -* -* @param mixed $strings a string or an array of strings to normalize -* @return mixed the normalized content, preserving array keys if array given. -*/ -function utf8_normalize_nfc($strings) -{ - if (empty($strings)) - { - return $strings; - } - - if (!class_exists('utf_normalizer')) - { - include(PHPBB_ROOT_PATH . 'includes/utf/utf_normalizer.' . PHP_EXT); - } - - if (!is_array($strings)) - { - utf_normalizer::nfc($strings); - } - else if (is_array($strings)) - { - foreach ($strings as $key => $string) - { - if (is_array($string)) - { - foreach ($string as $_key => $_string) - { - utf_normalizer::nfc($strings[$key][$_key]); - } - } - else - { - utf_normalizer::nfc($strings[$key]); - } - } - } - - return $strings; -} - -/** -* This function is used to generate a "clean" version of a string. -* Clean means that it is a case insensitive form (case folding) and that it is normalized (NFC). -* Additionally a homographs of one character are transformed into one specific character (preferably ASCII -* if it is an ASCII character). -* -* Please be aware that if you change something within this function or within -* functions used here you need to rebuild/update the username_clean column in the users table. And all other -* columns that store a clean string otherwise you will break this functionality. -* -* @param string $text An unclean string, mabye user input (has to be valid UTF-8!) -* @return string Cleaned up version of the input string -*/ -function utf8_clean_string($text) -{ - static $homographs = array(); - - if (empty($homographs)) - { - $homographs = include(PHPBB_ROOT_PATH . 'includes/utf/data/confusables.' . PHP_EXT); - } - - $text = utf8_case_fold_nfkc($text); - $text = strtr($text, $homographs); - // Other control characters - $text = preg_replace('#[\x00-\x1F\x7F]+|(?:\xC2[\x80-\x9F])+#', '', $text); - - // we need to reduce multiple spaces to a single one - $text = preg_replace('# {2,}#', ' ', $text); - - // we can use trim here as all the other space characters should have been turned - // into normal ASCII spaces by now - return trim($text); -} - -/** -* A wrapper for htmlspecialchars($value, ENT_COMPAT, 'UTF-8') -*/ -function utf8_htmlspecialchars($value) -{ - return htmlspecialchars($value, ENT_COMPAT, 'UTF-8'); -} - -/** -* Trying to convert returned system message to utf8 -* -* PHP assumes such messages are ISO-8859-1 so we'll do that too -* and if it breaks messages we'll blame it on them ;-) -*/ -function utf8_convert_message($message) -{ - // First of all check if conversion is neded at all, as there is no point - // in converting ASCII messages from ISO-8859-1 to UTF-8 - if (!preg_match('/[\x80-\xFF]/', $message)) - { - return utf8_htmlspecialchars($message); - } - - // else we need to convert some part of the message - return utf8_htmlspecialchars(utf8_encode($message)); -} - -/** -* UTF8-compatible wordwrap replacement -* -* @param string $string The input string -* @param int $width The column width. Defaults to 75. -* @param string $break The line is broken using the optional break parameter. Defaults to '\n'. -* @param bool $cut If the cut is set to TRUE, the string is always wrapped at the specified width. So if you have a word that is larger than the given width, it is broken apart. -* -* @return string the given string wrapped at the specified column. -* -*/ -function utf8_wordwrap($string, $width = 75, $break = "\n", $cut = false) -{ - // We first need to explode on $break, not destroying existing (intended) breaks - $lines = explode($break, $string); - $new_lines = array(0 => ''); - $index = 0; - - foreach ($lines as $line) - { - $words = explode(' ', $line); - - for ($i = 0, $size = sizeof($words); $i < $size; $i++) - { - $word = $words[$i]; - - // If cut is true we need to cut the word if it is > width chars - if ($cut && utf8_strlen($word) > $width) - { - $words[$i] = utf8_substr($word, $width); - $word = utf8_substr($word, 0, $width); - $i--; - } - - if (utf8_strlen($new_lines[$index] . $word) > $width) - { - $new_lines[$index] = substr($new_lines[$index], 0, -1); - $index++; - $new_lines[$index] = ''; - } - - $new_lines[$index] .= $word . ' '; - } - - $new_lines[$index] = substr($new_lines[$index], 0, -1); - $index++; - $new_lines[$index] = ''; - } - - unset($new_lines[$index]); - return implode($break, $new_lines); -} - -?>
\ No newline at end of file |